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
00039 #ifndef BLOCXX_ATOMIC_OPS_HPP_
00040 #define BLOCXX_ATOMIC_OPS_HPP_
00041 #include "blocxx/BLOCXX_config.h"
00042
00043 #if defined(BLOCXX_AIX)
00044 extern "C"
00045 {
00046 #include <sys/atomic_op.h>
00047 }
00048 #elif defined(__HP_aCC) && defined(BLOCXX_ARCH_IA64)
00049 #include <machine/sys/inline.h>
00050 #endif
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #if (defined(BLOCXX_ARCH_X86) || defined(__i386__) || defined(BLOCXX_ARCH_X86_64) || defined(__x86_64__)) && defined(__GNUC__)
00062
00063 namespace BLOCXX_NAMESPACE
00064 {
00065
00066
00067 struct Atomic_t
00068 {
00069 Atomic_t() : val(0) {}
00070 Atomic_t(int i) : val(i) {}
00071 volatile int val;
00072 };
00073 inline void AtomicInc(Atomic_t &v)
00074 {
00075 __asm__ __volatile__(
00076 "lock ; " "incl %0"
00077 :"=m" (v.val)
00078 :"m" (v.val));
00079 }
00080 inline bool AtomicDecAndTest(Atomic_t &v)
00081 {
00082 unsigned char c;
00083 __asm__ __volatile__(
00084 "lock ; " "decl %0; sete %1"
00085 :"=m" (v.val), "=qm" (c)
00086 :"m" (v.val) : "memory");
00087 return c != 0;
00088 }
00089 inline int AtomicGet(Atomic_t const &v)
00090 {
00091 return v.val;
00092 }
00093 inline void AtomicDec(Atomic_t &v)
00094 {
00095 __asm__ __volatile__(
00096 "lock ; " "decl %0"
00097 :"=m" (v.val)
00098 :"m" (v.val));
00099 }
00100
00101 }
00102 #elif defined(__HP_aCC) && defined(BLOCXX_ARCH_IA64)
00103 namespace BLOCXX_NAMESPACE
00104 {
00105 struct Atomic_t
00106 {
00107 Atomic_t() : val(0) {}
00108 Atomic_t(int i) : val(i) {}
00109 volatile int val;
00110 };
00111 inline void AtomicInc(Atomic_t &v)
00112 {
00113 _Asm_fetchadd(_FASZ_W, _SEM_ACQ, &v.val, 1, _LDHINT_NONE);
00114 }
00115 inline bool AtomicDecAndTest(Atomic_t &v)
00116 {
00117 int c = int(_Asm_fetchadd(_FASZ_W, _SEM_ACQ, &v.val, int(-1), _LDHINT_NONE));
00118 --c;
00119 return c == 0;
00120 }
00121 inline int AtomicGet(Atomic_t const &v)
00122 {
00123 return int(v.val);
00124 }
00125 inline void AtomicDec(Atomic_t &v)
00126 {
00127 _Asm_fetchadd(_FASZ_W, _SEM_ACQ, &v.val, -1, _LDHINT_NONE);
00128 }
00129 }
00130
00131 #elif defined(BLOCXX_AIX)
00132 namespace BLOCXX_NAMESPACE
00133 {
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 struct Atomic_t
00144 {
00145 Atomic_t() : val(0) {}
00146 Atomic_t(int i) : val(i) {}
00147 volatile int val;
00148 };
00149
00150 inline void AtomicInc(Atomic_t &v)
00151 {
00152 ::fetch_and_add(const_cast<atomic_p>(&v.val), 1);
00153 }
00154 inline bool AtomicDecAndTest(Atomic_t &v)
00155 {
00156
00157
00158 int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00159 --c;
00160 return c == 0;
00161 }
00162 inline int AtomicGet(Atomic_t const &v)
00163 {
00164 int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), 0);
00165 return c;
00166 }
00167 inline void AtomicDec(Atomic_t &v)
00168 {
00169 ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00170 }
00171
00172 }
00173
00174 #elif (defined(BLOCXX_ARCH_PPC) || defined(__ppc__)) && defined(__GNUC__)
00175
00176 namespace BLOCXX_NAMESPACE
00177 {
00178
00179
00180 struct Atomic_t
00181 {
00182 Atomic_t() : val(0) {}
00183 Atomic_t(int i) : val(i) {}
00184 volatile int val;
00185 };
00186
00187 inline void AtomicInc(Atomic_t &v)
00188 {
00189 int t;
00190 __asm__ __volatile__(
00191 "1: lwarx %0,0,%2\n"
00192 " addic %0,%0,1\n"
00193 " stwcx. %0,0,%2\n"
00194 " bne- 1b"
00195 : "=&r" (t), "=m" (v.val)
00196 : "r" (&v.val), "m" (v.val)
00197 : "cc");
00198 }
00199 inline bool AtomicDecAndTest(Atomic_t &v)
00200 {
00201 int c;
00202 __asm__ __volatile__(
00203 "1: lwarx %0,0,%1\n"
00204 " addic %0,%0,-1\n"
00205 " stwcx. %0,0,%1\n"
00206 " bne- 1b\n"
00207 " isync"
00208 : "=&r" (c)
00209 : "r" (&v.val)
00210 : "cc", "memory");
00211 return c == 0;
00212 }
00213 inline int AtomicGet(Atomic_t const &v)
00214 {
00215 return v.val;
00216 }
00217 inline void AtomicDec(Atomic_t &v)
00218 {
00219 int c;
00220 __asm__ __volatile__(
00221 "1: lwarx %0,0,%2\n"
00222 " addic %0,%0,-1\n"
00223 " stwcx. %0,0,%2\n"
00224 " bne- 1b"
00225 : "=&r" (c), "=m" (v.val)
00226 : "r" (&v.val), "m" (v.val)
00227 : "cc");
00228 }
00229
00230 }
00231
00232 #elif defined(BLOCXX_WIN32)
00233
00234 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
00235 #include <wtypes.h>
00236
00237 namespace BLOCXX_NAMESPACE
00238 {
00239
00240
00241 struct BLOCXX_COMMON_API Atomic_t
00242 {
00243 Atomic_t() : val(0) {}
00244 Atomic_t(int i) : val(i) {}
00245 volatile long val;
00246 };
00247 inline void AtomicInc(Atomic_t &v)
00248 {
00249 InterlockedIncrement(&v.val);
00250 }
00251 inline bool AtomicDecAndTest(Atomic_t &v)
00252 {
00253 return InterlockedDecrement(&v.val) == 0;
00254 }
00255 inline int AtomicGet(Atomic_t const &v)
00256 {
00257 return v.val;
00258 }
00259 inline void AtomicDec(Atomic_t &v)
00260 {
00261 InterlockedDecrement(&v.val);
00262 }
00263
00264 }
00265
00266 #elif defined(BLOCXX_HAVE_PTHREAD_SPIN_LOCK)
00267 #include <pthread.h>
00268
00269 #define BLOCXX_USE_PTHREAD_SPIN_LOCK_ATOMIC_OPS // used in BLOCXX_AtomicOps.cpp
00270
00271 namespace BLOCXX_NAMESPACE
00272 {
00276 struct Atomic_t
00277 {
00282 Atomic_t();
00283
00289 Atomic_t(int i);
00290
00292 int val;
00293
00294 pthread_spinlock_t spinlock;
00295 };
00296
00301 void AtomicInc(Atomic_t &v);
00302
00308 bool AtomicDecAndTest(Atomic_t &v);
00314 int AtomicGet(Atomic_t const &v);
00315
00320 void AtomicDec(Atomic_t &v);
00321
00322 }
00323
00324 #else
00325
00326 #define BLOCXX_USE_BLOCXX_DEFAULT_ATOMIC_OPS // used in BLOCXX_AtomicOps.cpp
00327
00328 namespace BLOCXX_NAMESPACE
00329 {
00330
00331 struct Atomic_t
00332 {
00333 Atomic_t() : val(0) {}
00334 Atomic_t(int i) : val(i) {}
00335 volatile int val;
00336 };
00337 void AtomicInc(Atomic_t &v);
00338 bool AtomicDecAndTest(Atomic_t &v);
00339 int AtomicGet(Atomic_t const &v);
00340 void AtomicDec(Atomic_t &v);
00341
00342 }
00343
00344 #endif
00345 #endif