Annotation of XNU/libkern/gen/OSAtomicOperations.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: 
        !            23: #include <libkern/OSAtomic.h>
        !            24: 
        !            25: enum {
        !            26:        false   = 0,
        !            27:        true    = 1
        !            28: };
        !            29: #define        NULL 0L
        !            30: 
        !            31: 
        !            32: /*
        !            33:  * atomic operations
        !            34:  *     these are _the_ atomic operations, currently cast atop CompareAndSwap,
        !            35:  *     which is implemented in assembler.  if we are worried about the cost of
        !            36:  *     this layering (we shouldn't be), then all this stuff could be
        !            37:  *     implemented in assembler, as it is in MacOS8/9
        !            38:  *     (derived from SuperMario/NativeLibs/IO/DriverServices/Synchronization.s,
        !            39:  *     which I wrote for NuKernel in a previous life with a different last name...)
        !            40:  *
        !            41:  * native Boolean      CompareAndSwap(UInt32 oldValue, UInt32 newValue, UInt32 * oldValuePtr);
        !            42:  */
        !            43: 
        !            44: #ifndef __ppc__
        !            45: 
        !            46: SInt32 OSAddAtomic(SInt32 amount, SInt32 * value)
        !            47: {
        !            48:        SInt32  oldValue;
        !            49:        SInt32  newValue;
        !            50:        
        !            51:        do {
        !            52:                oldValue = *value;
        !            53:                newValue = oldValue + amount;
        !            54:        } while (! OSCompareAndSwap((UInt32) oldValue, (UInt32) newValue, (UInt32 *) value));
        !            55:        
        !            56:        return oldValue;
        !            57: }
        !            58: 
        !            59: SInt32 OSIncrementAtomic(SInt32 * value)
        !            60: {
        !            61:        return OSAddAtomic(1, value);
        !            62: }
        !            63: 
        !            64: SInt32 OSDecrementAtomic(SInt32 * value)
        !            65: {
        !            66:        return OSAddAtomic(-1, value);
        !            67: }
        !            68: 
        !            69: #endif /* !__ppc__ */
        !            70: 
        !            71: static UInt32  OSBitwiseAtomic(UInt32 and_mask, UInt32 or_mask, UInt32 xor_mask, UInt32 * value)
        !            72: {
        !            73:        UInt32  oldValue;
        !            74:        UInt32  newValue;
        !            75:        
        !            76:        do {
        !            77:                oldValue = *value;
        !            78:                newValue = ((oldValue & and_mask) | or_mask) ^ xor_mask;
        !            79:        } while (! OSCompareAndSwap(oldValue, newValue, value));
        !            80:        
        !            81:        return oldValue;
        !            82: }
        !            83: 
        !            84: UInt32 OSBitAndAtomic(UInt32 mask, UInt32 * value)
        !            85: {
        !            86:        return OSBitwiseAtomic(mask, 0, 0, value);
        !            87: }
        !            88: 
        !            89: UInt32 OSBitOrAtomic(UInt32 mask, UInt32 * value)
        !            90: {
        !            91:        return OSBitwiseAtomic((UInt32) -1, mask, 0, value);
        !            92: }
        !            93: 
        !            94: UInt32 OSBitXorAtomic(UInt32 mask, UInt32 * value)
        !            95: {
        !            96:        return OSBitwiseAtomic((UInt32) -1, 0, mask, value);
        !            97: }
        !            98: 
        !            99: 
        !           100: static Boolean OSCompareAndSwap8(UInt8 oldValue8, UInt8 newValue8, UInt8 * value8)
        !           101: {
        !           102:        UInt32          mask = 0x000000ff;
        !           103:        UInt32          newbits = (UInt32) newValue8;
        !           104:        int                     shift;
        !           105:        UInt32          alignment = ((UInt32) value8) & (sizeof(UInt32) - 1);
        !           106:        UInt32          oldValue;
        !           107:        UInt32          newValue;
        !           108:        UInt32 *        value;
        !           109: 
        !           110:        switch (alignment) {
        !           111:                default:
        !           112:                        // assert(false);
        !           113:                case 0:
        !           114:                        value = (UInt32 *) value8;
        !           115:                        shift = 24;
        !           116:                        break;
        !           117:                case 1:
        !           118:                        value = (UInt32 *) (value8 + 1);
        !           119:                        shift = 16;
        !           120:                        break;
        !           121:                case 2:
        !           122:                        value = (UInt32 *) (value8 + 2);
        !           123:                        shift = 8;
        !           124:                        break;
        !           125:                case 3:
        !           126:                        value = (UInt32 *) (value8 + 3);
        !           127:                        shift = 0;
        !           128:                        break;
        !           129:        }
        !           130: 
        !           131:        mask <<= shift;
        !           132:        newbits <<= shift;
        !           133:        
        !           134:        oldValue = *value;
        !           135:        newValue = (oldValue & ~mask) | (newbits & mask);
        !           136:        
        !           137:        return OSCompareAndSwap(oldValue, newValue, value);
        !           138: }
        !           139: 
        !           140: static Boolean OSTestAndSetClear(UInt32 bit, Boolean wantSet, UInt8 * startAddress)
        !           141: {
        !           142:        UInt8           mask = 1;
        !           143:        UInt8           oldValue;
        !           144:        UInt8           wantValue;
        !           145:        
        !           146:        startAddress += (bit / 8);
        !           147:        mask <<= (7 - (bit % 8));
        !           148:        wantValue = wantSet ? mask : 0;
        !           149:        
        !           150:        do {
        !           151:                oldValue = *startAddress;
        !           152:                if ((oldValue & mask) == wantValue) {
        !           153:                        break;
        !           154:                }
        !           155:        } while (! OSCompareAndSwap8(oldValue, (oldValue & ~mask) | wantValue, startAddress));
        !           156:        
        !           157:        return (oldValue & mask) == wantValue;
        !           158: }
        !           159: 
        !           160: Boolean        OSTestAndSet(UInt32 bit, UInt8 * startAddress)
        !           161: {
        !           162:        return OSTestAndSetClear(bit, true, startAddress);
        !           163: }
        !           164: 
        !           165: Boolean        OSTestAndClear(UInt32 bit, UInt8 * startAddress)
        !           166: {
        !           167:        return OSTestAndSetClear(bit, false, startAddress);
        !           168: }
        !           169: 
        !           170: void * OSDequeueAtomic(void ** inList, SInt32 inOffset)
        !           171: {
        !           172:        void *  oldListHead;
        !           173:        void *  newListHead;
        !           174:        
        !           175:        do {
        !           176:                oldListHead = *inList;
        !           177:                if (oldListHead == NULL) {
        !           178:                        break;
        !           179:                }
        !           180:                
        !           181:                newListHead = *(void **) (((char *) oldListHead) + inOffset);
        !           182:        } while (! OSCompareAndSwap((UInt32)oldListHead,
        !           183:                                        (UInt32)newListHead, (UInt32 *)inList));
        !           184:        
        !           185:        return oldListHead;
        !           186: }
        !           187: 
        !           188: void   OSEnqueueAtomic(void ** inList, void * inNewLink, SInt32 inOffset)
        !           189: {
        !           190:        void *  oldListHead;
        !           191:        void *  newListHead = inNewLink;
        !           192:        void ** newLinkNextPtr = (void **) (((char *) inNewLink) + inOffset);
        !           193:        
        !           194:        do {
        !           195:                oldListHead = *inList;
        !           196:                *newLinkNextPtr = oldListHead;
        !           197:        } while (! OSCompareAndSwap((UInt32)oldListHead, (UInt32)newListHead,
        !           198:                                        (UInt32 *)inList));
        !           199: }
        !           200: 
        !           201: /*
        !           202:  * silly unaligned versions
        !           203:  */
        !           204: 
        !           205: SInt8  OSIncrementAtomic8(SInt8 * value)
        !           206: {
        !           207:        return OSAddAtomic8(1, value);
        !           208: }
        !           209: 
        !           210: SInt8  OSDecrementAtomic8(SInt8 * value)
        !           211: {
        !           212:        return OSAddAtomic8(-1, value);
        !           213: }
        !           214: 
        !           215: SInt8  OSAddAtomic8(SInt32 amount, SInt8 * value)
        !           216: {
        !           217:        SInt8   oldValue;
        !           218:        SInt8   newValue;
        !           219:        
        !           220:        do {
        !           221:                oldValue = *value;
        !           222:                newValue = oldValue + amount;
        !           223:        } while (! OSCompareAndSwap8((UInt8) oldValue, (UInt8) newValue, (UInt8 *) value));
        !           224:        
        !           225:        return oldValue;
        !           226: }
        !           227: 
        !           228: static UInt8   OSBitwiseAtomic8(UInt32 and_mask, UInt32 or_mask, UInt32 xor_mask, UInt8 * value)
        !           229: {
        !           230:        UInt8   oldValue;
        !           231:        UInt8   newValue;
        !           232:        
        !           233:        do {
        !           234:                oldValue = *value;
        !           235:                newValue = ((oldValue & and_mask) | or_mask) ^ xor_mask;
        !           236:        } while (! OSCompareAndSwap8(oldValue, newValue, value));
        !           237:        
        !           238:        return oldValue;
        !           239: }
        !           240: 
        !           241: UInt8  OSBitAndAtomic8(UInt32 mask, UInt8 * value)
        !           242: {
        !           243:        return OSBitwiseAtomic8(mask, 0, 0, value);
        !           244: }
        !           245: 
        !           246: UInt8  OSBitOrAtomic8(UInt32 mask, UInt8 * value)
        !           247: {
        !           248:        return OSBitwiseAtomic8((UInt32) -1, mask, 0, value);
        !           249: }
        !           250: 
        !           251: UInt8  OSBitXorAtomic8(UInt32 mask, UInt8 * value)
        !           252: {
        !           253:        return OSBitwiseAtomic8((UInt32) -1, 0, mask, value);
        !           254: }
        !           255: 
        !           256: 
        !           257: static Boolean OSCompareAndSwap16(UInt16 oldValue16, UInt16 newValue16, UInt16 * value16)
        !           258: {
        !           259:        UInt32          mask = 0x0000ffff;
        !           260:        UInt32          newbits = (UInt32) newValue16;
        !           261:        int                     shift;
        !           262:        UInt32          alignment = ((UInt32) value16) & (sizeof(UInt32) - 1);
        !           263:        UInt32          oldValue;
        !           264:        UInt32          newValue;
        !           265:        UInt32 *        value;
        !           266: 
        !           267:        if (alignment == 2) {
        !           268:                value = (UInt32 *) (value16 - 1);
        !           269:                shift = 0;
        !           270:        }
        !           271:        else {
        !           272:                // assert(alignment == 0);
        !           273:                value = (UInt32 *) value16;
        !           274:                shift = 16;
        !           275:        }
        !           276: 
        !           277:        mask <<= shift;
        !           278:        newbits <<= shift;
        !           279:        
        !           280:        oldValue = *value;
        !           281:        newValue = (oldValue & ~mask) | (newbits & mask);
        !           282:        
        !           283:        return OSCompareAndSwap(oldValue, newValue, value);
        !           284: }
        !           285: 
        !           286: SInt16 OSIncrementAtomic16(SInt16 * value)
        !           287: {
        !           288:        return OSAddAtomic16(1, value);
        !           289: }
        !           290: 
        !           291: SInt16 OSDecrementAtomic16(SInt16 * value)
        !           292: {
        !           293:        return OSAddAtomic16(-1, value);
        !           294: }
        !           295: 
        !           296: SInt16 OSAddAtomic16(SInt32 amount, SInt16 * value)
        !           297: {
        !           298:        SInt16  oldValue;
        !           299:        SInt16  newValue;
        !           300:        
        !           301:        do {
        !           302:                oldValue = *value;
        !           303:                newValue = oldValue + amount;
        !           304:        } while (! OSCompareAndSwap16((UInt16) oldValue, (UInt16) newValue, (UInt16 *) value));
        !           305:        
        !           306:        return oldValue;
        !           307: }
        !           308: 
        !           309: static UInt16  OSBitwiseAtomic16(UInt32 and_mask, UInt32 or_mask, UInt32 xor_mask, UInt16 * value)
        !           310: {
        !           311:        UInt16  oldValue;
        !           312:        UInt16  newValue;
        !           313:        
        !           314:        do {
        !           315:                oldValue = *value;
        !           316:                newValue = ((oldValue & and_mask) | or_mask) ^ xor_mask;
        !           317:        } while (! OSCompareAndSwap16(oldValue, newValue, value));
        !           318:        
        !           319:        return oldValue;
        !           320: }
        !           321: 
        !           322: UInt16 OSBitAndAtomic16(UInt32 mask, UInt16 * value)
        !           323: {
        !           324:        return OSBitwiseAtomic16(mask, 0, 0, value);
        !           325: }
        !           326: 
        !           327: UInt16 OSBitOrAtomic16(UInt32 mask, UInt16 * value)
        !           328: {
        !           329:        return OSBitwiseAtomic16((UInt32) -1, mask, 0, value);
        !           330: }
        !           331: 
        !           332: UInt16 OSBitXorAtomic16(UInt32 mask, UInt16 * value)
        !           333: {
        !           334:        return OSBitwiseAtomic16((UInt32) -1, 0, mask, value);
        !           335: }
        !           336: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.