aso 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. # AST atomic scalar operations feature tests
  2. if aso note{ gcc 4.1+ 64 bit memory atomic operations model }end link{
  3. #include "FEATURE/common"
  4. int main()
  5. {
  6. uint64_t i = 0;
  7. uint32_t j = 0;
  8. uint16_t l = 0;
  9. uint8_t m = 0;
  10. return __sync_fetch_and_add(&i,7)+__sync_fetch_and_add(&j,7)+__sync_fetch_and_add(&l,7)+__sync_fetch_and_add(&m,7);
  11. }
  12. }end && {
  13. #define _aso_cas8(p,o,n) __sync_val_compare_and_swap(p,o,n)
  14. #define _aso_inc8(p) __sync_fetch_and_add(p,1)
  15. #define _aso_dec8(p) __sync_fetch_and_sub(p,1)
  16. #define _aso_cas16(p,o,n) __sync_val_compare_and_swap(p,o,n)
  17. #define _aso_inc16(p) __sync_fetch_and_add(p,1)
  18. #define _aso_dec16(p) __sync_fetch_and_sub(p,1)
  19. #define _aso_cas32(p,o,n) __sync_val_compare_and_swap(p,o,n)
  20. #define _aso_inc32(p) __sync_fetch_and_add(p,1)
  21. #define _aso_dec32(p) __sync_fetch_and_sub(p,1)
  22. #define _aso_cas64(p,o,n) __sync_val_compare_and_swap(p,o,n)
  23. #define _aso_inc64(p) __sync_fetch_and_add(p,1)
  24. #define _aso_dec64(p) __sync_fetch_and_sub(p,1)
  25. #if _ast_sizeof_pointer == 8
  26. #define _aso_casptr(p,o,n) ((void*)__sync_val_compare_and_swap(p,o,n))
  27. #else
  28. #define _aso_casptr(p,o,n) ((void*)__sync_val_compare_and_swap(p,o,n))
  29. #endif
  30. }
  31. elif aso note{ gcc 4.1+ 32 bit memory atomic operations model }end link{
  32. #include "FEATURE/common"
  33. int main()
  34. {
  35. uint32_t i = 0;
  36. uint16_t j = 0;
  37. uint8_t l = 0;
  38. return __sync_fetch_and_add(&i,7)+__sync_fetch_and_add(&j,7)+__sync_fetch_and_add(&l,7);
  39. }
  40. }end && {
  41. #define _aso_cas8(p,o,n) __sync_val_compare_and_swap(p,o,n)
  42. #define _aso_inc8(p) __sync_fetch_and_add(p,1)
  43. #define _aso_dec8(p) __sync_fetch_and_sub(p,1)
  44. #define _aso_cas16(p,o,n) __sync_val_compare_and_swap(p,o,n)
  45. #define _aso_inc16(p) __sync_fetch_and_add(p,1)
  46. #define _aso_dec16(p) __sync_fetch_and_sub(p,1)
  47. #define _aso_cas32(p,o,n) __sync_val_compare_and_swap(p,o,n)
  48. #define _aso_inc32(p) __sync_fetch_and_add(p,1)
  49. #define _aso_dec32(p) __sync_fetch_and_sub(p,1)
  50. #define _aso_casptr(p,o,n) ((void*)__sync_val_compare_and_swap(p,o,n))
  51. }
  52. elif aso note{ <atomic.h> atomic_cas_64 }end link{
  53. #include "FEATURE/common"
  54. #include <atomic.h>
  55. int main()
  56. {
  57. uint64_t i = 0;
  58. uint32_t j = 1;
  59. return atomic_cas_64(&i, 0, 1) != 0 || atomic_add_32_nv(&j, 1) != 1;
  60. }
  61. }end && {
  62. #include <atomic.h>
  63. #define _aso_cas8(p,o,n) atomic_cas_8(p,o,n)
  64. #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
  65. #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
  66. #define _aso_cas16(p,o,n) atomic_cas_16(p,o,n)
  67. #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
  68. #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
  69. #define _aso_cas32(p,o,n) atomic_cas_32(p,o,n)
  70. #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
  71. #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
  72. #define _aso_cas64(p,o,n) atomic_cas_64(p,o,n)
  73. #define _aso_inc64(p) (atomic_add_64_nv(p,1)-1)
  74. #define _aso_dec64(p) (atomic_add_64_nv(p,-1)+1)
  75. #if _ast_sizeof_pointer == 8
  76. #define _aso_casptr(p,o,n) ((void*)atomic_cas_64((uint64_t*)p,o,n))
  77. #else
  78. #define _aso_casptr(p,o,n) ((void*)atomic_cas_32((uint32_t*)p,o,n))
  79. #endif
  80. }
  81. elif aso note{ <atomic.h> atomic_cas_32 }end link{
  82. #include "FEATURE/common"
  83. #include <atomic.h>
  84. int main()
  85. {
  86. uint32_t i = 0;
  87. return atomic_cas_32(&i, 0, 1) != 0 || (atomic_add_32_nv(&i, 1) - 1) != 1;
  88. }
  89. }end && {
  90. #include <atomic.h>
  91. #define _aso_cas8(p,o,n) atomic_cas_8(p,o,n)
  92. #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
  93. #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
  94. #define _aso_cas16(p,o,n) atomic_cas_16(p,o,n)
  95. #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
  96. #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
  97. #define _aso_cas32(p,o,n) atomic_cas_32(p,o,n)
  98. #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
  99. #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
  100. #define _aso_casptr(p,o,n) ((void*)atomic_cas_32((uint32_t*)p,o,n))
  101. }
  102. elif aso -latomic note{ <atomic.h> atomic_cas_64 with -latomic }end link{
  103. #include "FEATURE/common"
  104. #include <atomic.h>
  105. int main()
  106. {
  107. uint64_t i = 0;
  108. uint32_t j = 1;
  109. return atomic_cas_64(&i, 0, 1) != 0 || (atomic_add_32_nv(&j, 1) - 1) != 1;
  110. }
  111. }end && {
  112. #include <atomic.h>
  113. #define _REQ_atomic
  114. #define _aso_cas8(p,o,n) atomic_cas_8(p,o,n)
  115. #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
  116. #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
  117. #define _aso_cas16(p,o,n) atomic_cas_16(p,o,n)
  118. #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
  119. #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
  120. #define _aso_cas32(p,o,n) atomic_cas_32(p,o,n)
  121. #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
  122. #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
  123. #define _aso_cas64(p,o,n) atomic_cas_64(p,o,n)
  124. #define _aso_inc64(p) (atomic_add_64_nv(p,1)-1)
  125. #define _aso_dec64(p) (atomic_add_64_nv(p,-1)+1)
  126. #if _ast_sizeof_pointer == 8
  127. #define _aso_casptr(p,o,n) ((void*)atomic_cas_64((uint64_t*)p,o,n))
  128. #else
  129. #define _aso_casptr(p,o,n) ((void*)atomic_cas_32((uint32_t*)p,o,n))
  130. #endif
  131. }
  132. elif aso note{ <atomic.h> atomic_cas_32 with -latomic }end link{
  133. #include "FEATURE/common"
  134. #include <atomic.h>
  135. int main()
  136. {
  137. uint32_t i = 0;
  138. return atomic_cas_32(&i, 0, 1) != 0 || (atomic_add_32_nv(&i, 1) - 1) != 1;
  139. }
  140. }end && {
  141. #include <atomic.h>
  142. #define _REQ_atomic
  143. #define _aso_cas8(p,o,n) atomic_cas_8(p,o,n)
  144. #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
  145. #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
  146. #define _aso_cas16(p,o,n) atomic_cas_16(p,o,n)
  147. #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
  148. #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
  149. #define _aso_cas32(p,o,n) atomic_cas_32(p,o,n)
  150. #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
  151. #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
  152. #define _aso_casptr(p,o,n) ((void*)atomic_cas_32((uint32_t*)p,o,n))
  153. }
  154. elif aso note{ <atomic.h> cas64 }end link{
  155. #include "FEATURE/common"
  156. #include <atomic.h>
  157. int main()
  158. {
  159. uint64_t i = 0;
  160. uint32_t j = 1;
  161. return cas64(&i, 0, 1) != 0 || (atomic_add_32_nv(&j, 1) - 1) != 1;
  162. }
  163. }end && {
  164. #include <atomic.h>
  165. #define _aso_cas8(p,o,n) cas8(p,o,n)
  166. #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
  167. #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
  168. #define _aso_cas16(p,o,n) cas16(p,o,n)
  169. #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
  170. #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
  171. #define _aso_cas32(p,o,n) cas32(p,o,n)
  172. #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
  173. #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
  174. #define _aso_cas64(p,o,n) cas64(p,o,n)
  175. #define _aso_inc64(p) (atomic_add_64_nv(p,1)-1)
  176. #define _aso_dec64(p) (atomic_add_64_nv(p,-1)+1)
  177. #if _ast_sizeof_pointer == 8
  178. #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,o,n))
  179. #else
  180. #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,o,n))
  181. #endif
  182. }
  183. elif aso note{ <atomic.h> just cas64 }end link{
  184. #include "FEATURE/common"
  185. #include <atomic.h>
  186. int main()
  187. {
  188. uint64_t i = 0;
  189. uint32_t j = 1;
  190. uint16_t k = 1;
  191. uint8_t l = 1;
  192. return cas64(&i, 0, 1) != 0 || cas32(&j, 0, 1) != 0 || cas16(&k, 0, 1) != 0 || cas8(&l, 0, 1) != 0;
  193. }
  194. }end && {
  195. #include <atomic.h>
  196. #define _aso_cas8(p,o,n) cas8(p,o,n)
  197. #define _aso_cas16(p,o,n) cas16(p,o,n)
  198. #define _aso_cas32(p,o,n) cas32(p,o,n)
  199. #define _aso_cas64(p,o,n) cas64(p,o,n)
  200. #if _ast_sizeof_pointer == 8
  201. #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,o,n))
  202. #else
  203. #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,o,n))
  204. #endif
  205. }
  206. elif aso note{ <atomic.h> cas32 }end link{
  207. #include "FEATURE/common"
  208. #include <atomic.h>
  209. int main()
  210. {
  211. uint32_t i = 0;
  212. return cas32(&i, 0, 1) != 0 || (atomic_add_32_nv(&i, 1) - 1) != 1;
  213. }
  214. }end && {
  215. #include <atomic.h>
  216. #define _aso_cas8(p,o,n) cas8(p,o,n)
  217. #define _aso_inc8(p) (atomic_add_8_nv(p,1)-1)
  218. #define _aso_dec8(p) (atomic_add_8_nv(p,-1)+1)
  219. #define _aso_cas16(p,o,n) cas16(p,o,n)
  220. #define _aso_inc16(p) (atomic_add_16_nv(p,1)-1)
  221. #define _aso_dec16(p) (atomic_add_16_nv(p,-1)+1)
  222. #define _aso_cas32(p,o,n) cas32(p,o,n)
  223. #define _aso_inc32(p) (atomic_add_32_nv(p,1)-1)
  224. #define _aso_dec32(p) (atomic_add_32_nv(p,-1)+1)
  225. #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,o,n))
  226. }
  227. elif aso note{ <atomic.h> just cas32 }end link{
  228. #include "FEATURE/common"
  229. #include <atomic.h>
  230. int main()
  231. {
  232. uint32_t j = 1;
  233. uint16_t k = 1;
  234. uint8_t l = 1;
  235. return cas32(&j, 0, 1) != 0 || cas16(&k, 0, 1) != 0 || cas8(&l, 0, 1) != 0;
  236. }
  237. }end && {
  238. #include <atomic.h>
  239. #define _aso_cas8(p,o,n) cas8(p,o,n)
  240. #define _aso_cas16(p,o,n) cas16(p,o,n)
  241. #define _aso_cas32(p,o,n) cas32(p,o,n)
  242. #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,o,n))
  243. }
  244. elif aso note{ winix Interlocked }end link{
  245. #include <windows.h>
  246. int main()
  247. {
  248. LONG i = 0;
  249. LONGLONG j = 0;
  250. return InterlockedCompareExchange(&i, 1, 0) != 0 ||
  251. InterlockedIncrement(&i) != 1 ||
  252. InterlockedDecrement(&i) != 2;
  253. }
  254. }end && {
  255. #include <ast_windows.h>
  256. #define _aso_cas32(p,o,n) InterlockedCompareExchange((LONG volatile*)p,n,o)
  257. #define _aso_inc32(p) (InterlockedIncrement((LONG volatile*)p)-1)
  258. #define _aso_dec32(p) (InterlockedDecrement((LONG volatile*)p)+1)
  259. #if _X64
  260. #define _aso_cas64(p,o,n) InterlockedCompareExchange64((LONGLONG volatile*)p,n,o)
  261. #define _aso_inc64(p) (InterlockedIncrement64((LONGLONG volatile*)p)-1)
  262. #define _aso_dec64(p) (InterlockedDecrement64((LONGLONG volatile*)p)+1)
  263. #define _aso_casptr(p,o,n) ((void*)InterlockedCompareExchange64((LONGLONG volatile*)p,n,o))
  264. #else
  265. #if _BLD_posix
  266. #include "dl.h"
  267. typedef struct LL_s
  268. {
  269. LONG a;
  270. LONG b;
  271. } LL_t;
  272. typedef union
  273. {
  274. LONGLONG i;
  275. LL_t ll;
  276. } LL_u;
  277. #define _aso_cas64(p,o,n) _aso_InterlockedCompareExchange64((LONGLONG volatile*)p,n,o)
  278. static LONGLONG _aso_InterlockedCompareExchange64_init(LONGLONG volatile*, LONGLONG, LONGLONG);
  279. typedef LONGLONG (*_aso_InterlockedCompareExchange64_f)(LONGLONG volatile*, LONGLONG, LONGLONG);
  280. static _aso_InterlockedCompareExchange64_f _aso_InterlockedCompareExchange64 = _aso_InterlockedCompareExchange64_init;
  281. static LONGLONG _aso_InterlockedCompareExchange64_32(LONGLONG volatile* p, LONGLONG o, LONGLONG n)
  282. {
  283. LL_t* lp = (LL_t*)p;
  284. LL_t* op = (LL_t*)&o;
  285. LL_t* np = (LL_t*)&n;
  286. LONGLONG r;
  287. r = *p;
  288. if (_aso_cas32(&lp->a, op->a, np->a) == op->a)
  289. {
  290. if (_aso_cas32(&lp->b, op->b, np->b) == op->b)
  291. return o;
  292. _aso_cas32(&lp->a, np->a, op->a);
  293. }
  294. return r;
  295. }
  296. static LONGLONG _aso_InterlockedCompareExchange64_init(LONGLONG volatile* p, LONGLONG o, LONGLONG n)
  297. {
  298. if (!(_aso_InterlockedCompareExchange64 = (_aso_InterlockedCompareExchange64_f)getsymbol(MODULE_kernel, "InterlockedCompareExchange64")))
  299. _aso_InterlockedCompareExchange64 = _aso_InterlockedCompareExchange64_32;
  300. return _aso_InterlockedCompareExchange64(p, o, n);
  301. }
  302. #define _aso_inc64(p) (_aso_InterlockedIncrement64((LONGLONG volatile*)p)-1)
  303. typedef LONGLONG (*_aso_InterlockedIncrement64_f)(LONGLONG volatile*);
  304. static LONGLONG _aso_InterlockedIncrement64_init(LONGLONG volatile*);
  305. static _aso_InterlockedIncrement64_f _aso_InterlockedIncrement64 = _aso_InterlockedIncrement64_init;
  306. static LONGLONG _aso_InterlockedIncrement64_32(LONGLONG volatile* p)
  307. {
  308. LONGLONG o;
  309. do
  310. {
  311. o = *p;
  312. } while (_aso_InterlockedCompareExchange64_32(p, o, o + 1) != o);
  313. return o;
  314. }
  315. static LONGLONG _aso_InterlockedIncrement64_init(LONGLONG volatile* p)
  316. {
  317. if (!(_aso_InterlockedIncrement64 = (_aso_InterlockedIncrement64_f)getsymbol(MODULE_kernel, "InterlockedIncrement64")))
  318. _aso_InterlockedIncrement64 = _aso_InterlockedIncrement64_32;
  319. return _aso_InterlockedIncrement64(p);
  320. }
  321. #define _aso_dec64(p) (_aso_InterlockedDecrement64((LONGLONG volatile*)p)+1)
  322. typedef LONGLONG (*_aso_InterlockedDecrement64_f)(LONGLONG volatile*);
  323. static LONGLONG _aso_InterlockedDecrement64_init(LONGLONG volatile*);
  324. static _aso_InterlockedDecrement64_f _aso_InterlockedDecrement64 = _aso_InterlockedDecrement64_init;
  325. static LONGLONG _aso_InterlockedDecrement64_32(LONGLONG volatile* p)
  326. {
  327. LONGLONG o;
  328. do
  329. {
  330. o = *p;
  331. } while (_aso_InterlockedCompareExchange64_32(p, o, o - 1) != o);
  332. return o;
  333. }
  334. static LONGLONG _aso_InterlockedDecrement64_init(LONGLONG volatile* p)
  335. {
  336. if (!(_aso_InterlockedDecrement64 = (_aso_InterlockedDecrement64_f)getsymbol(MODULE_kernel, "InterlockedDecrement64")))
  337. _aso_InterlockedDecrement64 = _aso_InterlockedDecrement64_32;
  338. return _aso_InterlockedDecrement64(p);
  339. }
  340. #endif
  341. #define _aso_casptr(p,o,n) ((void*)InterlockedCompareExchange((LONG volatile*)p,n,o))
  342. #endif
  343. }
  344. elif aso note{ AIX fetch and add }end link{
  345. #include <sys/atomic_op.h>
  346. int main()
  347. {
  348. int i = 0;
  349. return fetch_and_add((atomic_p)&i,1);
  350. }
  351. }end && {
  352. #include <sys/atomic_op.h>
  353. #define _aso_incint(p) fetch_and_add((atomic_p)p,1)
  354. #define _aso_decint(p) fetch_and_add((atomic_p)p,-1)
  355. #define _aso_casint(p,o,n) (compare_and_swap((atomic_p)p,(int*)&o,(int)n) ? o : *p)
  356. #if _ast_sizeof_pointer == 8
  357. #define _aso_casptr(p,o,n) (compare_and_swaplp((atomic_l)p,(long*)&o,n) ? o : *(void**)p)
  358. #else
  359. #define _aso_casptr(p,o,n) (compare_and_swap((atomic_p)p,(int*)&o,n) ? o : *(void**)p)
  360. #endif
  361. }
  362. elif aso note{ MIPS compare and swap }end link{
  363. int main()
  364. {
  365. int i = 1;
  366. return __compare_and_swap(&i, 0, 1) != 1;
  367. }
  368. }end && {
  369. #define _aso_cas32(p,o,n) (__compare_and_swap(p,o,n) ? o : *p)
  370. #define _aso_casptr(p,o,n) (__compare_and_swap((long*)p,o,n) ? o : *(void**)p)
  371. }
  372. elif aso note{ i386|i386-64 asm compare and swap }end link{
  373. #include "FEATURE/common"
  374. static uint32_t
  375. cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
  376. {
  377. uint32_t r;
  378. __asm__ __volatile__ (
  379. "lock ; cmpxchg %3,%4"
  380. : "=a"(r), "=m"(*p)
  381. : "0"(o), "q"(n), "m"(*p)
  382. : "memory", "cc"
  383. );
  384. return r;
  385. }
  386. #if _ast_sizeof_pointer == 8
  387. static uint64_t
  388. cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
  389. {
  390. uint64_t r;
  391. __asm__ __volatile__ (
  392. "lock ; cmpxchg %3,%4"
  393. : "=a"(r), "=m"(*p)
  394. : "0"(o), "q"(n), "m"(*p)
  395. : "memory", "cc"
  396. );
  397. return r;
  398. }
  399. #else
  400. #define cas64(p,o,n) (*(p))
  401. #endif
  402. int main()
  403. {
  404. uint32_t i = 0;
  405. uint64_t j = 0;
  406. return cas32(&i, 0, 1) || cas64(&j, 0, 1);
  407. }
  408. }end && {
  409. static uint32_t
  410. cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
  411. {
  412. uint32_t r;
  413. __asm__ __volatile__ (
  414. "lock ; cmpxchg %3,%4"
  415. : "=a"(r), "=m"(*p)
  416. : "0"(o), "q"(n), "m"(*p)
  417. : "memory", "cc"
  418. );
  419. return r;
  420. }
  421. #if _ast_sizeof_pointer == 8
  422. static uint64_t
  423. cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
  424. {
  425. uint64_t r;
  426. __asm__ __volatile__ (
  427. "lock ; cmpxchg %3,%4"
  428. : "=a"(r), "=m"(*p)
  429. : "0"(o), "q"(n), "m"(*p)
  430. : "memory", "cc"
  431. );
  432. return r;
  433. }
  434. #endif
  435. #define _aso_cas32(p,o,n) cas32(p,o,n)
  436. #if _ast_sizeof_pointer == 8
  437. #define _aso_cas64(p,o,n) cas64(p,o,n)
  438. #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,o,n))
  439. #else
  440. #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,o,n))
  441. #endif
  442. }
  443. elif aso note{ ia64 asm compare and swap }end link{
  444. #include "FEATURE/common"
  445. static uint32_t
  446. cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
  447. {
  448. uint32_t r;
  449. __asm__ __volatile__ (
  450. "zxt4 %3=%3 ;; mov ar.ccv=%3 ;; cmpxchg4.acq %0=%1,%2,ar.ccv"
  451. : "=r"(r), "+S"(*p)
  452. : "r"(n), "r"(o) : "memory"
  453. );
  454. return r;
  455. }
  456. static uint64_t
  457. cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
  458. {
  459. uint64_t r;
  460. __asm__ __volatile__ (
  461. "mov ar.ccv=%3 ;; cmpxchg8.acq %0=%1,%2,ar.ccv"
  462. : "=r"(r), "+S"(*p)
  463. : "r"(n), "r"(o) : "memory"
  464. );
  465. return r;
  466. }
  467. int main()
  468. {
  469. uint32_t i = 0;
  470. uint64_t j = 0;
  471. return cas32(&i, 0, 1) || cas64(&j, 0, 1);
  472. }
  473. }end && {
  474. static uint32_t
  475. cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
  476. {
  477. uint32_t r;
  478. __asm__ __volatile__ (
  479. "zxt4 %3=%3 ;; mov ar.ccv=%3 ;; cmpxchg4.acq %0=%1,%2,ar.ccv"
  480. : "=r"(r), "+S"(*p)
  481. : "r"(n), "r"(o) : "memory"
  482. );
  483. return r;
  484. }
  485. static uint64_t
  486. cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
  487. {
  488. uint64_t r;
  489. __asm__ __volatile__ (
  490. "mov ar.ccv=%3 ;; cmpxchg8.acq %0=%1,%2,ar.ccv"
  491. : "=r"(r), "+S"(*p)
  492. : "r"(n), "r"(o) : "memory"
  493. );
  494. return r;
  495. }
  496. #define _aso_cas32(p,o,n) cas32(p,o,n)
  497. #define _aso_cas64(p,o,n) cas64(p,o,n)
  498. #if _ast_sizeof_pointer == 8
  499. #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,o,n))
  500. #else
  501. #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,o,n))
  502. #endif
  503. }
  504. elif aso note{ ppc asm compare and swap }end link{
  505. #include "FEATURE/common"
  506. static uint32_t
  507. cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
  508. {
  509. int r;
  510. __asm__ __volatile__ (
  511. "0: lwarx %0,0,%1 ;"
  512. " xor. %0,%3,%0;"
  513. " bne 1f;"
  514. " stwcx. %2,0,%1;"
  515. " bne- 0b;"
  516. "1:"
  517. : "=&r"(r)
  518. : "r"(p), "r"(n), "r"(o)
  519. : "cr0", "memory"
  520. );
  521. __asm__ __volatile__ ("isync" : : : "memory");
  522. return r ? *p : o;
  523. }
  524. static uint64_t
  525. cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
  526. {
  527. long r;
  528. __asm__ __volatile__ (
  529. "0: ldarx %0,0,%1 ;"
  530. " xor. %0,%3,%0;"
  531. " bne 1f;"
  532. " stdcx. %2,0,%1;"
  533. " bne- 0b;"
  534. "1:"
  535. : "=&r"(r)
  536. : "r"(p), "r"(n), "r"(o)
  537. : "cr0", "memory"
  538. );
  539. __asm__ __volatile__ ("isync" : : : "memory");
  540. return r ? *p : o;
  541. }
  542. int main()
  543. {
  544. uint32_t i = 0;
  545. uint64_t j = 0;
  546. return cas32(&i, 0, 1) || cas64(&j, 0, 1);
  547. }
  548. }end && {
  549. static uint32_t
  550. cas32(uint32_t volatile* p, uint32_t o, uint32_t n)
  551. {
  552. int r;
  553. __asm__ __volatile__ (
  554. "0: lwarx %0,0,%1 ;"
  555. " xor. %0,%3,%0;"
  556. " bne 1f;"
  557. " stwcx. %2,0,%1;"
  558. " bne- 0b;"
  559. "1:"
  560. : "=&r"(r)
  561. : "r"(p), "r"(n), "r"(o)
  562. : "cr0", "memory"
  563. );
  564. __asm__ __volatile__ ("isync" : : : "memory");
  565. return r ? *p : o;
  566. }
  567. static uint64_t
  568. cas64(uint64_t volatile* p, uint64_t o, uint64_t n)
  569. {
  570. long r;
  571. __asm__ __volatile__ (
  572. "0: ldarx %0,0,%1 ;"
  573. " xor. %0,%3,%0;"
  574. " bne 1f;"
  575. " stdcx. %2,0,%1;"
  576. " bne- 0b;"
  577. "1:"
  578. : "=&r"(r)
  579. : "r"(p), "r"(n), "r"(o)
  580. : "cr0", "memory"
  581. );
  582. __asm__ __volatile__ ("isync" : : : "memory");
  583. return r ? *p : o;
  584. }
  585. #define _aso_cas32(p,o,n) cas32(p,o,n)
  586. #define _aso_cas64(p,o,n) cas64(p,o,n)
  587. #if _ast_sizeof_pointer == 8
  588. #define _aso_casptr(p,o,n) ((void*)cas64((uint64_t*)p,o,n))
  589. #else
  590. #define _aso_casptr(p,o,n) ((void*)cas32((uint32_t*)p,o,n))
  591. #endif
  592. }
  593. endif