00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __SYS_AtomicIntImpl__
00020 #define __SYS_AtomicIntImpl__
00021
00022 #include "SYS_API.h"
00023 #include "SYS_Types.h"
00024 #ifdef WIN32
00025 #if defined(_MSC_VER) && _MSC_VER >= 1400
00026 #include <intrin.h>
00027 #define USE_INTRINSICS
00028 #else
00029 #include <windows.h>
00030 #endif
00031 #define SYS_ATOMIC_INLINE SYS_FORCE_INLINE
00032 #else
00033 #define SYS_ATOMIC_INLINE inline
00034 #endif
00035 #ifdef SOLARIS
00036 #include <bits/atomicity.h>
00037 #endif
00038 #ifdef MBSD
00039 #include <libkern/OSAtomic.h>
00040 #endif
00041
00042 namespace SYS_AtomicIntNS {
00043
00044 #if defined(LINUX)
00045
00046
00047
00048 #if defined(GCC4) && __GNUC_MINOR__ >= 1
00049
00050 SYS_ATOMIC_INLINE static int32
00051 test_and_set(int32 *addr, int val)
00052 {
00053 return __sync_lock_test_and_set(addr, val);
00054 }
00055
00056 SYS_ATOMIC_INLINE static int32
00057 test_and_add(int32 *addr, int val)
00058 {
00059 return __sync_fetch_and_add(addr, val);
00060 }
00061
00062 #else
00063
00064 #if !defined(IA64)
00065
00066 SYS_ATOMIC_INLINE static int32
00067 test_and_set(int32 *addr, int32 val)
00068 {
00069 int32 oldval;
00070 __asm__ __volatile__("lock xchgl %0, %1"
00071 : "=r"(oldval), "=m"(*(addr))
00072 : "0"(val), "m"(*(addr)));
00073 return oldval;
00074 }
00075
00076 SYS_ATOMIC_INLINE static int32
00077 test_and_add(int32 *addr, int32 val)
00078 {
00079 int oldval;
00080 __asm__ __volatile__("lock xaddl %0, %1"
00081 : "=r"(oldval), "=m"(*(addr))
00082 : "0"(val), "m"(*(addr)));
00083 return oldval;
00084 }
00085
00086 #else
00087
00088
00089 SYS_ATOMIC_INLINE static int32
00090 test_and_set(int32 *addr, int32 val)
00091 {
00092 int32 oldval;
00093
00094
00095
00096
00097
00098
00099 __asm__ __volatile__("xchg4 %0=%1, %2"
00100 : "=r" (oldval), "=m" (*(addr))
00101 : "r" (1), "1"(*(addr))
00102 : "memory");
00103
00104 return oldval;
00105 }
00106
00107 SYS_ATOMIC_INLINE static int32
00108 test_and_add(int32 *addr, int32 val)
00109 {
00110 int32 oldval = *addr;
00111
00112 UT_ASSERT(0 && "No test_and_add defined for IA64");
00113 *addr += val;
00114 return oldval;
00115 }
00116
00117 #endif // !defined(IA64)
00118
00119 #endif // defined(GCC4)
00120
00121 #elif defined(MBSD_INTEL)
00122
00123 SYS_ATOMIC_INLINE static int32
00124 test_and_set(int32 *addr, int32 val)
00125 {
00126 int32 oldval;
00127 __asm__ __volatile__("lock xchgl %0, %1"
00128 : "=r"(oldval), "=m"(*(addr))
00129 : "0"(val), "m"(*(addr)));
00130 return oldval;
00131 }
00132
00133 #elif defined(MBSD_PPC)
00134
00135 SYS_ATOMIC_INLINE static int32
00136 test_and_set(int32 *__p, int32 int __newval)
00137 {
00138 int __res;
00139 __asm__ __volatile__ (
00140 "/* Inline test & set */\n"
00141 "0:\t"
00142 "lwarx %0,0,%1 \n\t"
00143 "cmpwi %0,0 \n\t"
00144 "bne- 1f \n\t"
00145 "stwcx. %2,0,%1 \n\t"
00146 "bne- 0b \n"
00147 "1:\n\t"
00148 "/* End test & set */"
00149 : "=&r"(__res)
00150 : "r"(__p), "r"(__newval)
00151 : "cr0", "memory");
00152 return __res;
00153 }
00154
00155 SYS_ATOMIC_INLINE static int32
00156 test_and_add(int32 *__p, int32 int __newval)
00157 {
00158 int32 oldval = *__p;
00159
00160
00161 *__p += __newval;
00162 return oldval;
00163 }
00164
00165 #elif defined(WIN32)
00166
00167 #ifdef USE_INTRINSICS
00168 #pragma intrinsic (_InterlockedExchange)
00169 #pragma intrinsic (_InterlockedExchangeAdd)
00170 #endif
00171
00172 SYS_FORCE_INLINE static int32
00173 test_and_set(int32 *addr, int32 val)
00174 {
00175 #ifdef USE_INTRINSICS
00176 return (int32)_InterlockedExchange((long *)addr, (long)val);
00177 #else
00178 return (int32)InterlockedExchange((long *)addr, (long)val);
00179 #endif
00180 }
00181
00182 SYS_FORCE_INLINE static int32
00183 test_and_add(int32 *addr, int32 val)
00184 {
00185 #ifdef USE_INTRINSICS
00186 return (int32)_InterlockedExchangeAdd((long *)addr, (long)val);
00187 #else
00188 return (int32)InterlockedExchangeAdd((long *)addr, (long)val);
00189 #endif
00190 }
00191
00192 #elif defined(SOLARIS)
00193
00194 SYS_ATOMIC_INLINE static int32
00195 test_and_set(int32 *addr, int32 val)
00196 {
00197 int32 oldval = *addr;
00198
00199
00200 *addr = val;
00201 return oldval;
00202 }
00203
00204 SYS_ATOMIC_INLINE static int32
00205 test_and_add(int32 *addr, int32 val)
00206 {
00207 int32 oldval = *addr;
00208
00209
00210 *addr += val;
00211 return oldval;
00212 }
00213
00214 #elif defined (GAMEOS)
00215
00216 SYS_ATOMIC_INLINE static int32
00217 test_and_set(int32 *addr, int32 val)
00218 {
00219 int32 oldval = *addr;
00220
00221 *addr = val;
00222 return oldval;
00223 }
00224
00225 SYS_ATOMIC_INLINE static int32
00226 test_and_add(int32 *addr, int32 val)
00227 {
00228 int32 oldval = *addr;
00229
00230 *addr += val;
00231 return oldval;
00232 }
00233
00234 #else
00235
00236
00237
00238 #endif
00239
00240 }
00241
00242
00243
00244 SYS_ATOMIC_INLINE int32
00245 SYS_AtomicInt32::exchange(int32 val)
00246 {
00247 return SYS_AtomicIntNS::test_and_set(&myValue, val);
00248 }
00249
00250
00251
00252 SYS_ATOMIC_INLINE int32
00253 SYS_AtomicInt32::exchangeAdd(int32 val)
00254 {
00255 #ifdef MBSD
00256 return ::OSAtomicAdd32(val, &myValue) - val;
00257 #else
00258 return SYS_AtomicIntNS::test_and_add(&myValue, val);
00259 #endif
00260 }
00261
00262
00263 SYS_ATOMIC_INLINE int32
00264 SYS_AtomicInt32::add(int32 val)
00265 {
00266 #ifdef MBSD
00267 return ::OSAtomicAdd32(val, &myValue);
00268 #else
00269 return SYS_AtomicIntNS::test_and_add(&myValue, val) + val;
00270 #endif
00271 }
00272
00273 SYS_ATOMIC_INLINE void
00274 SYS_AtomicInt32::maximum(int32 val)
00275 {
00276 int peak = exchange(val);
00277 while (peak > val)
00278 {
00279 val = peak;
00280 peak = exchange(val);
00281 }
00282 }
00283
00284 #endif
00285