00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef BASE_ATOMICOPS_INTERNALS_MACOSX_H__
00039 #define BASE_ATOMICOPS_INTERNALS_MACOSX_H__
00040
00041 typedef int32_t Atomic32;
00042 typedef intptr_t AtomicWord;
00043
00044 #include <libkern/OSAtomic.h>
00045
00046 #ifdef __LP64__ // Indicates 64-bit pointers under OS
00047 #define OSAtomicCastIntPtr(p) \
00048 reinterpret_cast<int64_t *>(const_cast<AtomicWord *>(p))
00049 #define OSAtomicCompareAndSwapIntPtr OSAtomicCompareAndSwap64
00050 #define OSAtomicAddIntPtr OSAtomicAdd64
00051 #define OSAtomicCompareAndSwapIntPtrBarrier OSAtomicCompareAndSwap64Barrier
00052 #else
00053 #define OSAtomicCastIntPtr(p) \
00054 reinterpret_cast<int32_t *>(const_cast<AtomicWord *>(p))
00055 #define OSAtomicCompareAndSwapIntPtr OSAtomicCompareAndSwap32
00056 #define OSAtomicAddIntPtr OSAtomicAdd32
00057 #define OSAtomicCompareAndSwapIntPtrBarrier OSAtomicCompareAndSwap32Barrier
00058 #endif
00059
00060 inline void MemoryBarrier() {
00061 OSMemoryBarrier();
00062 }
00063
00064 inline AtomicWord CompareAndSwap(volatile AtomicWord *ptr,
00065 AtomicWord old_value,
00066 AtomicWord new_value) {
00067 AtomicWord prev_value;
00068 do {
00069 if (OSAtomicCompareAndSwapIntPtr(old_value, new_value,
00070 OSAtomicCastIntPtr(ptr))) {
00071 return old_value;
00072 }
00073 prev_value = *ptr;
00074 } while (prev_value == old_value);
00075 return prev_value;
00076 }
00077
00078 inline AtomicWord AtomicExchange(volatile AtomicWord *ptr,
00079 AtomicWord new_value) {
00080 AtomicWord old_value;
00081 do {
00082 old_value = *ptr;
00083 } while (!OSAtomicCompareAndSwapIntPtr(old_value, new_value,
00084 OSAtomicCastIntPtr(ptr)));
00085 return old_value;
00086 }
00087
00088
00089 inline AtomicWord AtomicIncrement(volatile AtomicWord *ptr, AtomicWord increment) {
00090 return OSAtomicAddIntPtr(increment, OSAtomicCastIntPtr(ptr));
00091 }
00092
00093 inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord *ptr,
00094 AtomicWord old_value,
00095 AtomicWord new_value) {
00096 AtomicWord prev_value;
00097 do {
00098 if (OSAtomicCompareAndSwapIntPtrBarrier(old_value, new_value,
00099 OSAtomicCastIntPtr(ptr))) {
00100 return old_value;
00101 }
00102 prev_value = *ptr;
00103 } while (prev_value == old_value);
00104 return prev_value;
00105 }
00106
00107 inline AtomicWord Release_CompareAndSwap(volatile AtomicWord *ptr,
00108 AtomicWord old_value,
00109 AtomicWord new_value) {
00110
00111
00112 return Acquire_CompareAndSwap(ptr, old_value, new_value);
00113 }
00114
00115
00116 inline void Acquire_Store(volatile AtomicWord *ptr, AtomicWord value) {
00117 *ptr = value;
00118 MemoryBarrier();
00119 }
00120
00121 inline void Release_Store(volatile AtomicWord *ptr, AtomicWord value) {
00122 MemoryBarrier();
00123 *ptr = value;
00124 }
00125
00126 inline AtomicWord Acquire_Load(volatile const AtomicWord *ptr) {
00127 AtomicWord value = *ptr;
00128 MemoryBarrier();
00129 return value;
00130 }
00131
00132 inline AtomicWord Release_Load(volatile const AtomicWord *ptr) {
00133 MemoryBarrier();
00134 return *ptr;
00135 }
00136
00137
00138
00139
00140
00141
00142 inline Atomic32 CompareAndSwap(volatile Atomic32 *ptr,
00143 Atomic32 old_value,
00144 Atomic32 new_value) {
00145 Atomic32 prev_value;
00146 do {
00147 if (OSAtomicCompareAndSwap32(old_value, new_value,
00148 const_cast<Atomic32*>(ptr))) {
00149 return old_value;
00150 }
00151 prev_value = *ptr;
00152 } while (prev_value == old_value);
00153 return prev_value;
00154 }
00155
00156 inline Atomic32 AtomicExchange(volatile Atomic32 *ptr,
00157 Atomic32 new_value) {
00158 Atomic32 old_value;
00159 do {
00160 old_value = *ptr;
00161 } while (!OSAtomicCompareAndSwap32(old_value, new_value,
00162 const_cast<Atomic32*>(ptr)));
00163 return old_value;
00164 }
00165
00166 inline Atomic32 AtomicIncrement(volatile Atomic32 *ptr, Atomic32 increment) {
00167 return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
00168 }
00169
00170 inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr,
00171 Atomic32 old_value,
00172 Atomic32 new_value) {
00173 Atomic32 prev_value;
00174 do {
00175 if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
00176 const_cast<Atomic32*>(ptr))) {
00177 return old_value;
00178 }
00179 prev_value = *ptr;
00180 } while (prev_value == old_value);
00181 return prev_value;
00182 }
00183
00184 inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr,
00185 Atomic32 old_value,
00186 Atomic32 new_value) {
00187 return Acquire_CompareAndSwap(ptr, old_value, new_value);
00188 }
00189
00190
00191 inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) {
00192 *ptr = value;
00193 MemoryBarrier();
00194 }
00195
00196 inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) {
00197 MemoryBarrier();
00198 *ptr = value;
00199 }
00200
00201 inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) {
00202 Atomic32 value = *ptr;
00203 MemoryBarrier();
00204 return value;
00205 }
00206
00207 inline Atomic32 Release_Load(volatile const Atomic32 *ptr) {
00208 MemoryBarrier();
00209 return *ptr;
00210 }
00211
00212 #endif // BASE_ATOMICOPS_INTERNALS_MACOSX_H__