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
00035 #ifndef OWBI1_ATOMIC_OPS_HPP_
00036 #define OWBI1_ATOMIC_OPS_HPP_
00037 #include "OWBI1_config.h"
00038
00039 #if defined(OWBI1_AIX)
00040 extern "C"
00041 {
00042 #include <sys/atomic_op.h>
00043 }
00044 #endif
00045
00046
00047
00048
00049 #if (defined(OWBI1_ARCH_X86) || defined(__i386__)) && defined(__GNUC__)
00050
00051 namespace OWBI1
00052 {
00053
00054
00055 struct Atomic_t
00056 {
00057 Atomic_t() : val(0) {}
00058 Atomic_t(int i) : val(i) {}
00059 volatile int val;
00060 };
00061 inline void AtomicInc(Atomic_t &v)
00062 {
00063 __asm__ __volatile__(
00064 "lock ; " "incl %0"
00065 :"=m" (v.val)
00066 :"m" (v.val));
00067 }
00068 inline bool AtomicDecAndTest(Atomic_t &v)
00069 {
00070 unsigned char c;
00071 __asm__ __volatile__(
00072 "lock ; " "decl %0; sete %1"
00073 :"=m" (v.val), "=qm" (c)
00074 :"m" (v.val) : "memory");
00075 return c != 0;
00076 }
00077 inline int AtomicGet(Atomic_t const &v)
00078 {
00079 return v.val;
00080 }
00081 inline void AtomicDec(Atomic_t &v)
00082 {
00083 __asm__ __volatile__(
00084 "lock ; " "decl %0"
00085 :"=m" (v.val)
00086 :"m" (v.val));
00087 }
00088
00089 }
00090
00091 #elif defined(OWBI1_AIX)
00092 namespace OWBI1
00093 {
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 struct Atomic_t
00104 {
00105 Atomic_t() : val(0) {}
00106 Atomic_t(int i) : val(i) {}
00107 volatile int val;
00108 };
00109
00110 inline void AtomicInc(Atomic_t &v)
00111 {
00112 ::fetch_and_add(const_cast<atomic_p>(&v.val), 1);
00113 }
00114 inline bool AtomicDecAndTest(Atomic_t &v)
00115 {
00116
00117
00118 int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00119 --c;
00120 return c == 0;
00121 }
00122 inline int AtomicGet(Atomic_t const &v)
00123 {
00124 int c = ::fetch_and_add(const_cast<atomic_p>(&v.val), 0);
00125 return c;
00126 }
00127 inline void AtomicDec(Atomic_t &v)
00128 {
00129 ::fetch_and_add(const_cast<atomic_p>(&v.val), -1);
00130 }
00131
00132 }
00133
00134 #elif (defined(OWBI1_ARCH_PPC) || defined(__ppc__)) && defined(__GNUC__)
00135
00136 namespace OWBI1
00137 {
00138
00139
00140 struct Atomic_t
00141 {
00142 Atomic_t() : val(0) {}
00143 Atomic_t(int i) : val(i) {}
00144 volatile int val;
00145 };
00146
00147 inline void AtomicInc(Atomic_t &v)
00148 {
00149 int t;
00150 __asm__ __volatile__(
00151 "1: lwarx %0,0,%2\n"
00152 " addic %0,%0,1\n"
00153 " stwcx. %0,0,%2\n"
00154 " bne- 1b"
00155 : "=&r" (t), "=m" (v.val)
00156 : "r" (&v.val), "m" (v.val)
00157 : "cc");
00158 }
00159 inline bool AtomicDecAndTest(Atomic_t &v)
00160 {
00161 int c;
00162 __asm__ __volatile__(
00163 "1: lwarx %0,0,%1\n"
00164 " addic %0,%0,-1\n"
00165 " stwcx. %0,0,%1\n"
00166 " bne- 1b\n"
00167 " isync"
00168 : "=&r" (c)
00169 : "r" (&v.val)
00170 : "cc", "memory");
00171 return c == 0;
00172 }
00173 inline int AtomicGet(Atomic_t const &v)
00174 {
00175 return v.val;
00176 }
00177 inline void AtomicDec(Atomic_t &v)
00178 {
00179 int c;
00180 __asm__ __volatile__(
00181 "1: lwarx %0,0,%2\n"
00182 " addic %0,%0,-1\n"
00183 " stwcx. %0,0,%2\n"
00184 " bne- 1b"
00185 : "=&r" (c), "=m" (v.val)
00186 : "r" (&v.val), "m" (v.val)
00187 : "cc");
00188 }
00189
00190 }
00191
00192 #elif defined(OWBI1_WIN32)
00193
00194 namespace OWBI1
00195 {
00196
00197
00198 struct OWBI1_OWBI1PROVIFC_API Atomic_t
00199 {
00200 Atomic_t() : val(0) {}
00201 Atomic_t(int i) : val(i) {}
00202 volatile LONG val;
00203 };
00204 inline void AtomicInc(Atomic_t &v)
00205 {
00206 InterlockedIncrement(&v.val);
00207 }
00208 inline bool AtomicDecAndTest(Atomic_t &v)
00209 {
00210 return InterlockedDecrement(&v.val) == 0;
00211 }
00212 inline int AtomicGet(Atomic_t const &v)
00213 {
00214 return v.val;
00215 }
00216 inline void AtomicDec(Atomic_t &v)
00217 {
00218 InterlockedDecrement(&v.val);
00219 }
00220
00221 }
00222
00223 #elif defined(OWBI1_HAVE_PTHREAD_SPIN_LOCK)
00224 #include <pthread.h>
00225
00226 #define OWBI1_USE_PTHREAD_SPIN_LOCK_ATOMIC_OPS // used in OWBI1_AtomicOps.cpp
00227
00228 namespace OWBI1
00229 {
00230
00231 struct Atomic_t
00232 {
00233 Atomic_t();
00234 Atomic_t(int i);
00235 int val;
00236 pthread_spinlock_t spinlock;
00237 };
00238 void AtomicInc(Atomic_t &v);
00239 bool AtomicDecAndTest(Atomic_t &v);
00240 int AtomicGet(Atomic_t const &v);
00241 void AtomicDec(Atomic_t &v);
00242
00243 }
00244
00245 #else
00246
00247 #define OWBI1_USE_OWBI1_DEFAULT_ATOMIC_OPS // used in OWBI1_AtomicOps.cpp
00248
00249 namespace OWBI1
00250 {
00251
00252 struct Atomic_t
00253 {
00254 Atomic_t() : val(0) {}
00255 Atomic_t(int i) : val(i) {}
00256 volatile int val;
00257 };
00258 void AtomicInc(Atomic_t &v);
00259 bool AtomicDecAndTest(Atomic_t &v);
00260 int AtomicGet(Atomic_t const &v);
00261 void AtomicDec(Atomic_t &v);
00262
00263 }
00264
00265 #endif
00266 #endif