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
00037 #ifndef BLOCXX_ATOMIC_OPS_HPP_
00038 #define BLOCXX_ATOMIC_OPS_HPP_
00039 #include "blocxx/BLOCXX_config.h"
00040
00041 #if defined(BLOCXX_AIX)
00042 extern "C"
00043 {
00044 #include <sys/atomic_op.h>
00045 }
00046 #endif
00047
00048
00049
00050
00051
00052 #if (defined(BLOCXX_ARCH_X86) || defined(__i386__) || defined(BLOCXX_ARCH_X86_64) || defined(__x86_64__)) && defined(__GNUC__)
00053
00054 namespace BLOCXX_NAMESPACE
00055 {
00056
00057
00058 struct Atomic_t
00059 {
00060 Atomic_t() : val(0) {}
00061 Atomic_t(int i) : val(i) {}
00062 volatile int val;
00063 };
00064 inline void AtomicInc(Atomic_t &v)
00065 {
00066 __asm__ __volatile__(
00067 "lock ; " "incl %0"
00068 :"=m" (v.val)
00069 :"m" (v.val));
00070 }
00071 inline bool AtomicDecAndTest(Atomic_t &v)
00072 {
00073 unsigned char c;
00074 __asm__ __volatile__(
00075 "lock ; " "decl %0; sete %1"
00076 :"=m" (v.val), "=qm" (c)
00077 :"m" (v.val) : "memory");
00078 return c != 0;
00079 }
00080 inline int AtomicGet(Atomic_t const &v)
00081 {
00082 return v.val;
00083 }
00084 inline void AtomicDec(Atomic_t &v)
00085 {
00086 __asm__ __volatile__(
00087 "lock ; " "decl %0"
00088 :"=m" (v.val)
00089 :"m" (v.val));
00090 }
00091
00092 }
00093
00094 #elif defined(BLOCXX_AIX)
00095 namespace BLOCXX_NAMESPACE
00096 {
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 struct Atomic_t
00107 {
00108 Atomic_t() : val(0) {}
00109 Atomic_t(int i) : val(i) {}
00110 volatile int val;
00111 };
00112
00113 inline void AtomicInc(Atomic_t &v)
00114 {
00115 ::fetch_and_add(const_cast<atomic_p>(&v.val), 1);
00116 }
00117 inline bool AtomicDecAndTest(Atomic_t &v)
00118 {
00119
00120
00121 int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00122 --c;
00123 return c == 0;
00124 }
00125 inline int AtomicGet(Atomic_t const &v)
00126 {
00127 int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), 0);
00128 return c;
00129 }
00130 inline void AtomicDec(Atomic_t &v)
00131 {
00132 ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00133 }
00134
00135 }
00136
00137 #elif (defined(BLOCXX_ARCH_PPC) || defined(__ppc__)) && defined(__GNUC__)
00138
00139 namespace BLOCXX_NAMESPACE
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 int t;
00153 __asm__ __volatile__(
00154 "1: lwarx %0,0,%2\n"
00155 " addic %0,%0,1\n"
00156 " stwcx. %0,0,%2\n"
00157 " bne- 1b"
00158 : "=&r" (t), "=m" (v.val)
00159 : "r" (&v.val), "m" (v.val)
00160 : "cc");
00161 }
00162 inline bool AtomicDecAndTest(Atomic_t &v)
00163 {
00164 int c;
00165 __asm__ __volatile__(
00166 "1: lwarx %0,0,%1\n"
00167 " addic %0,%0,-1\n"
00168 " stwcx. %0,0,%1\n"
00169 " bne- 1b\n"
00170 " isync"
00171 : "=&r" (c)
00172 : "r" (&v.val)
00173 : "cc", "memory");
00174 return c == 0;
00175 }
00176 inline int AtomicGet(Atomic_t const &v)
00177 {
00178 return v.val;
00179 }
00180 inline void AtomicDec(Atomic_t &v)
00181 {
00182 int c;
00183 __asm__ __volatile__(
00184 "1: lwarx %0,0,%2\n"
00185 " addic %0,%0,-1\n"
00186 " stwcx. %0,0,%2\n"
00187 " bne- 1b"
00188 : "=&r" (c), "=m" (v.val)
00189 : "r" (&v.val), "m" (v.val)
00190 : "cc");
00191 }
00192
00193 }
00194
00195 #elif defined(BLOCXX_WIN32)
00196
00197 namespace BLOCXX_NAMESPACE
00198 {
00199
00200
00201 struct BLOCXX_COMMON_API Atomic_t
00202 {
00203 Atomic_t() : val(0) {}
00204 Atomic_t(int i) : val(i) {}
00205 volatile LONG val;
00206 };
00207 inline void AtomicInc(Atomic_t &v)
00208 {
00209 InterlockedIncrement(&v.val);
00210 }
00211 inline bool AtomicDecAndTest(Atomic_t &v)
00212 {
00213 return InterlockedDecrement(&v.val) == 0;
00214 }
00215 inline int AtomicGet(Atomic_t const &v)
00216 {
00217 return v.val;
00218 }
00219 inline void AtomicDec(Atomic_t &v)
00220 {
00221 InterlockedDecrement(&v.val);
00222 }
00223
00224 }
00225
00226 #elif defined(BLOCXX_HAVE_PTHREAD_SPIN_LOCK)
00227 #include <pthread.h>
00228
00229 #define BLOCXX_USE_PTHREAD_SPIN_LOCK_ATOMIC_OPS // used in BLOCXX_AtomicOps.cpp
00230
00231 namespace BLOCXX_NAMESPACE
00232 {
00236 struct Atomic_t
00237 {
00242 Atomic_t();
00243
00249 Atomic_t(int i);
00250
00252 int val;
00253
00254 pthread_spinlock_t spinlock;
00255 };
00256
00261 void AtomicInc(Atomic_t &v);
00262
00268 bool AtomicDecAndTest(Atomic_t &v);
00274 int AtomicGet(Atomic_t const &v);
00275
00280 void AtomicDec(Atomic_t &v);
00281
00282 }
00283
00284 #else
00285
00286 #define BLOCXX_USE_BLOCXX_DEFAULT_ATOMIC_OPS // used in BLOCXX_AtomicOps.cpp
00287
00288 namespace BLOCXX_NAMESPACE
00289 {
00290
00291 struct Atomic_t
00292 {
00293 Atomic_t() : val(0) {}
00294 Atomic_t(int i) : val(i) {}
00295 volatile int val;
00296 };
00297 void AtomicInc(Atomic_t &v);
00298 bool AtomicDecAndTest(Atomic_t &v);
00299 int AtomicGet(Atomic_t const &v);
00300 void AtomicDec(Atomic_t &v);
00301
00302 }
00303
00304 #endif
00305 #endif