Annotation of XNU/libkern/gen/OSAtomicOperations.c, revision 1.1.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.