LocksLin32.h

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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends