00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __CS_CSUTIL_ATOMICOPS_GCC_X86_H__
00020 #define __CS_CSUTIL_ATOMICOPS_GCC_X86_H__
00021
00022 #ifndef DOXYGEN_RUN
00023
00024 namespace CS
00025 {
00026 namespace Threading
00027 {
00028 class AtomicOperationsX86GCC
00029 {
00030 public:
00031 inline static int32 Set (int32* target, int32 value)
00032 {
00033 __asm__ __volatile__
00034 (
00035 "xchgl %0, %1"
00036 : "=r" (value)
00037 : "m" (*target), "0" (value)
00038 : "memory"
00039 );
00040 return value;
00041 }
00042
00043 inline static void* Set (void** target, void* value)
00044 {
00045 #if CS_PROCESSOR_SIZE == 32
00046 return (void*)Set ((int32*)target, (int32)value);
00047 #elif CS_PROCESSOR_SIZE == 64
00048 __asm__ __volatile__
00049 (
00050 "xchgq %0, %1"
00051 : "=r" (value)
00052 : "m" (*target), "0" (value)
00053 : "memory"
00054 );
00055 return value;
00056 #endif
00057 }
00058
00059 inline static int32 CompareAndSet (int32* target, int32 value,
00060 int32 comparand)
00061 {
00062 int32 prev;
00063 __asm__ __volatile__
00064 (
00065 "lock; cmpxchgl %1, %2"
00066 : "=a" (prev)
00067 : "r" (value), "m" (*target), "0" (comparand)
00068 : "memory"
00069 );
00070 return prev;
00071 }
00072
00073 inline static void* CompareAndSet (void** target, void* value,
00074 void* comparand)
00075 {
00076 #if CS_PROCESSOR_SIZE == 32
00077 return (void*)CompareAndSet ((int32*)target, (int32)value,
00078 (int32)comparand);
00079 #elif CS_PROCESSOR_SIZE == 64
00080 void* prev;
00081 __asm__ __volatile__
00082 (
00083 "lock; cmpxchgq %1, %2"
00084 : "=a" (prev)
00085 : "r" (value), "m" (*target), "0" (comparand)
00086 : "memory"
00087 );
00088 return prev;
00089 #endif
00090 }
00091
00092 inline static int32 Increment (int32* target, int32 incr = 1)
00093 {
00094 int32 result;
00095 __asm__ __volatile__
00096 (
00097 "lock; xaddl %0, %1"
00098 : "=r" (result), "=m" (*target)
00099 : "0" (incr), "m" (*target)
00100 : "memory"
00101 );
00102 return result + incr;
00103 }
00104
00105 inline static int32 Decrement (int32* target)
00106 {
00107 return (int32)Increment (target, -1);
00108 }
00109 };
00110
00111 }
00112 }
00113
00114 #endif // DOXYGEN_RUN
00115
00116 #endif // __CS_CSUTIL_ATOMICOPS_GCC_X86_H__