gcc-x86.hpp 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017
  1. #ifndef BOOST_ATOMIC_DETAIL_GCC_X86_HPP
  2. #define BOOST_ATOMIC_DETAIL_GCC_X86_HPP
  3. // Copyright (c) 2009 Helge Bahmann
  4. // Copyright (c) 2012 Tim Blechmann
  5. //
  6. // Distributed under the Boost Software License, Version 1.0.
  7. // See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. #include <string.h>
  10. #include <cstddef>
  11. #include <boost/cstdint.hpp>
  12. #include <boost/atomic/detail/config.hpp>
  13. #ifdef BOOST_HAS_PRAGMA_ONCE
  14. #pragma once
  15. #endif
  16. namespace boost {
  17. namespace atomics {
  18. namespace detail {
  19. #if defined(__x86_64__) || defined(__SSE2__)
  20. # define BOOST_ATOMIC_X86_FENCE_INSTR "mfence\n"
  21. #else
  22. # define BOOST_ATOMIC_X86_FENCE_INSTR "lock ; addl $0, (%%esp)\n"
  23. #endif
  24. #define BOOST_ATOMIC_X86_PAUSE() __asm__ __volatile__ ("pause\n")
  25. #if defined(__i386__) &&\
  26. (\
  27. defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) ||\
  28. defined(__i586__) || defined(__i686__) || defined(__pentium4__) || defined(__nocona__) || defined(__core2__) || defined(__corei7__) ||\
  29. defined(__k6__) || defined(__athlon__) || defined(__k8__) || defined(__amdfam10__) || defined(__bdver1__) || defined(__bdver2__) || defined(__bdver3__) || defined(__btver1__) || defined(__btver2__)\
  30. )
  31. #define BOOST_ATOMIC_X86_HAS_CMPXCHG8B 1
  32. #endif
  33. #if defined(__x86_64__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
  34. #define BOOST_ATOMIC_X86_HAS_CMPXCHG16B 1
  35. #endif
  36. inline void
  37. platform_fence_before(memory_order order)
  38. {
  39. switch(order)
  40. {
  41. case memory_order_relaxed:
  42. case memory_order_acquire:
  43. case memory_order_consume:
  44. break;
  45. case memory_order_release:
  46. case memory_order_acq_rel:
  47. __asm__ __volatile__ ("" ::: "memory");
  48. /* release */
  49. break;
  50. case memory_order_seq_cst:
  51. __asm__ __volatile__ ("" ::: "memory");
  52. /* seq */
  53. break;
  54. default:;
  55. }
  56. }
  57. inline void
  58. platform_fence_after(memory_order order)
  59. {
  60. switch(order)
  61. {
  62. case memory_order_relaxed:
  63. case memory_order_release:
  64. break;
  65. case memory_order_acquire:
  66. case memory_order_acq_rel:
  67. __asm__ __volatile__ ("" ::: "memory");
  68. /* acquire */
  69. break;
  70. case memory_order_consume:
  71. /* consume */
  72. break;
  73. case memory_order_seq_cst:
  74. __asm__ __volatile__ ("" ::: "memory");
  75. /* seq */
  76. break;
  77. default:;
  78. }
  79. }
  80. inline void
  81. platform_fence_after_load(memory_order order)
  82. {
  83. switch(order)
  84. {
  85. case memory_order_relaxed:
  86. case memory_order_release:
  87. break;
  88. case memory_order_acquire:
  89. case memory_order_acq_rel:
  90. __asm__ __volatile__ ("" ::: "memory");
  91. break;
  92. case memory_order_consume:
  93. break;
  94. case memory_order_seq_cst:
  95. __asm__ __volatile__ ("" ::: "memory");
  96. break;
  97. default:;
  98. }
  99. }
  100. inline void
  101. platform_fence_before_store(memory_order order)
  102. {
  103. switch(order)
  104. {
  105. case memory_order_relaxed:
  106. case memory_order_acquire:
  107. case memory_order_consume:
  108. break;
  109. case memory_order_release:
  110. case memory_order_acq_rel:
  111. __asm__ __volatile__ ("" ::: "memory");
  112. /* release */
  113. break;
  114. case memory_order_seq_cst:
  115. __asm__ __volatile__ ("" ::: "memory");
  116. /* seq */
  117. break;
  118. default:;
  119. }
  120. }
  121. inline void
  122. platform_fence_after_store(memory_order order)
  123. {
  124. switch(order)
  125. {
  126. case memory_order_relaxed:
  127. case memory_order_release:
  128. break;
  129. case memory_order_acquire:
  130. case memory_order_acq_rel:
  131. __asm__ __volatile__ ("" ::: "memory");
  132. /* acquire */
  133. break;
  134. case memory_order_consume:
  135. /* consume */
  136. break;
  137. case memory_order_seq_cst:
  138. __asm__ __volatile__ ("" ::: "memory");
  139. /* seq */
  140. break;
  141. default:;
  142. }
  143. }
  144. }
  145. }
  146. class atomic_flag
  147. {
  148. private:
  149. atomic_flag(const atomic_flag &) /* = delete */ ;
  150. atomic_flag & operator=(const atomic_flag &) /* = delete */ ;
  151. uint32_t v_;
  152. public:
  153. BOOST_CONSTEXPR atomic_flag(void) BOOST_NOEXCEPT : v_(0) {}
  154. bool
  155. test_and_set(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  156. {
  157. uint32_t v = 1;
  158. atomics::detail::platform_fence_before(order);
  159. __asm__ __volatile__ (
  160. "xchgl %0, %1"
  161. : "+r" (v), "+m" (v_)
  162. );
  163. atomics::detail::platform_fence_after(order);
  164. return v;
  165. }
  166. void
  167. clear(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  168. {
  169. if (order == memory_order_seq_cst) {
  170. uint32_t v = 0;
  171. __asm__ __volatile__ (
  172. "xchgl %0, %1"
  173. : "+r" (v), "+m" (v_)
  174. );
  175. } else {
  176. atomics::detail::platform_fence_before(order);
  177. v_ = 0;
  178. }
  179. }
  180. };
  181. } /* namespace boost */
  182. #define BOOST_ATOMIC_FLAG_LOCK_FREE 2
  183. #include <boost/atomic/detail/base.hpp>
  184. #if !defined(BOOST_ATOMIC_FORCE_FALLBACK)
  185. #define BOOST_ATOMIC_CHAR_LOCK_FREE 2
  186. #define BOOST_ATOMIC_CHAR16_T_LOCK_FREE 2
  187. #define BOOST_ATOMIC_CHAR32_T_LOCK_FREE 2
  188. #define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 2
  189. #define BOOST_ATOMIC_SHORT_LOCK_FREE 2
  190. #define BOOST_ATOMIC_INT_LOCK_FREE 2
  191. #define BOOST_ATOMIC_LONG_LOCK_FREE 2
  192. #if defined(__x86_64__) || defined(BOOST_ATOMIC_X86_HAS_CMPXCHG8B)
  193. #define BOOST_ATOMIC_LLONG_LOCK_FREE 2
  194. #endif
  195. #if defined(BOOST_ATOMIC_X86_HAS_CMPXCHG16B) && (defined(BOOST_HAS_INT128) || !defined(BOOST_NO_ALIGNMENT))
  196. #define BOOST_ATOMIC_INT128_LOCK_FREE 2
  197. #endif
  198. #define BOOST_ATOMIC_POINTER_LOCK_FREE 2
  199. #define BOOST_ATOMIC_BOOL_LOCK_FREE 2
  200. namespace boost {
  201. #define BOOST_ATOMIC_THREAD_FENCE 2
  202. inline void
  203. atomic_thread_fence(memory_order order)
  204. {
  205. switch(order)
  206. {
  207. case memory_order_relaxed:
  208. break;
  209. case memory_order_release:
  210. __asm__ __volatile__ ("" ::: "memory");
  211. break;
  212. case memory_order_acquire:
  213. __asm__ __volatile__ ("" ::: "memory");
  214. break;
  215. case memory_order_acq_rel:
  216. __asm__ __volatile__ ("" ::: "memory");
  217. break;
  218. case memory_order_consume:
  219. break;
  220. case memory_order_seq_cst:
  221. __asm__ __volatile__ (BOOST_ATOMIC_X86_FENCE_INSTR ::: "memory");
  222. break;
  223. default:;
  224. }
  225. }
  226. #define BOOST_ATOMIC_SIGNAL_FENCE 2
  227. inline void
  228. atomic_signal_fence(memory_order)
  229. {
  230. __asm__ __volatile__ ("" ::: "memory");
  231. }
  232. namespace atomics {
  233. namespace detail {
  234. template<typename T, bool Sign>
  235. class base_atomic<T, int, 1, Sign>
  236. {
  237. private:
  238. typedef base_atomic this_type;
  239. typedef T value_type;
  240. typedef T difference_type;
  241. protected:
  242. typedef value_type value_arg_type;
  243. public:
  244. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  245. BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
  246. void
  247. store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  248. {
  249. if (order != memory_order_seq_cst) {
  250. platform_fence_before(order);
  251. const_cast<volatile value_type &>(v_) = v;
  252. } else {
  253. exchange(v, order);
  254. }
  255. }
  256. value_type
  257. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  258. {
  259. value_type v = const_cast<const volatile value_type &>(v_);
  260. platform_fence_after_load(order);
  261. return v;
  262. }
  263. value_type
  264. fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  265. {
  266. platform_fence_before(order);
  267. __asm__ __volatile__
  268. (
  269. "lock ; xaddb %0, %1"
  270. : "+q" (v), "+m" (v_)
  271. :
  272. : "cc"
  273. );
  274. platform_fence_after(order);
  275. return v;
  276. }
  277. value_type
  278. fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  279. {
  280. return fetch_add(-v, order);
  281. }
  282. value_type
  283. exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  284. {
  285. platform_fence_before(order);
  286. __asm__ __volatile__
  287. (
  288. "xchgb %0, %1"
  289. : "+q" (v), "+m" (v_)
  290. );
  291. platform_fence_after(order);
  292. return v;
  293. }
  294. bool
  295. compare_exchange_strong(
  296. value_type & expected,
  297. value_type desired,
  298. memory_order success_order,
  299. memory_order failure_order) volatile BOOST_NOEXCEPT
  300. {
  301. value_type previous = expected;
  302. platform_fence_before(success_order);
  303. bool success;
  304. __asm__ __volatile__
  305. (
  306. "lock ; cmpxchgb %3, %1\n\t"
  307. "sete %2"
  308. : "+a" (previous), "+m" (v_), "=q" (success)
  309. : "q" (desired)
  310. : "cc"
  311. );
  312. if (success)
  313. platform_fence_after(success_order);
  314. else
  315. platform_fence_after(failure_order);
  316. expected = previous;
  317. return success;
  318. }
  319. bool
  320. compare_exchange_weak(
  321. value_type & expected,
  322. value_type desired,
  323. memory_order success_order,
  324. memory_order failure_order) volatile BOOST_NOEXCEPT
  325. {
  326. return compare_exchange_strong(expected, desired, success_order, failure_order);
  327. }
  328. value_type
  329. fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  330. {
  331. value_type tmp = load(memory_order_relaxed);
  332. while (!compare_exchange_weak(tmp, tmp & v, order, memory_order_relaxed))
  333. {
  334. BOOST_ATOMIC_X86_PAUSE();
  335. }
  336. return tmp;
  337. }
  338. value_type
  339. fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  340. {
  341. value_type tmp = load(memory_order_relaxed);
  342. while (!compare_exchange_weak(tmp, tmp | v, order, memory_order_relaxed))
  343. {
  344. BOOST_ATOMIC_X86_PAUSE();
  345. }
  346. return tmp;
  347. }
  348. value_type
  349. fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  350. {
  351. value_type tmp = load(memory_order_relaxed);
  352. while (!compare_exchange_weak(tmp, tmp ^ v, order, memory_order_relaxed))
  353. {
  354. BOOST_ATOMIC_X86_PAUSE();
  355. }
  356. return tmp;
  357. }
  358. bool
  359. is_lock_free(void) const volatile BOOST_NOEXCEPT
  360. {
  361. return true;
  362. }
  363. BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
  364. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  365. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  366. private:
  367. value_type v_;
  368. };
  369. template<typename T, bool Sign>
  370. class base_atomic<T, int, 2, Sign>
  371. {
  372. private:
  373. typedef base_atomic this_type;
  374. typedef T value_type;
  375. typedef T difference_type;
  376. protected:
  377. typedef value_type value_arg_type;
  378. public:
  379. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  380. BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
  381. void
  382. store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  383. {
  384. if (order != memory_order_seq_cst) {
  385. platform_fence_before(order);
  386. const_cast<volatile value_type &>(v_) = v;
  387. } else {
  388. exchange(v, order);
  389. }
  390. }
  391. value_type
  392. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  393. {
  394. value_type v = const_cast<const volatile value_type &>(v_);
  395. platform_fence_after_load(order);
  396. return v;
  397. }
  398. value_type
  399. fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  400. {
  401. platform_fence_before(order);
  402. __asm__ __volatile__
  403. (
  404. "lock ; xaddw %0, %1"
  405. : "+q" (v), "+m" (v_)
  406. :
  407. : "cc"
  408. );
  409. platform_fence_after(order);
  410. return v;
  411. }
  412. value_type
  413. fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  414. {
  415. return fetch_add(-v, order);
  416. }
  417. value_type
  418. exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  419. {
  420. platform_fence_before(order);
  421. __asm__ __volatile__
  422. (
  423. "xchgw %0, %1"
  424. : "+q" (v), "+m" (v_)
  425. );
  426. platform_fence_after(order);
  427. return v;
  428. }
  429. bool
  430. compare_exchange_strong(
  431. value_type & expected,
  432. value_type desired,
  433. memory_order success_order,
  434. memory_order failure_order) volatile BOOST_NOEXCEPT
  435. {
  436. value_type previous = expected;
  437. platform_fence_before(success_order);
  438. bool success;
  439. __asm__ __volatile__
  440. (
  441. "lock ; cmpxchgw %3, %1\n\t"
  442. "sete %2"
  443. : "+a" (previous), "+m" (v_), "=q" (success)
  444. : "q" (desired)
  445. : "cc"
  446. );
  447. if (success)
  448. platform_fence_after(success_order);
  449. else
  450. platform_fence_after(failure_order);
  451. expected = previous;
  452. return success;
  453. }
  454. bool
  455. compare_exchange_weak(
  456. value_type & expected,
  457. value_type desired,
  458. memory_order success_order,
  459. memory_order failure_order) volatile BOOST_NOEXCEPT
  460. {
  461. return compare_exchange_strong(expected, desired, success_order, failure_order);
  462. }
  463. value_type
  464. fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  465. {
  466. value_type tmp = load(memory_order_relaxed);
  467. while (!compare_exchange_weak(tmp, tmp & v, order, memory_order_relaxed))
  468. {
  469. BOOST_ATOMIC_X86_PAUSE();
  470. }
  471. return tmp;
  472. }
  473. value_type
  474. fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  475. {
  476. value_type tmp = load(memory_order_relaxed);
  477. while (!compare_exchange_weak(tmp, tmp | v, order, memory_order_relaxed))
  478. {
  479. BOOST_ATOMIC_X86_PAUSE();
  480. }
  481. return tmp;
  482. }
  483. value_type
  484. fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  485. {
  486. value_type tmp = load(memory_order_relaxed);
  487. while (!compare_exchange_weak(tmp, tmp ^ v, order, memory_order_relaxed))
  488. {
  489. BOOST_ATOMIC_X86_PAUSE();
  490. }
  491. return tmp;
  492. }
  493. bool
  494. is_lock_free(void) const volatile BOOST_NOEXCEPT
  495. {
  496. return true;
  497. }
  498. BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
  499. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  500. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  501. private:
  502. value_type v_;
  503. };
  504. template<typename T, bool Sign>
  505. class base_atomic<T, int, 4, Sign>
  506. {
  507. private:
  508. typedef base_atomic this_type;
  509. typedef T value_type;
  510. typedef T difference_type;
  511. protected:
  512. typedef value_type value_arg_type;
  513. public:
  514. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  515. BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
  516. void
  517. store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  518. {
  519. if (order != memory_order_seq_cst) {
  520. platform_fence_before(order);
  521. const_cast<volatile value_type &>(v_) = v;
  522. } else {
  523. exchange(v, order);
  524. }
  525. }
  526. value_type
  527. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  528. {
  529. value_type v = const_cast<const volatile value_type &>(v_);
  530. platform_fence_after_load(order);
  531. return v;
  532. }
  533. value_type
  534. fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  535. {
  536. platform_fence_before(order);
  537. __asm__ __volatile__
  538. (
  539. "lock ; xaddl %0, %1"
  540. : "+r" (v), "+m" (v_)
  541. :
  542. : "cc"
  543. );
  544. platform_fence_after(order);
  545. return v;
  546. }
  547. value_type
  548. fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  549. {
  550. return fetch_add(-v, order);
  551. }
  552. value_type
  553. exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  554. {
  555. platform_fence_before(order);
  556. __asm__ __volatile__
  557. (
  558. "xchgl %0, %1"
  559. : "+r" (v), "+m" (v_)
  560. );
  561. platform_fence_after(order);
  562. return v;
  563. }
  564. bool
  565. compare_exchange_strong(
  566. value_type & expected,
  567. value_type desired,
  568. memory_order success_order,
  569. memory_order failure_order) volatile BOOST_NOEXCEPT
  570. {
  571. value_type previous = expected;
  572. platform_fence_before(success_order);
  573. bool success;
  574. __asm__ __volatile__
  575. (
  576. "lock ; cmpxchgl %3, %1\n\t"
  577. "sete %2"
  578. : "+a,a" (previous), "+m,m" (v_), "=q,m" (success)
  579. : "r,r" (desired)
  580. : "cc"
  581. );
  582. if (success)
  583. platform_fence_after(success_order);
  584. else
  585. platform_fence_after(failure_order);
  586. expected = previous;
  587. return success;
  588. }
  589. bool
  590. compare_exchange_weak(
  591. value_type & expected,
  592. value_type desired,
  593. memory_order success_order,
  594. memory_order failure_order) volatile BOOST_NOEXCEPT
  595. {
  596. return compare_exchange_strong(expected, desired, success_order, failure_order);
  597. }
  598. value_type
  599. fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  600. {
  601. value_type tmp = load(memory_order_relaxed);
  602. while (!compare_exchange_weak(tmp, tmp & v, order, memory_order_relaxed))
  603. {
  604. BOOST_ATOMIC_X86_PAUSE();
  605. }
  606. return tmp;
  607. }
  608. value_type
  609. fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  610. {
  611. value_type tmp = load(memory_order_relaxed);
  612. while (!compare_exchange_weak(tmp, tmp | v, order, memory_order_relaxed))
  613. {
  614. BOOST_ATOMIC_X86_PAUSE();
  615. }
  616. return tmp;
  617. }
  618. value_type
  619. fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  620. {
  621. value_type tmp = load(memory_order_relaxed);
  622. while (!compare_exchange_weak(tmp, tmp ^ v, order, memory_order_relaxed))
  623. {
  624. BOOST_ATOMIC_X86_PAUSE();
  625. }
  626. return tmp;
  627. }
  628. bool
  629. is_lock_free(void) const volatile BOOST_NOEXCEPT
  630. {
  631. return true;
  632. }
  633. BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
  634. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  635. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  636. private:
  637. value_type v_;
  638. };
  639. #if defined(__x86_64__)
  640. template<typename T, bool Sign>
  641. class base_atomic<T, int, 8, Sign>
  642. {
  643. private:
  644. typedef base_atomic this_type;
  645. typedef T value_type;
  646. typedef T difference_type;
  647. protected:
  648. typedef value_type value_arg_type;
  649. public:
  650. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  651. BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
  652. void
  653. store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  654. {
  655. if (order != memory_order_seq_cst) {
  656. platform_fence_before(order);
  657. const_cast<volatile value_type &>(v_) = v;
  658. } else {
  659. exchange(v, order);
  660. }
  661. }
  662. value_type
  663. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  664. {
  665. value_type v = const_cast<const volatile value_type &>(v_);
  666. platform_fence_after_load(order);
  667. return v;
  668. }
  669. value_type
  670. fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  671. {
  672. platform_fence_before(order);
  673. __asm__ __volatile__
  674. (
  675. "lock ; xaddq %0, %1"
  676. : "+r" (v), "+m" (v_)
  677. :
  678. : "cc"
  679. );
  680. platform_fence_after(order);
  681. return v;
  682. }
  683. value_type
  684. fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  685. {
  686. return fetch_add(-v, order);
  687. }
  688. value_type
  689. exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  690. {
  691. platform_fence_before(order);
  692. __asm__ __volatile__
  693. (
  694. "xchgq %0, %1"
  695. : "+r" (v), "+m" (v_)
  696. );
  697. platform_fence_after(order);
  698. return v;
  699. }
  700. bool
  701. compare_exchange_strong(
  702. value_type & expected,
  703. value_type desired,
  704. memory_order success_order,
  705. memory_order failure_order) volatile BOOST_NOEXCEPT
  706. {
  707. value_type previous = expected;
  708. platform_fence_before(success_order);
  709. bool success;
  710. __asm__ __volatile__
  711. (
  712. "lock ; cmpxchgq %3, %1\n\t"
  713. "sete %2"
  714. : "+a,a" (previous), "+m,m" (v_), "=q,m" (success)
  715. : "r,r" (desired)
  716. : "cc"
  717. );
  718. if (success)
  719. platform_fence_after(success_order);
  720. else
  721. platform_fence_after(failure_order);
  722. expected = previous;
  723. return success;
  724. }
  725. bool
  726. compare_exchange_weak(
  727. value_type & expected,
  728. value_type desired,
  729. memory_order success_order,
  730. memory_order failure_order) volatile BOOST_NOEXCEPT
  731. {
  732. return compare_exchange_strong(expected, desired, success_order, failure_order);
  733. }
  734. value_type
  735. fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  736. {
  737. value_type tmp = load(memory_order_relaxed);
  738. while (!compare_exchange_weak(tmp, tmp & v, order, memory_order_relaxed))
  739. {
  740. BOOST_ATOMIC_X86_PAUSE();
  741. }
  742. return tmp;
  743. }
  744. value_type
  745. fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  746. {
  747. value_type tmp = load(memory_order_relaxed);
  748. while (!compare_exchange_weak(tmp, tmp | v, order, memory_order_relaxed))
  749. {
  750. BOOST_ATOMIC_X86_PAUSE();
  751. }
  752. return tmp;
  753. }
  754. value_type
  755. fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  756. {
  757. value_type tmp = load(memory_order_relaxed);
  758. while (!compare_exchange_weak(tmp, tmp ^ v, order, memory_order_relaxed))
  759. {
  760. BOOST_ATOMIC_X86_PAUSE();
  761. }
  762. return tmp;
  763. }
  764. bool
  765. is_lock_free(void) const volatile BOOST_NOEXCEPT
  766. {
  767. return true;
  768. }
  769. BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS
  770. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  771. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  772. private:
  773. value_type v_;
  774. };
  775. #endif
  776. /* pointers */
  777. // NOTE: x32 target is still regarded to as x86_64 and can only be detected by the size of pointers
  778. #if !defined(__x86_64__) || (defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 4)
  779. template<bool Sign>
  780. class base_atomic<void *, void *, 4, Sign>
  781. {
  782. private:
  783. typedef base_atomic this_type;
  784. typedef std::ptrdiff_t difference_type;
  785. typedef void * value_type;
  786. protected:
  787. typedef value_type value_arg_type;
  788. public:
  789. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  790. BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
  791. void
  792. store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  793. {
  794. if (order != memory_order_seq_cst) {
  795. platform_fence_before(order);
  796. const_cast<volatile value_type &>(v_) = v;
  797. } else {
  798. exchange(v, order);
  799. }
  800. }
  801. value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  802. {
  803. value_type v = const_cast<const volatile value_type &>(v_);
  804. platform_fence_after_load(order);
  805. return v;
  806. }
  807. value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  808. {
  809. platform_fence_before(order);
  810. __asm__ __volatile__
  811. (
  812. "xchgl %0, %1"
  813. : "+r" (v), "+m" (v_)
  814. );
  815. platform_fence_after(order);
  816. return v;
  817. }
  818. bool compare_exchange_strong(value_type & expected, value_type desired,
  819. memory_order success_order,
  820. memory_order failure_order) volatile BOOST_NOEXCEPT
  821. {
  822. value_type previous = expected;
  823. platform_fence_before(success_order);
  824. bool success;
  825. __asm__ __volatile__
  826. (
  827. "lock ; cmpxchgl %3, %1\n\t"
  828. "sete %2"
  829. : "+a,a" (previous), "+m,m" (v_), "=q,m" (success)
  830. : "r,r" (desired)
  831. : "cc"
  832. );
  833. if (success)
  834. platform_fence_after(success_order);
  835. else
  836. platform_fence_after(failure_order);
  837. expected = previous;
  838. return success;
  839. }
  840. bool compare_exchange_weak(value_type & expected, value_type desired,
  841. memory_order success_order,
  842. memory_order failure_order) volatile BOOST_NOEXCEPT
  843. {
  844. return compare_exchange_strong(expected, desired, success_order, failure_order);
  845. }
  846. bool
  847. is_lock_free(void) const volatile BOOST_NOEXCEPT
  848. {
  849. return true;
  850. }
  851. value_type
  852. fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  853. {
  854. platform_fence_before(order);
  855. __asm__ __volatile__
  856. (
  857. "lock ; xaddl %0, %1"
  858. : "+r" (v), "+m" (v_)
  859. :
  860. : "cc"
  861. );
  862. platform_fence_after(order);
  863. return reinterpret_cast<value_type>(v);
  864. }
  865. value_type
  866. fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  867. {
  868. return fetch_add(-v, order);
  869. }
  870. BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
  871. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  872. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  873. private:
  874. value_type v_;
  875. };
  876. template<typename T, bool Sign>
  877. class base_atomic<T *, void *, 4, Sign>
  878. {
  879. private:
  880. typedef base_atomic this_type;
  881. typedef T * value_type;
  882. typedef std::ptrdiff_t difference_type;
  883. protected:
  884. typedef value_type value_arg_type;
  885. public:
  886. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  887. BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
  888. void
  889. store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  890. {
  891. if (order != memory_order_seq_cst) {
  892. platform_fence_before(order);
  893. const_cast<volatile value_type &>(v_) = v;
  894. } else {
  895. exchange(v, order);
  896. }
  897. }
  898. value_type
  899. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  900. {
  901. value_type v = const_cast<const volatile value_type &>(v_);
  902. platform_fence_after_load(order);
  903. return v;
  904. }
  905. value_type
  906. exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  907. {
  908. platform_fence_before(order);
  909. __asm__ __volatile__
  910. (
  911. "xchgl %0, %1"
  912. : "+r" (v), "+m" (v_)
  913. );
  914. platform_fence_after(order);
  915. return v;
  916. }
  917. bool
  918. compare_exchange_strong(
  919. value_type & expected,
  920. value_type desired,
  921. memory_order success_order,
  922. memory_order failure_order) volatile BOOST_NOEXCEPT
  923. {
  924. value_type previous = expected;
  925. platform_fence_before(success_order);
  926. bool success;
  927. __asm__ __volatile__
  928. (
  929. "lock ; cmpxchgl %3, %1\n\t"
  930. "sete %2"
  931. : "+a,a" (previous), "+m,m" (v_), "=q,m" (success)
  932. : "r,r" (desired)
  933. : "cc"
  934. );
  935. if (success)
  936. platform_fence_after(success_order);
  937. else
  938. platform_fence_after(failure_order);
  939. expected = previous;
  940. return success;
  941. }
  942. bool
  943. compare_exchange_weak(
  944. value_type & expected,
  945. value_type desired,
  946. memory_order success_order,
  947. memory_order failure_order) volatile BOOST_NOEXCEPT
  948. {
  949. return compare_exchange_strong(expected, desired, success_order, failure_order);
  950. }
  951. value_type
  952. fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  953. {
  954. v = v * sizeof(*v_);
  955. platform_fence_before(order);
  956. __asm__ __volatile__
  957. (
  958. "lock ; xaddl %0, %1"
  959. : "+r" (v), "+m" (v_)
  960. :
  961. : "cc"
  962. );
  963. platform_fence_after(order);
  964. return reinterpret_cast<value_type>(v);
  965. }
  966. value_type
  967. fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  968. {
  969. return fetch_add(-v, order);
  970. }
  971. bool
  972. is_lock_free(void) const volatile BOOST_NOEXCEPT
  973. {
  974. return true;
  975. }
  976. BOOST_ATOMIC_DECLARE_POINTER_OPERATORS
  977. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  978. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  979. private:
  980. value_type v_;
  981. };
  982. #else
  983. template<bool Sign>
  984. class base_atomic<void *, void *, 8, Sign>
  985. {
  986. private:
  987. typedef base_atomic this_type;
  988. typedef std::ptrdiff_t difference_type;
  989. typedef void * value_type;
  990. protected:
  991. typedef value_type value_arg_type;
  992. public:
  993. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  994. BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
  995. void
  996. store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  997. {
  998. if (order != memory_order_seq_cst) {
  999. platform_fence_before(order);
  1000. const_cast<volatile value_type &>(v_) = v;
  1001. } else {
  1002. exchange(v, order);
  1003. }
  1004. }
  1005. value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  1006. {
  1007. value_type v = const_cast<const volatile value_type &>(v_);
  1008. platform_fence_after_load(order);
  1009. return v;
  1010. }
  1011. value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1012. {
  1013. platform_fence_before(order);
  1014. __asm__ __volatile__
  1015. (
  1016. "xchgq %0, %1"
  1017. : "+r" (v), "+m" (v_)
  1018. );
  1019. platform_fence_after(order);
  1020. return v;
  1021. }
  1022. bool compare_exchange_strong(value_type & expected, value_type desired,
  1023. memory_order success_order,
  1024. memory_order failure_order) volatile BOOST_NOEXCEPT
  1025. {
  1026. value_type previous = expected;
  1027. platform_fence_before(success_order);
  1028. bool success;
  1029. __asm__ __volatile__
  1030. (
  1031. "lock ; cmpxchgq %3, %1\n\t"
  1032. "sete %2"
  1033. : "+a,a" (previous), "+m,m" (v_), "=q,m" (success)
  1034. : "r,r" (desired)
  1035. : "cc"
  1036. );
  1037. if (success)
  1038. platform_fence_after(success_order);
  1039. else
  1040. platform_fence_after(failure_order);
  1041. expected = previous;
  1042. return success;
  1043. }
  1044. bool compare_exchange_weak(value_type & expected, value_type desired,
  1045. memory_order success_order,
  1046. memory_order failure_order) volatile BOOST_NOEXCEPT
  1047. {
  1048. return compare_exchange_strong(expected, desired, success_order, failure_order);
  1049. }
  1050. bool
  1051. is_lock_free(void) const volatile BOOST_NOEXCEPT
  1052. {
  1053. return true;
  1054. }
  1055. value_type
  1056. fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1057. {
  1058. platform_fence_before(order);
  1059. __asm__ __volatile__
  1060. (
  1061. "lock ; xaddq %0, %1"
  1062. : "+r" (v), "+m" (v_)
  1063. :
  1064. : "cc"
  1065. );
  1066. platform_fence_after(order);
  1067. return reinterpret_cast<value_type>(v);
  1068. }
  1069. value_type
  1070. fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1071. {
  1072. return fetch_add(-v, order);
  1073. }
  1074. BOOST_ATOMIC_DECLARE_VOID_POINTER_OPERATORS
  1075. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  1076. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  1077. private:
  1078. value_type v_;
  1079. };
  1080. template<typename T, bool Sign>
  1081. class base_atomic<T *, void *, 8, Sign>
  1082. {
  1083. private:
  1084. typedef base_atomic this_type;
  1085. typedef T * value_type;
  1086. typedef std::ptrdiff_t difference_type;
  1087. protected:
  1088. typedef value_type value_arg_type;
  1089. public:
  1090. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  1091. BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : v_(v) {}
  1092. void
  1093. store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1094. {
  1095. if (order != memory_order_seq_cst) {
  1096. platform_fence_before(order);
  1097. const_cast<volatile value_type &>(v_) = v;
  1098. } else {
  1099. exchange(v, order);
  1100. }
  1101. }
  1102. value_type
  1103. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  1104. {
  1105. value_type v = const_cast<const volatile value_type &>(v_);
  1106. platform_fence_after_load(order);
  1107. return v;
  1108. }
  1109. value_type
  1110. exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1111. {
  1112. platform_fence_before(order);
  1113. __asm__ __volatile__
  1114. (
  1115. "xchgq %0, %1"
  1116. : "+r" (v), "+m" (v_)
  1117. );
  1118. platform_fence_after(order);
  1119. return v;
  1120. }
  1121. bool
  1122. compare_exchange_strong(
  1123. value_type & expected,
  1124. value_type desired,
  1125. memory_order success_order,
  1126. memory_order failure_order) volatile BOOST_NOEXCEPT
  1127. {
  1128. value_type previous = expected;
  1129. platform_fence_before(success_order);
  1130. bool success;
  1131. __asm__ __volatile__
  1132. (
  1133. "lock ; cmpxchgq %3, %1\n\t"
  1134. "sete %2"
  1135. : "+a,a" (previous), "+m,m" (v_), "=q,m" (success)
  1136. : "r,r" (desired)
  1137. : "cc"
  1138. );
  1139. if (success)
  1140. platform_fence_after(success_order);
  1141. else
  1142. platform_fence_after(failure_order);
  1143. expected = previous;
  1144. return success;
  1145. }
  1146. bool
  1147. compare_exchange_weak(
  1148. value_type & expected,
  1149. value_type desired,
  1150. memory_order success_order,
  1151. memory_order failure_order) volatile BOOST_NOEXCEPT
  1152. {
  1153. return compare_exchange_strong(expected, desired, success_order, failure_order);
  1154. }
  1155. value_type
  1156. fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1157. {
  1158. v = v * sizeof(*v_);
  1159. platform_fence_before(order);
  1160. __asm__ __volatile__
  1161. (
  1162. "lock ; xaddq %0, %1"
  1163. : "+r" (v), "+m" (v_)
  1164. :
  1165. : "cc"
  1166. );
  1167. platform_fence_after(order);
  1168. return reinterpret_cast<value_type>(v);
  1169. }
  1170. value_type
  1171. fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1172. {
  1173. return fetch_add(-v, order);
  1174. }
  1175. bool
  1176. is_lock_free(void) const volatile BOOST_NOEXCEPT
  1177. {
  1178. return true;
  1179. }
  1180. BOOST_ATOMIC_DECLARE_POINTER_OPERATORS
  1181. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  1182. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  1183. private:
  1184. value_type v_;
  1185. };
  1186. #endif
  1187. template<typename T, bool Sign>
  1188. class base_atomic<T, void, 1, Sign>
  1189. {
  1190. private:
  1191. typedef base_atomic this_type;
  1192. typedef T value_type;
  1193. typedef uint8_t storage_type;
  1194. protected:
  1195. typedef value_type const& value_arg_type;
  1196. public:
  1197. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  1198. BOOST_CONSTEXPR explicit base_atomic(value_type const& v) BOOST_NOEXCEPT :
  1199. v_(reinterpret_cast<storage_type const&>(v))
  1200. {
  1201. }
  1202. void
  1203. store(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1204. {
  1205. if (order != memory_order_seq_cst) {
  1206. storage_type tmp;
  1207. memcpy(&tmp, &v, sizeof(value_type));
  1208. platform_fence_before(order);
  1209. const_cast<volatile storage_type &>(v_) = tmp;
  1210. } else {
  1211. exchange(v, order);
  1212. }
  1213. }
  1214. value_type
  1215. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  1216. {
  1217. storage_type tmp = const_cast<volatile storage_type &>(v_);
  1218. platform_fence_after_load(order);
  1219. value_type v;
  1220. memcpy(&v, &tmp, sizeof(value_type));
  1221. return v;
  1222. }
  1223. value_type
  1224. exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1225. {
  1226. storage_type tmp;
  1227. memcpy(&tmp, &v, sizeof(value_type));
  1228. platform_fence_before(order);
  1229. __asm__ __volatile__
  1230. (
  1231. "xchgb %0, %1"
  1232. : "+q" (tmp), "+m" (v_)
  1233. );
  1234. platform_fence_after(order);
  1235. value_type res;
  1236. memcpy(&res, &tmp, sizeof(value_type));
  1237. return res;
  1238. }
  1239. bool
  1240. compare_exchange_strong(
  1241. value_type & expected,
  1242. value_type const& desired,
  1243. memory_order success_order,
  1244. memory_order failure_order) volatile BOOST_NOEXCEPT
  1245. {
  1246. storage_type expected_s, desired_s;
  1247. memcpy(&expected_s, &expected, sizeof(value_type));
  1248. memcpy(&desired_s, &desired, sizeof(value_type));
  1249. storage_type previous_s = expected_s;
  1250. platform_fence_before(success_order);
  1251. bool success;
  1252. __asm__ __volatile__
  1253. (
  1254. "lock ; cmpxchgb %3, %1\n\t"
  1255. "sete %2"
  1256. : "+a" (previous_s), "+m" (v_), "=q" (success)
  1257. : "q" (desired_s)
  1258. : "cc"
  1259. );
  1260. if (success)
  1261. platform_fence_after(success_order);
  1262. else
  1263. platform_fence_after(failure_order);
  1264. memcpy(&expected, &previous_s, sizeof(value_type));
  1265. return success;
  1266. }
  1267. bool
  1268. compare_exchange_weak(
  1269. value_type & expected,
  1270. value_type const& desired,
  1271. memory_order success_order,
  1272. memory_order failure_order) volatile BOOST_NOEXCEPT
  1273. {
  1274. return compare_exchange_strong(expected, desired, success_order, failure_order);
  1275. }
  1276. bool
  1277. is_lock_free(void) const volatile BOOST_NOEXCEPT
  1278. {
  1279. return true;
  1280. }
  1281. BOOST_ATOMIC_DECLARE_BASE_OPERATORS
  1282. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  1283. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  1284. private:
  1285. storage_type v_;
  1286. };
  1287. template<typename T, bool Sign>
  1288. class base_atomic<T, void, 2, Sign>
  1289. {
  1290. private:
  1291. typedef base_atomic this_type;
  1292. typedef T value_type;
  1293. typedef uint16_t storage_type;
  1294. protected:
  1295. typedef value_type const& value_arg_type;
  1296. public:
  1297. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  1298. BOOST_CONSTEXPR explicit base_atomic(value_type const& v) BOOST_NOEXCEPT :
  1299. v_(reinterpret_cast<storage_type const&>(v))
  1300. {
  1301. }
  1302. void
  1303. store(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1304. {
  1305. if (order != memory_order_seq_cst) {
  1306. storage_type tmp;
  1307. memcpy(&tmp, &v, sizeof(value_type));
  1308. platform_fence_before(order);
  1309. const_cast<volatile storage_type &>(v_) = tmp;
  1310. } else {
  1311. exchange(v, order);
  1312. }
  1313. }
  1314. value_type
  1315. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  1316. {
  1317. storage_type tmp = const_cast<volatile storage_type &>(v_);
  1318. platform_fence_after_load(order);
  1319. value_type v;
  1320. memcpy(&v, &tmp, sizeof(value_type));
  1321. return v;
  1322. }
  1323. value_type
  1324. exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1325. {
  1326. storage_type tmp;
  1327. memcpy(&tmp, &v, sizeof(value_type));
  1328. platform_fence_before(order);
  1329. __asm__ __volatile__
  1330. (
  1331. "xchgw %0, %1"
  1332. : "+q" (tmp), "+m" (v_)
  1333. );
  1334. platform_fence_after(order);
  1335. value_type res;
  1336. memcpy(&res, &tmp, sizeof(value_type));
  1337. return res;
  1338. }
  1339. bool
  1340. compare_exchange_strong(
  1341. value_type & expected,
  1342. value_type const& desired,
  1343. memory_order success_order,
  1344. memory_order failure_order) volatile BOOST_NOEXCEPT
  1345. {
  1346. storage_type expected_s, desired_s;
  1347. memcpy(&expected_s, &expected, sizeof(value_type));
  1348. memcpy(&desired_s, &desired, sizeof(value_type));
  1349. storage_type previous_s = expected_s;
  1350. platform_fence_before(success_order);
  1351. bool success;
  1352. __asm__ __volatile__
  1353. (
  1354. "lock ; cmpxchgw %3, %1\n\t"
  1355. "sete %2"
  1356. : "+a" (previous_s), "+m" (v_), "=q" (success)
  1357. : "q" (desired_s)
  1358. : "cc"
  1359. );
  1360. if (success)
  1361. platform_fence_after(success_order);
  1362. else
  1363. platform_fence_after(failure_order);
  1364. memcpy(&expected, &previous_s, sizeof(value_type));
  1365. return success;
  1366. }
  1367. bool
  1368. compare_exchange_weak(
  1369. value_type & expected,
  1370. value_type const& desired,
  1371. memory_order success_order,
  1372. memory_order failure_order) volatile BOOST_NOEXCEPT
  1373. {
  1374. return compare_exchange_strong(expected, desired, success_order, failure_order);
  1375. }
  1376. bool
  1377. is_lock_free(void) const volatile BOOST_NOEXCEPT
  1378. {
  1379. return true;
  1380. }
  1381. BOOST_ATOMIC_DECLARE_BASE_OPERATORS
  1382. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  1383. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  1384. private:
  1385. storage_type v_;
  1386. };
  1387. template<typename T, bool Sign>
  1388. class base_atomic<T, void, 4, Sign>
  1389. {
  1390. private:
  1391. typedef base_atomic this_type;
  1392. typedef T value_type;
  1393. typedef uint32_t storage_type;
  1394. protected:
  1395. typedef value_type const& value_arg_type;
  1396. public:
  1397. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  1398. explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : v_(0)
  1399. {
  1400. memcpy(&v_, &v, sizeof(value_type));
  1401. }
  1402. void
  1403. store(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1404. {
  1405. if (order != memory_order_seq_cst) {
  1406. storage_type tmp = 0;
  1407. memcpy(&tmp, &v, sizeof(value_type));
  1408. platform_fence_before(order);
  1409. const_cast<volatile storage_type &>(v_) = tmp;
  1410. } else {
  1411. exchange(v, order);
  1412. }
  1413. }
  1414. value_type
  1415. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  1416. {
  1417. storage_type tmp = const_cast<volatile storage_type &>(v_);
  1418. platform_fence_after_load(order);
  1419. value_type v;
  1420. memcpy(&v, &tmp, sizeof(value_type));
  1421. return v;
  1422. }
  1423. value_type
  1424. exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1425. {
  1426. storage_type tmp = 0;
  1427. memcpy(&tmp, &v, sizeof(value_type));
  1428. platform_fence_before(order);
  1429. __asm__ __volatile__
  1430. (
  1431. "xchgl %0, %1"
  1432. : "+q" (tmp), "+m" (v_)
  1433. );
  1434. platform_fence_after(order);
  1435. value_type res;
  1436. memcpy(&res, &tmp, sizeof(value_type));
  1437. return res;
  1438. }
  1439. bool
  1440. compare_exchange_strong(
  1441. value_type & expected,
  1442. value_type const& desired,
  1443. memory_order success_order,
  1444. memory_order failure_order) volatile BOOST_NOEXCEPT
  1445. {
  1446. storage_type expected_s = 0, desired_s = 0;
  1447. memcpy(&expected_s, &expected, sizeof(value_type));
  1448. memcpy(&desired_s, &desired, sizeof(value_type));
  1449. storage_type previous_s = expected_s;
  1450. platform_fence_before(success_order);
  1451. bool success;
  1452. __asm__ __volatile__
  1453. (
  1454. "lock ; cmpxchgl %3, %1\n\t"
  1455. "sete %2"
  1456. : "+a,a" (previous_s), "+m,m" (v_), "=q,m" (success)
  1457. : "q,q" (desired_s)
  1458. : "cc"
  1459. );
  1460. if (success)
  1461. platform_fence_after(success_order);
  1462. else
  1463. platform_fence_after(failure_order);
  1464. memcpy(&expected, &previous_s, sizeof(value_type));
  1465. return success;
  1466. }
  1467. bool
  1468. compare_exchange_weak(
  1469. value_type & expected,
  1470. value_type const& desired,
  1471. memory_order success_order,
  1472. memory_order failure_order) volatile BOOST_NOEXCEPT
  1473. {
  1474. return compare_exchange_strong(expected, desired, success_order, failure_order);
  1475. }
  1476. bool
  1477. is_lock_free(void) const volatile BOOST_NOEXCEPT
  1478. {
  1479. return true;
  1480. }
  1481. BOOST_ATOMIC_DECLARE_BASE_OPERATORS
  1482. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  1483. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  1484. private:
  1485. storage_type v_;
  1486. };
  1487. #if defined(__x86_64__)
  1488. template<typename T, bool Sign>
  1489. class base_atomic<T, void, 8, Sign>
  1490. {
  1491. private:
  1492. typedef base_atomic this_type;
  1493. typedef T value_type;
  1494. typedef uint64_t storage_type;
  1495. protected:
  1496. typedef value_type const& value_arg_type;
  1497. public:
  1498. BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
  1499. explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : v_(0)
  1500. {
  1501. memcpy(&v_, &v, sizeof(value_type));
  1502. }
  1503. void
  1504. store(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1505. {
  1506. if (order != memory_order_seq_cst) {
  1507. storage_type tmp = 0;
  1508. memcpy(&tmp, &v, sizeof(value_type));
  1509. platform_fence_before(order);
  1510. const_cast<volatile storage_type &>(v_) = tmp;
  1511. } else {
  1512. exchange(v, order);
  1513. }
  1514. }
  1515. value_type
  1516. load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
  1517. {
  1518. storage_type tmp = const_cast<volatile storage_type &>(v_);
  1519. platform_fence_after_load(order);
  1520. value_type v;
  1521. memcpy(&v, &tmp, sizeof(value_type));
  1522. return v;
  1523. }
  1524. value_type
  1525. exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
  1526. {
  1527. storage_type tmp = 0;
  1528. memcpy(&tmp, &v, sizeof(value_type));
  1529. platform_fence_before(order);
  1530. __asm__ __volatile__
  1531. (
  1532. "xchgq %0, %1"
  1533. : "+q" (tmp), "+m" (v_)
  1534. );
  1535. platform_fence_after(order);
  1536. value_type res;
  1537. memcpy(&res, &tmp, sizeof(value_type));
  1538. return res;
  1539. }
  1540. bool
  1541. compare_exchange_strong(
  1542. value_type & expected,
  1543. value_type const& desired,
  1544. memory_order success_order,
  1545. memory_order failure_order) volatile BOOST_NOEXCEPT
  1546. {
  1547. storage_type expected_s = 0, desired_s = 0;
  1548. memcpy(&expected_s, &expected, sizeof(value_type));
  1549. memcpy(&desired_s, &desired, sizeof(value_type));
  1550. storage_type previous_s = expected_s;
  1551. platform_fence_before(success_order);
  1552. bool success;
  1553. __asm__ __volatile__
  1554. (
  1555. "lock ; cmpxchgq %3, %1\n\t"
  1556. "sete %2"
  1557. : "+a,a" (previous_s), "+m,m" (v_), "=q,m" (success)
  1558. : "q,q" (desired_s)
  1559. : "cc"
  1560. );
  1561. if (success)
  1562. platform_fence_after(success_order);
  1563. else
  1564. platform_fence_after(failure_order);
  1565. memcpy(&expected, &previous_s, sizeof(value_type));
  1566. return success;
  1567. }
  1568. bool
  1569. compare_exchange_weak(
  1570. value_type & expected,
  1571. value_type const& desired,
  1572. memory_order success_order,
  1573. memory_order failure_order) volatile BOOST_NOEXCEPT
  1574. {
  1575. return compare_exchange_strong(expected, desired, success_order, failure_order);
  1576. }
  1577. bool
  1578. is_lock_free(void) const volatile BOOST_NOEXCEPT
  1579. {
  1580. return true;
  1581. }
  1582. BOOST_ATOMIC_DECLARE_BASE_OPERATORS
  1583. BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
  1584. BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
  1585. private:
  1586. storage_type v_;
  1587. };
  1588. #endif
  1589. #if !defined(__x86_64__) && defined(BOOST_ATOMIC_X86_HAS_CMPXCHG8B)
  1590. template<typename T>
  1591. inline bool
  1592. platform_cmpxchg64_strong(T & expected, T desired, volatile T * ptr) BOOST_NOEXCEPT
  1593. {
  1594. #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
  1595. const T oldval = __sync_val_compare_and_swap(ptr, expected, desired);
  1596. const bool result = (oldval == expected);
  1597. expected = oldval;
  1598. return result;
  1599. #else
  1600. uint32_t scratch;
  1601. /* Make sure ebx is saved and restored properly in case
  1602. this object is compiled as "position independent". Since
  1603. programmers on x86 tend to forget specifying -DPIC or
  1604. similar, always assume PIC.
  1605. To make this work uniformly even in the non-PIC case,
  1606. setup register constraints such that ebx can not be
  1607. used by accident e.g. as base address for the variable
  1608. to be modified. Accessing "scratch" should always be okay,
  1609. as it can only be placed on the stack (and therefore
  1610. accessed through ebp or esp only).
  1611. In theory, could push/pop ebx onto/off the stack, but movs
  1612. to a prepared stack slot turn out to be faster. */
  1613. bool success;
  1614. __asm__ __volatile__
  1615. (
  1616. "movl %%ebx, %[scratch]\n\t"
  1617. "movl %[desired_lo], %%ebx\n\t"
  1618. "lock; cmpxchg8b %[dest]\n\t"
  1619. "movl %[scratch], %%ebx\n\t"
  1620. "sete %[success]"
  1621. : "+A,A,A,A,A,A" (expected), [dest] "+m,m,m,m,m,m" (*ptr), [scratch] "=m,m,m,m,m,m" (scratch), [success] "=q,m,q,m,q,m" (success)
  1622. : [desired_lo] "S,S,D,D,m,m" ((uint32_t)desired), "c,c,c,c,c,c" ((uint32_t)(desired >> 32))
  1623. : "memory", "cc"
  1624. );
  1625. return success;
  1626. #endif
  1627. }
  1628. // Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3A, 8.1.1. Guaranteed Atomic Operations:
  1629. //
  1630. // The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically:
  1631. // * Reading or writing a quadword aligned on a 64-bit boundary
  1632. //
  1633. // Luckily, the memory is almost always 8-byte aligned in our case because atomic<> uses 64 bit native types for storage and dynamic memory allocations
  1634. // have at least 8 byte alignment. The only unfortunate case is when atomic is placeod on the stack and it is not 8-byte aligned (like on 32 bit Windows).
  1635. template<typename T>
  1636. inline void
  1637. platform_store64(T value, volatile T * ptr) BOOST_NOEXCEPT
  1638. {
  1639. if (((uint32_t)ptr & 0x00000007) == 0)
  1640. {
  1641. #if defined(__SSE2__)
  1642. __asm__ __volatile__
  1643. (
  1644. "movq %1, %%xmm4\n\t"
  1645. "movq %%xmm4, %0\n\t"
  1646. : "=m" (*ptr)
  1647. : "m" (value)
  1648. : "memory", "xmm4"
  1649. );
  1650. #else
  1651. __asm__ __volatile__
  1652. (
  1653. "fildll %1\n\t"
  1654. "fistpll %0\n\t"
  1655. : "=m" (*ptr)
  1656. : "m" (value)
  1657. : "memory"
  1658. );
  1659. #endif
  1660. }
  1661. else
  1662. {
  1663. uint32_t scratch;
  1664. __asm__ __volatile__
  1665. (
  1666. "movl %%ebx, %[scratch]\n\t"
  1667. "movl %[value_lo], %%ebx\n\t"
  1668. "movl 0(%[dest]), %%eax\n\t"
  1669. "movl 4(%[dest]), %%edx\n\t"
  1670. ".align 16\n\t"
  1671. "1: lock; cmpxchg8b 0(%[dest])\n\t"
  1672. "jne 1b\n\t"
  1673. "movl %[scratch], %%ebx"
  1674. : [scratch] "=m,m" (scratch)
  1675. : [value_lo] "a,a" ((uint32_t)value), "c,c" ((uint32_t)(value >> 32)), [dest] "D,S" (ptr)
  1676. : "memory", "cc", "edx"
  1677. );
  1678. }
  1679. }
  1680. template<typename T>
  1681. inline T
  1682. platform_load64(const volatile T * ptr) BOOST_NOEXCEPT
  1683. {
  1684. T value;
  1685. if (((uint32_t)ptr & 0x00000007) == 0)
  1686. {
  1687. #if defined(__SSE2__)
  1688. __asm__ __volatile__
  1689. (
  1690. "movq %1, %%xmm4\n\t"
  1691. "movq %%xmm4, %0\n\t"
  1692. : "=m" (value)
  1693. : "m" (*ptr)
  1694. : "memory", "xmm4"
  1695. );
  1696. #else
  1697. __asm__ __volatile__
  1698. (
  1699. "fildll %1\n\t"
  1700. "fistpll %0\n\t"
  1701. : "=m" (value)
  1702. : "m" (*ptr)
  1703. : "memory"
  1704. );
  1705. #endif
  1706. }
  1707. else
  1708. {
  1709. // We don't care for comparison result here; the previous value will be stored into value anyway.
  1710. // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b.
  1711. __asm__ __volatile__
  1712. (
  1713. "movl %%ebx, %%eax\n\t"
  1714. "movl %%ecx, %%edx\n\t"
  1715. "lock; cmpxchg8b %[dest]"
  1716. : "=&A" (value)
  1717. : [dest] "m" (*ptr)
  1718. : "cc"
  1719. );
  1720. }
  1721. return value;
  1722. }
  1723. #endif
  1724. #if defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0
  1725. template<typename T>
  1726. inline bool
  1727. platform_cmpxchg128_strong(T& expected, T desired, volatile T* ptr) BOOST_NOEXCEPT
  1728. {
  1729. uint64_t const* p_desired = (uint64_t const*)&desired;
  1730. bool success;
  1731. __asm__ __volatile__
  1732. (
  1733. "lock; cmpxchg16b %[dest]\n\t"
  1734. "sete %[success]"
  1735. : "+A,A" (expected), [dest] "+m,m" (*ptr), [success] "=q,m" (success)
  1736. : "b,b" (p_desired[0]), "c,c" (p_desired[1])
  1737. : "memory", "cc"
  1738. );
  1739. return success;
  1740. }
  1741. template<typename T>
  1742. inline void
  1743. platform_store128(T value, volatile T* ptr) BOOST_NOEXCEPT
  1744. {
  1745. uint64_t const* p_value = (uint64_t const*)&value;
  1746. __asm__ __volatile__
  1747. (
  1748. "movq 0(%[dest]), %%rax\n\t"
  1749. "movq 8(%[dest]), %%rdx\n\t"
  1750. ".align 16\n\t"
  1751. "1: lock; cmpxchg16b 0(%[dest])\n\t"
  1752. "jne 1b"
  1753. :
  1754. : "b" (p_value[0]), "c" (p_value[1]), [dest] "r" (ptr)
  1755. : "memory", "cc", "rax", "rdx"
  1756. );
  1757. }
  1758. template<typename T>
  1759. inline T
  1760. platform_load128(const volatile T* ptr) BOOST_NOEXCEPT
  1761. {
  1762. T value;
  1763. // We don't care for comparison result here; the previous value will be stored into value anyway.
  1764. // Also we don't care for rbx and rcx values, they just have to be equal to rax and rdx before cmpxchg16b.
  1765. __asm__ __volatile__
  1766. (
  1767. "movq %%rbx, %%rax\n\t"
  1768. "movq %%rcx, %%rdx\n\t"
  1769. "lock; cmpxchg16b %[dest]"
  1770. : "=&A" (value)
  1771. : [dest] "m" (*ptr)
  1772. : "cc"
  1773. );
  1774. return value;
  1775. }
  1776. #endif // defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0
  1777. }
  1778. }
  1779. }
  1780. /* pull in 64-bit atomic type using cmpxchg8b above */
  1781. #if !defined(__x86_64__) && defined(BOOST_ATOMIC_X86_HAS_CMPXCHG8B)
  1782. #include <boost/atomic/detail/cas64strong.hpp>
  1783. #endif
  1784. /* pull in 128-bit atomic type using cmpxchg16b above */
  1785. #if defined(BOOST_ATOMIC_INT128_LOCK_FREE) && BOOST_ATOMIC_INT128_LOCK_FREE > 0
  1786. #include <boost/atomic/detail/cas128strong.hpp>
  1787. #endif
  1788. #endif /* !defined(BOOST_ATOMIC_FORCE_FALLBACK) */
  1789. #endif