00001 #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_GCC_PPC_HPP
00002 #define BOOST_ATOMIC_DETAIL_ATOMIC_GCC_PPC_HPP
00003
00004
00005
00006
00007
00008
00009
00010 #include "base.hpp"
00011 #include "builder.hpp"
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 namespace boost_atomic {
00022 namespace detail {
00023 namespace atomic {
00024
00025 static inline void fence_before(memory_order2 order)
00026 {
00027 switch(order) {
00028 case memory_order2_release:
00029 case memory_order2_acq_rel:
00030 #if defined(__powerpc64__)
00031 __asm__ __volatile__ ("lwsync" ::: "memory");
00032 break;
00033 #endif
00034 case memory_order2_seq_cst:
00035 __asm__ __volatile__ ("sync" ::: "memory");
00036 default:;
00037 }
00038 }
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 static inline void fence_after(memory_order2 order)
00063 {
00064 switch(order) {
00065 case memory_order2_acquire:
00066 case memory_order2_acq_rel:
00067 case memory_order2_seq_cst:
00068 __asm__ __volatile__ ("isync");
00069 case memory_order2_consume:
00070 __asm__ __volatile__ ("" ::: "memory");
00071 default:;
00072 }
00073 }
00074
00075 template<>
00076 inline void platform_atomic_thread_fence(memory_order2 order)
00077 {
00078 switch(order) {
00079 case memory_order2_acquire:
00080 __asm__ __volatile__ ("isync" ::: "memory");
00081 break;
00082 case memory_order2_release:
00083 case memory_order2_acq_rel:
00084 #if defined(__powerpc64__)
00085 __asm__ __volatile__ ("lwsync" ::: "memory");
00086 break;
00087 #endif
00088 case memory_order2_seq_cst:
00089 __asm__ __volatile__ ("sync" ::: "memory");
00090 default:;
00091 }
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101 template<typename T>
00102 class atomic_ppc_32 {
00103 public:
00104 typedef T integral_type;
00105 explicit atomic_ppc_32(T v) : i(v) {}
00106 atomic_ppc_32() {}
00107 T load(memory_order2 order=memory_order2_seq_cst) const volatile
00108 {
00109 T v=*reinterpret_cast<volatile const T *>(&i);
00110 __asm__ __volatile__ (
00111 "cmpw %0, %0\n"
00112 "bne- 1f\n"
00113 "1f:\n"
00114 : "+b"(v));
00115 fence_after(order);
00116 return v;
00117 }
00118 void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00119 {
00120 fence_before(order);
00121 *reinterpret_cast<volatile T *>(&i)=v;
00122 }
00123 bool compare_exchange_weak(
00124 T &expected,
00125 T desired,
00126 memory_order2 success_order,
00127 memory_order2 failure_order) volatile
00128 {
00129 fence_before(success_order);
00130 int success;
00131 __asm__ __volatile__(
00132 "lwarx %0,0,%2\n"
00133 "cmpw %0, %3\n"
00134 "bne- 2f\n"
00135 "stwcx. %4,0,%2\n"
00136 "bne- 2f\n"
00137 "addi %1,0,1\n"
00138 "1:"
00139
00140 ".subsection 2\n"
00141 "2: addi %1,0,0\n"
00142 "b 1b\n"
00143 ".previous\n"
00144 : "=&b" (expected), "=&b" (success)
00145 : "b" (&i), "b" (expected), "b" ((int)desired)
00146 );
00147 if (success) fence_after(success_order);
00148 else fence_after(failure_order);
00149 return success;
00150 }
00151
00152 bool is_lock_free(void) const volatile {return true;}
00153 protected:
00154 inline T fetch_add_var(T c, memory_order2 order) volatile
00155 {
00156 fence_before(order);
00157 T original, tmp;
00158 __asm__ __volatile__(
00159 "1: lwarx %0,0,%2\n"
00160 "add %1,%0,%3\n"
00161 "stwcx. %1,0,%2\n"
00162 "bne- 1b\n"
00163 : "=&b" (original), "=&b" (tmp)
00164 : "b" (&i), "b" (c)
00165 : "cc");
00166 fence_after(order);
00167 return original;
00168 }
00169 inline T fetch_inc(memory_order2 order) volatile
00170 {
00171 fence_before(order);
00172 T original, tmp;
00173 __asm__ __volatile__(
00174 "1: lwarx %0,0,%2\n"
00175 "addi %1,%0,1\n"
00176 "stwcx. %1,0,%2\n"
00177 "bne- 1b\n"
00178 : "=&b" (original), "=&b" (tmp)
00179 : "b" (&i)
00180 : "cc");
00181 fence_after(order);
00182 return original;
00183 }
00184 inline T fetch_dec(memory_order2 order) volatile
00185 {
00186 fence_before(order);
00187 T original, tmp;
00188 __asm__ __volatile__(
00189 "1: lwarx %0,0,%2\n"
00190 "addi %1,%0,-1\n"
00191 "stwcx. %1,0,%2\n"
00192 "bne- 1b\n"
00193 : "=&b" (original), "=&b" (tmp)
00194 : "b" (&i)
00195 : "cc");
00196 fence_after(order);
00197 return original;
00198 }
00199 private:
00200 T i;
00201 };
00202
00203 #if defined(__powerpc64__)
00204
00205 #warning Untested code -- please inform me if it works
00206
00207 template<typename T>
00208 class atomic_ppc_64 {
00209 public:
00210 typedef T integral_type;
00211 explicit atomic_ppc_64(T v) : i(v) {}
00212 atomic_ppc_64() {}
00213 T load(memory_order2 order=memory_order2_seq_cst) const volatile
00214 {
00215 T v=*reinterpret_cast<volatile const T *>(&i);
00216 __asm__ __volatile__ (
00217 "cmpw %0, %0\n"
00218 "bne- 1f\n"
00219 "1f:\n"
00220 : "+b"(v));
00221 fence_after(order);
00222 return v;
00223 }
00224 void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00225 {
00226 fence_before(order);
00227 *reinterpret_cast<volatile T *>(&i)=v;
00228 }
00229 bool compare_exchange_weak(
00230 T &expected,
00231 T desired,
00232 memory_order2 success_order,
00233 memory_order2 failure_order) volatile
00234 {
00235 fence_before(success_order);
00236 int success;
00237 __asm__ __volatile__(
00238 "ldarx %0,0,%2\n"
00239 "cmpw %0, %3\n"
00240 "bne- 2f\n"
00241 "stdcx. %4,0,%2\n"
00242 "bne- 2f\n"
00243 "addi %1,0,1\n"
00244 "1:"
00245
00246 ".subsection 2\n"
00247 "2: addi %1,0,0\n"
00248 "b 1b\n"
00249 ".previous\n"
00250 : "=&b" (expected), "=&b" (success)
00251 : "b" (&i), "b" (expected), "b" ((int)desired)
00252 );
00253 if (success) fence_after(success_order);
00254 else fence_after(failure_order);
00255 fence_after(order);
00256 return success;
00257 }
00258
00259 bool is_lock_free(void) const volatile {return true;}
00260 protected:
00261 inline T fetch_add_var(T c, memory_order2 order) volatile
00262 {
00263 fence_before(order);
00264 T original, tmp;
00265 __asm__ __volatile__(
00266 "1: ldarx %0,0,%2\n"
00267 "add %1,%0,%3\n"
00268 "stdcx. %1,0,%2\n"
00269 "bne- 1b\n"
00270 : "=&b" (original), "=&b" (tmp)
00271 : "b" (&i), "b" (c)
00272 : "cc");
00273 fence_after(order);
00274 return original;
00275 }
00276 inline T fetch_inc(memory_order2 order) volatile
00277 {
00278 fence_before(order);
00279 T original, tmp;
00280 __asm__ __volatile__(
00281 "1: ldarx %0,0,%2\n"
00282 "addi %1,%0,1\n"
00283 "stdcx. %1,0,%2\n"
00284 "bne- 1b\n"
00285 : "=&b" (original), "=&b" (tmp)
00286 : "b" (&i)
00287 : "cc");
00288 fence_after(order);
00289 return original;
00290 }
00291 inline T fetch_dec(memory_order2 order) volatile
00292 {
00293 fence_before(order);
00294 T original, tmp;
00295 __asm__ __volatile__(
00296 "1: ldarx %0,0,%2\n"
00297 "addi %1,%0,-1\n"
00298 "stdcx. %1,0,%2\n"
00299 "bne- 1b\n"
00300 : "=&b" (original), "=&b" (tmp)
00301 : "b" (&i)
00302 : "cc");
00303 fence_after(order);
00304 return original;
00305 }
00306 private:
00307 T i;
00308 };
00309 #endif
00310
00311 template<typename T>
00312 class platform_atomic_integral<T, 4> : public build_atomic_from_typical<build_exchange<atomic_ppc_32<T> > > {
00313 public:
00314 typedef build_atomic_from_typical<build_exchange<atomic_ppc_32<T> > > super;
00315 explicit platform_atomic_integral(T v) : super(v) {}
00316 platform_atomic_integral(void) {}
00317 };
00318
00319 template<typename T>
00320 class platform_atomic_integral<T, 1>: public build_atomic_from_larger_type<atomic_ppc_32<uint32_t>, T> {
00321 public:
00322 typedef build_atomic_from_larger_type<atomic_ppc_32<uint32_t>, T> super;
00323
00324 explicit platform_atomic_integral(T v) : super(v) {}
00325 platform_atomic_integral(void) {}
00326 };
00327
00328 template<typename T>
00329 class platform_atomic_integral<T, 2>: public build_atomic_from_larger_type<atomic_ppc_32<uint32_t>, T> {
00330 public:
00331 typedef build_atomic_from_larger_type<atomic_ppc_32<uint32_t>, T> super;
00332
00333 explicit platform_atomic_integral(T v) : super(v) {}
00334 platform_atomic_integral(void) {}
00335 };
00336
00337 #if defined(__powerpc64__)
00338 template<typename T>
00339 class platform_atomic_integral<T, 8> : public build_atomic_from_typical<build_exchange<atomic_ppc_64<T> > > {
00340 public:
00341 typedef build_atomic_from_typical<build_exchange<atomic_ppc_64<T> > > super;
00342 explicit platform_atomic_integral(T v) : super(v) {}
00343 platform_atomic_integral(void) {}
00344 };
00345 #endif
00346
00347 }
00348 }
00349 }
00350
00351 #endif