MPMA Framework 0.4
|
00001 //Thread Locking constructs 00002 //Luke Lenhart, 2007 00003 //See /docs/License.txt for details on how this code may be used. 00004 00005 #pragma once 00006 00007 namespace MPMA 00008 { 00009 //Atomically increments an integer 00010 inline void AtomicIntInc(volatile nuint *pint) 00011 { 00012 #ifdef __i386__ 00013 asm( "lock incl (%0);" 00014 : 00015 :"r"(pint) 00016 :"%0", "memory"); 00017 #else 00018 __sync_fetch_and_add(pint, 1); 00019 #endif 00020 } 00021 00022 //Atomically decrements an integer 00023 inline void AtomicIntDec(volatile nuint *pint) 00024 { 00025 #ifdef __i386__ 00026 asm( "lock decl (%0);" 00027 : 00028 :"r"(pint) 00029 :"%0", "memory"); 00030 #else 00031 __sync_fetch_and_add(pint, -1); 00032 #endif 00033 } 00034 00035 //Atomically adds one integer to another and returns the value of the original 00036 inline nsint AtomicIntAdd(volatile nsint *pint, nsint addValue) 00037 { 00038 #ifdef __i386__ 00039 int rval; 00040 asm volatile( "lock xaddl %2, (%1);" 00041 "movl %2, %0" 00042 :"=g"(rval) 00043 :"r"(pint), "r"(addValue) 00044 :"%0", "%1", "%2", "memory"); 00045 return rval; 00046 #else 00047 return __sync_fetch_and_add(pint, addValue); 00048 #endif 00049 } 00050 00051 //Compares expectedValue with the value at pInt, and if they are the same, sets pInt to newValue and returns true with outResultValue set to newValue. If they are different then pInt is unaffected, and returns false with outResultValue set to the value that was found at pInt. 00052 inline bool AtomicCompareExchange(volatile nuint *pInt, nuint expectedValue, nuint newValue, volatile nuint &outResultValue) 00053 { 00054 #ifdef __i386__ 00055 volatile nuint changed=0; //why does this need volatile? it fixes the return bug... 00056 nuint rval; 00057 asm( 00058 "lock cmpxchgl %4, (%2);" 00059 "jnz AtomCmpExch_Diff%=;" 00060 "movl %4, %%eax;" 00061 "incl %1;" 00062 "AtomCmpExch_Diff%=:;" 00063 "movl %%eax, %0;" 00064 :"=g"(rval), "=g"(changed) 00065 :"r"(pInt), "a"(expectedValue), "r"(newValue) 00066 :"memory", "cc"); 00067 00068 outResultValue=rval; 00069 return changed!=0; 00070 #else 00071 nuint ret=__sync_val_compare_and_swap(pInt, expectedValue, newValue); 00072 if (ret==expectedValue) 00073 { 00074 outResultValue=newValue; 00075 return true; 00076 } 00077 else 00078 { 00079 outResultValue=ret; 00080 return false; 00081 } 00082 #endif 00083 } 00084 00085 }; //namespace MPMA