00001 #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_GCC_X86_HPP
00002 #define BOOST_ATOMIC_DETAIL_ATOMIC_GCC_X86_HPP
00003
00004
00005
00006
00007
00008
00009
00010 #include "base.hpp"
00011 #include "builder.hpp"
00012
00013 namespace boost_atomic {
00014 namespace detail {
00015 namespace atomic {
00016
00017 static inline void fence_before(memory_order2 order)
00018 {
00019 switch(order) {
00020 case memory_order2_consume:
00021 case memory_order2_release:
00022 case memory_order2_acq_rel:
00023 case memory_order2_seq_cst:
00024 __asm__ __volatile__ ("" ::: "memory");
00025 default:;
00026 }
00027 }
00028
00029 static inline void fence_after(memory_order2 order)
00030 {
00031 switch(order) {
00032 case memory_order2_acquire:
00033 case memory_order2_acq_rel:
00034 case memory_order2_seq_cst:
00035 __asm__ __volatile__ ("" ::: "memory");
00036 default:;
00037 }
00038 }
00039
00040 static inline void full_fence(void)
00041 {
00042 #if defined(__amd64__)
00043 __asm__ __volatile__("mfence" ::: "memory");
00044 #else
00045
00046 __asm__ __volatile__("lock; addl $0, (%%esp)" ::: "memory");
00047 #endif
00048 }
00049
00050 static inline void fence_after_load(memory_order2 order)
00051 {
00052 switch(order) {
00053 case memory_order2_seq_cst:
00054 full_fence();
00055 case memory_order2_acquire:
00056 case memory_order2_acq_rel:
00057 __asm__ __volatile__ ("" ::: "memory");
00058 default:;
00059 }
00060 }
00061
00062 template<>
00063 inline void platform_atomic_thread_fence(memory_order2 order)
00064 {
00065 switch(order) {
00066 case memory_order2_seq_cst:
00067 full_fence();
00068 case memory_order2_acquire:
00069 case memory_order2_consume:
00070 case memory_order2_acq_rel:
00071 case memory_order2_release:
00072 __asm__ __volatile__ ("" ::: "memory");
00073 default:;
00074 }
00075 }
00076
00077 template<typename T>
00078 class atomic_x86_8 {
00079 public:
00080 explicit atomic_x86_8(T v) : i(v) {}
00081 atomic_x86_8() {}
00082 T load(memory_order2 order=memory_order2_seq_cst) const volatile
00083 {
00084 T v=*reinterpret_cast<volatile const T *>(&i);
00085 fence_after_load(order);
00086 return v;
00087 }
00088 void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00089 {
00090 if (order!=memory_order2_seq_cst) {
00091 fence_before(order);
00092 *reinterpret_cast<volatile T *>(&i)=v;
00093 } else {
00094 exchange(v);
00095 }
00096 }
00097 bool compare_exchange_strong(
00098 T &expected,
00099 T desired,
00100 memory_order2 success_order,
00101 memory_order2 failure_order) volatile
00102 {
00103 fence_before(success_order);
00104 T prev=expected;
00105 __asm__ __volatile__("lock; cmpxchgb %1, %2\n" : "=a" (prev) : "q" (desired), "m" (i), "a" (expected) : "memory");
00106 bool success=(prev==expected);
00107 if (success) fence_after(success_order);
00108 else fence_after(failure_order);
00109 expected=prev;
00110 return success;
00111 }
00112 bool compare_exchange_weak(
00113 T &expected,
00114 T desired,
00115 memory_order2 success_order,
00116 memory_order2 failure_order) volatile
00117 {
00118 return compare_exchange_strong(expected, desired, success_order, failure_order);
00119 }
00120 T exchange(T r, memory_order2 order=memory_order2_seq_cst) volatile
00121 {
00122 __asm__ __volatile__("xchgb %0, %1\n" : "=q" (r) : "m"(i), "0" (r) : "memory");
00123 return r;
00124 }
00125 T fetch_add(T c, memory_order2 order=memory_order2_seq_cst) volatile
00126 {
00127 __asm__ __volatile__("lock; xaddb %0, %1" : "+q" (c), "+m" (i) :: "memory");
00128 return c;
00129 }
00130
00131 bool is_lock_free(void) const volatile {return true;}
00132 protected:
00133 typedef T integral_type;
00134 private:
00135 T i;
00136 };
00137
00138 template<typename T>
00139 class platform_atomic_integral<T, 1> : public build_atomic_from_add<atomic_x86_8<T> > {
00140 public:
00141 typedef build_atomic_from_add<atomic_x86_8<T> > super;
00142 explicit platform_atomic_integral(T v) : super(v) {}
00143 platform_atomic_integral(void) {}
00144 };
00145
00146 template<typename T>
00147 class atomic_x86_16 {
00148 public:
00149 explicit atomic_x86_16(T v) : i(v) {}
00150 atomic_x86_16() {}
00151 T load(memory_order2 order=memory_order2_seq_cst) const volatile
00152 {
00153 T v=*reinterpret_cast<volatile const T *>(&i);
00154 fence_after_load(order);
00155 return v;
00156 }
00157 void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00158 {
00159 if (order!=memory_order2_seq_cst) {
00160 fence_before(order);
00161 *reinterpret_cast<volatile T *>(&i)=v;
00162 } else {
00163 exchange(v);
00164 }
00165 }
00166 bool compare_exchange_strong(
00167 T &expected,
00168 T desired,
00169 memory_order2 success_order,
00170 memory_order2 failure_order) volatile
00171 {
00172 fence_before(success_order);
00173 T prev=expected;
00174 __asm__ __volatile__("lock; cmpxchgw %1, %2\n" : "=a" (prev) : "q" (desired), "m" (i), "a" (expected) : "memory");
00175 bool success=(prev==expected);
00176 if (success) fence_after(success_order);
00177 else fence_after(failure_order);
00178 expected=prev;
00179 return success;
00180 }
00181 bool compare_exchange_weak(
00182 T &expected,
00183 T desired,
00184 memory_order2 success_order,
00185 memory_order2 failure_order) volatile
00186 {
00187 return compare_exchange_strong(expected, desired, success_order, failure_order);
00188 }
00189 T exchange(T r, memory_order2 order=memory_order2_seq_cst) volatile
00190 {
00191 __asm__ __volatile__("xchgw %0, %1\n" : "=r" (r) : "m"(i), "0" (r) : "memory");
00192 return r;
00193 }
00194 T fetch_add(T c, memory_order2 order=memory_order2_seq_cst) volatile
00195 {
00196 __asm__ __volatile__("lock; xaddw %0, %1" : "+r" (c), "+m" (i) :: "memory");
00197 return c;
00198 }
00199
00200 bool is_lock_free(void) const volatile {return true;}
00201 protected:
00202 typedef T integral_type;
00203 private:
00204 T i;
00205 };
00206
00207 template<typename T>
00208 class platform_atomic_integral<T, 2> : public build_atomic_from_add<atomic_x86_16<T> > {
00209 public:
00210 typedef build_atomic_from_add<atomic_x86_16<T> > super;
00211 explicit platform_atomic_integral(T v) : super(v) {}
00212 platform_atomic_integral(void) {}
00213 };
00214
00215 template<typename T>
00216 class atomic_x86_32 {
00217 public:
00218 explicit atomic_x86_32(T v) : i(v) {}
00219 atomic_x86_32() {}
00220 T load(memory_order2 order=memory_order2_seq_cst) const volatile
00221 {
00222 T v=*reinterpret_cast<volatile const T *>(&i);
00223 fence_after_load(order);
00224 return v;
00225 }
00226 void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00227 {
00228 if (order!=memory_order2_seq_cst) {
00229 fence_before(order);
00230 *reinterpret_cast<volatile T *>(&i)=v;
00231 } else {
00232 exchange(v);
00233 }
00234 }
00235 bool compare_exchange_strong(
00236 T &expected,
00237 T desired,
00238 memory_order2 success_order,
00239 memory_order2 failure_order) volatile
00240 {
00241 fence_before(success_order);
00242 T prev=expected;
00243 __asm__ __volatile__("lock; cmpxchgl %1, %2\n" : "=a" (prev) : "q" (desired), "m" (i), "a" (expected) : "memory");
00244 bool success=(prev==expected);
00245 if (success) fence_after(success_order);
00246 else fence_after(failure_order);
00247 expected=prev;
00248 return success;
00249 }
00250 bool compare_exchange_weak(
00251 T &expected,
00252 T desired,
00253 memory_order2 success_order,
00254 memory_order2 failure_order) volatile
00255 {
00256 return compare_exchange_strong(expected, desired, success_order, failure_order);
00257 }
00258 T exchange(T r, memory_order2 order=memory_order2_seq_cst) volatile
00259 {
00260 __asm__ __volatile__("xchgl %0, %1\n" : "=r" (r) : "m"(i), "0" (r) : "memory");
00261 return r;
00262 }
00263 T fetch_add(T c, memory_order2 order=memory_order2_seq_cst) volatile
00264 {
00265 __asm__ __volatile__("lock; xaddl %0, %1" : "+r" (c), "+m" (i) :: "memory");
00266 return c;
00267 }
00268
00269 bool is_lock_free(void) const volatile {return true;}
00270 protected:
00271 typedef T integral_type;
00272 private:
00273 T i;
00274 };
00275
00276 template<typename T>
00277 class platform_atomic_integral<T, 4> : public build_atomic_from_add<atomic_x86_32<T> > {
00278 public:
00279 typedef build_atomic_from_add<atomic_x86_32<T> > super;
00280 explicit platform_atomic_integral(T v) : super(v) {}
00281 platform_atomic_integral(void) {}
00282 };
00283
00284 #if defined(__amd64__)
00285 template<typename T>
00286 class atomic_x86_64 {
00287 public:
00288 explicit atomic_x86_64(T v) : i(v) {}
00289 atomic_x86_64() {}
00290 T load(memory_order2 order=memory_order2_seq_cst) const volatile
00291 {
00292 T v=*reinterpret_cast<volatile const T *>(&i);
00293 fence_after_load(order);
00294 return v;
00295 }
00296 void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00297 {
00298 if (order!=memory_order2_seq_cst) {
00299 fence_before(order);
00300 *reinterpret_cast<volatile T *>(&i)=v;
00301 } else {
00302 exchange(v);
00303 }
00304 }
00305 bool compare_exchange_strong(
00306 T &expected,
00307 T desired,
00308 memory_order2 success_order,
00309 memory_order2 failure_order) volatile
00310 {
00311 fence_before(success_order);
00312 T prev=expected;
00313 __asm__ __volatile__("lock; cmpxchgq %1, %2\n" : "=a" (prev) : "q" (desired), "m" (i), "a" (expected) : "memory");
00314 bool success=(prev==expected);
00315 if (success) fence_after(success_order);
00316 else fence_after(failure_order);
00317 expected=prev;
00318 return success;
00319 }
00320 bool compare_exchange_weak(
00321 T &expected,
00322 T desired,
00323 memory_order2 success_order,
00324 memory_order2 failure_order) volatile
00325 {
00326 return compare_exchange_strong(expected, desired, success_order, failure_order);
00327 }
00328 T exchange(T r, memory_order2 order=memory_order2_seq_cst) volatile
00329 {
00330 __asm__ __volatile__("xchgq %0, %1\n" : "=r" (r) : "m"(i), "0" (r) : "memory");
00331 return r;
00332 }
00333 T fetch_add(T c, memory_order2 order=memory_order2_seq_cst) volatile
00334 {
00335 __asm__ __volatile__("lock; xaddq %0, %1" : "+r" (c), "+m" (i) :: "memory");
00336 return c;
00337 }
00338
00339 bool is_lock_free(void) const volatile {return true;}
00340 protected:
00341 typedef T integral_type;
00342 private:
00343 T i;
00344 } __attribute__((aligned(8)));
00345
00346 #elif defined(__i686__)
00347
00348 template<typename T>
00349 class atomic_x86_64 {
00350 private:
00351 typedef atomic_x86_64 this_type;
00352 public:
00353 explicit atomic_x86_64(T v) : i(v) {}
00354 atomic_x86_64() {}
00355
00356 bool compare_exchange_strong(
00357 T &expected,
00358 T desired,
00359 memory_order2 success_order,
00360 memory_order2 failure_order) volatile
00361 {
00362 long scratch;
00363 fence_before(success_order);
00364 T prev=expected;
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 __asm__ __volatile__(
00380 "movl %%ebx, %1\n"
00381 "movl %2, %%ebx\n"
00382 "lock; cmpxchg8b 0(%4)\n"
00383 "movl %1, %%ebx\n"
00384 : "=A" (prev), "=m" (scratch)
00385 : "D" ((long)desired), "c" ((long)(desired>>32)), "S" (&i), "0" (prev)
00386 : "memory");
00387 bool success=(prev==expected);
00388 if (success) fence_after(success_order);
00389 else fence_after(failure_order);
00390 expected=prev;
00391 return success;
00392 }
00393 bool compare_exchange_weak(
00394 T &expected,
00395 T desired,
00396 memory_order2 success_order,
00397 memory_order2 failure_order) volatile
00398 {
00399 return compare_exchange_strong(expected, desired, success_order, failure_order);
00400 }
00401 T exchange(T r, memory_order2 order=memory_order2_seq_cst) volatile
00402 {
00403 T prev=i;
00404 do {} while(!compare_exchange_strong(prev, r, order, memory_order2_relaxed));
00405 return prev;
00406 }
00407
00408 T load(memory_order2 order=memory_order2_seq_cst) const volatile
00409 {
00410
00411
00412
00413
00414 T expected=i;
00415 do { } while(!const_cast<this_type *>(this)->compare_exchange_strong(expected, expected, order, memory_order2_relaxed));
00416 return expected;
00417 }
00418 void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00419 {
00420 exchange(v, order);
00421 }
00422 T fetch_add(T c, memory_order2 order=memory_order2_seq_cst) volatile
00423 {
00424 T expected=i, desired;;
00425 do {
00426 desired=expected+c;
00427 } while(!compare_exchange_strong(expected, desired, order, memory_order2_relaxed));
00428 return expected;
00429 }
00430
00431 bool is_lock_free(void) const volatile {return true;}
00432 protected:
00433 typedef T integral_type;
00434 private:
00435 T i;
00436 } __attribute__((aligned(8))) ;
00437
00438 #endif
00439
00440 #if defined(__amd64__) || defined(__i686__)
00441 template<typename T>
00442 class platform_atomic_integral<T, 8> : public build_atomic_from_add<atomic_x86_64<T> >{
00443 public:
00444 typedef build_atomic_from_add<atomic_x86_64<T> > super;
00445 explicit platform_atomic_integral(T v) : super(v) {}
00446 platform_atomic_integral(void) {}
00447 };
00448 #endif
00449
00450 }
00451 }
00452 }
00453
00454 #endif