rseq-s390.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
  2. #define RSEQ_SIG 0x53053053
  3. #define rseq_smp_mb() __asm__ __volatile__ ("bcr 15,0" ::: "memory")
  4. #define rseq_smp_rmb() rseq_smp_mb()
  5. #define rseq_smp_wmb() rseq_smp_mb()
  6. #define rseq_smp_load_acquire(p) \
  7. __extension__ ({ \
  8. __typeof(*p) ____p1 = RSEQ_READ_ONCE(*p); \
  9. rseq_barrier(); \
  10. ____p1; \
  11. })
  12. #define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb()
  13. #define rseq_smp_store_release(p, v) \
  14. do { \
  15. rseq_barrier(); \
  16. RSEQ_WRITE_ONCE(*p, v); \
  17. } while (0)
  18. #ifdef RSEQ_SKIP_FASTPATH
  19. #include "rseq-skip.h"
  20. #else /* !RSEQ_SKIP_FASTPATH */
  21. #ifdef __s390x__
  22. #define LONG_L "lg"
  23. #define LONG_S "stg"
  24. #define LONG_LT_R "ltgr"
  25. #define LONG_CMP "cg"
  26. #define LONG_CMP_R "cgr"
  27. #define LONG_ADDI "aghi"
  28. #define LONG_ADD_R "agr"
  29. #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \
  30. start_ip, post_commit_offset, abort_ip) \
  31. ".pushsection __rseq_table, \"aw\"\n\t" \
  32. ".balign 32\n\t" \
  33. __rseq_str(label) ":\n\t" \
  34. ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
  35. ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \
  36. ".popsection\n\t"
  37. #elif __s390__
  38. #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \
  39. start_ip, post_commit_offset, abort_ip) \
  40. ".pushsection __rseq_table, \"aw\"\n\t" \
  41. ".balign 32\n\t" \
  42. __rseq_str(label) ":\n\t" \
  43. ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
  44. ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) "\n\t" \
  45. ".popsection\n\t"
  46. #define LONG_L "l"
  47. #define LONG_S "st"
  48. #define LONG_LT_R "ltr"
  49. #define LONG_CMP "c"
  50. #define LONG_CMP_R "cr"
  51. #define LONG_ADDI "ahi"
  52. #define LONG_ADD_R "ar"
  53. #endif
  54. #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
  55. __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \
  56. (post_commit_ip - start_ip), abort_ip)
  57. #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
  58. RSEQ_INJECT_ASM(1) \
  59. "larl %%r0, " __rseq_str(cs_label) "\n\t" \
  60. LONG_S " %%r0, %[" __rseq_str(rseq_cs) "]\n\t" \
  61. __rseq_str(label) ":\n\t"
  62. #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \
  63. RSEQ_INJECT_ASM(2) \
  64. "c %[" __rseq_str(cpu_id) "], %[" __rseq_str(current_cpu_id) "]\n\t" \
  65. "jnz " __rseq_str(label) "\n\t"
  66. #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label) \
  67. ".pushsection __rseq_failure, \"ax\"\n\t" \
  68. ".long " __rseq_str(RSEQ_SIG) "\n\t" \
  69. __rseq_str(label) ":\n\t" \
  70. teardown \
  71. "j %l[" __rseq_str(abort_label) "]\n\t" \
  72. ".popsection\n\t"
  73. #define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label) \
  74. ".pushsection __rseq_failure, \"ax\"\n\t" \
  75. __rseq_str(label) ":\n\t" \
  76. teardown \
  77. "j %l[" __rseq_str(cmpfail_label) "]\n\t" \
  78. ".popsection\n\t"
  79. static inline __attribute__((always_inline))
  80. int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
  81. {
  82. RSEQ_INJECT_C(9)
  83. __asm__ __volatile__ goto (
  84. RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
  85. /* Start rseq by storing table entry pointer into rseq_cs. */
  86. RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
  87. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  88. RSEQ_INJECT_ASM(3)
  89. LONG_CMP " %[expect], %[v]\n\t"
  90. "jnz %l[cmpfail]\n\t"
  91. RSEQ_INJECT_ASM(4)
  92. #ifdef RSEQ_COMPARE_TWICE
  93. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  94. LONG_CMP " %[expect], %[v]\n\t"
  95. "jnz %l[error2]\n\t"
  96. #endif
  97. /* final store */
  98. LONG_S " %[newv], %[v]\n\t"
  99. "2:\n\t"
  100. RSEQ_INJECT_ASM(5)
  101. RSEQ_ASM_DEFINE_ABORT(4, "", abort)
  102. : /* gcc asm goto does not allow outputs */
  103. : [cpu_id] "r" (cpu),
  104. [current_cpu_id] "m" (__rseq_abi.cpu_id),
  105. [rseq_cs] "m" (__rseq_abi.rseq_cs),
  106. [v] "m" (*v),
  107. [expect] "r" (expect),
  108. [newv] "r" (newv)
  109. RSEQ_INJECT_INPUT
  110. : "memory", "cc", "r0"
  111. RSEQ_INJECT_CLOBBER
  112. : abort, cmpfail
  113. #ifdef RSEQ_COMPARE_TWICE
  114. , error1, error2
  115. #endif
  116. );
  117. return 0;
  118. abort:
  119. RSEQ_INJECT_FAILED
  120. return -1;
  121. cmpfail:
  122. return 1;
  123. #ifdef RSEQ_COMPARE_TWICE
  124. error1:
  125. rseq_bug("cpu_id comparison failed");
  126. error2:
  127. rseq_bug("expected value comparison failed");
  128. #endif
  129. }
  130. /*
  131. * Compare @v against @expectnot. When it does _not_ match, load @v
  132. * into @load, and store the content of *@v + voffp into @v.
  133. */
  134. static inline __attribute__((always_inline))
  135. int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
  136. off_t voffp, intptr_t *load, int cpu)
  137. {
  138. RSEQ_INJECT_C(9)
  139. __asm__ __volatile__ goto (
  140. RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
  141. /* Start rseq by storing table entry pointer into rseq_cs. */
  142. RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
  143. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  144. RSEQ_INJECT_ASM(3)
  145. LONG_L " %%r1, %[v]\n\t"
  146. LONG_CMP_R " %%r1, %[expectnot]\n\t"
  147. "je %l[cmpfail]\n\t"
  148. RSEQ_INJECT_ASM(4)
  149. #ifdef RSEQ_COMPARE_TWICE
  150. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  151. LONG_L " %%r1, %[v]\n\t"
  152. LONG_CMP_R " %%r1, %[expectnot]\n\t"
  153. "je %l[error2]\n\t"
  154. #endif
  155. LONG_S " %%r1, %[load]\n\t"
  156. LONG_ADD_R " %%r1, %[voffp]\n\t"
  157. LONG_L " %%r1, 0(%%r1)\n\t"
  158. /* final store */
  159. LONG_S " %%r1, %[v]\n\t"
  160. "2:\n\t"
  161. RSEQ_INJECT_ASM(5)
  162. RSEQ_ASM_DEFINE_ABORT(4, "", abort)
  163. : /* gcc asm goto does not allow outputs */
  164. : [cpu_id] "r" (cpu),
  165. [current_cpu_id] "m" (__rseq_abi.cpu_id),
  166. [rseq_cs] "m" (__rseq_abi.rseq_cs),
  167. /* final store input */
  168. [v] "m" (*v),
  169. [expectnot] "r" (expectnot),
  170. [voffp] "r" (voffp),
  171. [load] "m" (*load)
  172. RSEQ_INJECT_INPUT
  173. : "memory", "cc", "r0", "r1"
  174. RSEQ_INJECT_CLOBBER
  175. : abort, cmpfail
  176. #ifdef RSEQ_COMPARE_TWICE
  177. , error1, error2
  178. #endif
  179. );
  180. return 0;
  181. abort:
  182. RSEQ_INJECT_FAILED
  183. return -1;
  184. cmpfail:
  185. return 1;
  186. #ifdef RSEQ_COMPARE_TWICE
  187. error1:
  188. rseq_bug("cpu_id comparison failed");
  189. error2:
  190. rseq_bug("expected value comparison failed");
  191. #endif
  192. }
  193. static inline __attribute__((always_inline))
  194. int rseq_addv(intptr_t *v, intptr_t count, int cpu)
  195. {
  196. RSEQ_INJECT_C(9)
  197. __asm__ __volatile__ goto (
  198. RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
  199. /* Start rseq by storing table entry pointer into rseq_cs. */
  200. RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
  201. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  202. RSEQ_INJECT_ASM(3)
  203. #ifdef RSEQ_COMPARE_TWICE
  204. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  205. #endif
  206. LONG_L " %%r0, %[v]\n\t"
  207. LONG_ADD_R " %%r0, %[count]\n\t"
  208. /* final store */
  209. LONG_S " %%r0, %[v]\n\t"
  210. "2:\n\t"
  211. RSEQ_INJECT_ASM(4)
  212. RSEQ_ASM_DEFINE_ABORT(4, "", abort)
  213. : /* gcc asm goto does not allow outputs */
  214. : [cpu_id] "r" (cpu),
  215. [current_cpu_id] "m" (__rseq_abi.cpu_id),
  216. [rseq_cs] "m" (__rseq_abi.rseq_cs),
  217. /* final store input */
  218. [v] "m" (*v),
  219. [count] "r" (count)
  220. RSEQ_INJECT_INPUT
  221. : "memory", "cc", "r0"
  222. RSEQ_INJECT_CLOBBER
  223. : abort
  224. #ifdef RSEQ_COMPARE_TWICE
  225. , error1
  226. #endif
  227. );
  228. return 0;
  229. abort:
  230. RSEQ_INJECT_FAILED
  231. return -1;
  232. #ifdef RSEQ_COMPARE_TWICE
  233. error1:
  234. rseq_bug("cpu_id comparison failed");
  235. #endif
  236. }
  237. static inline __attribute__((always_inline))
  238. int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
  239. intptr_t *v2, intptr_t newv2,
  240. intptr_t newv, int cpu)
  241. {
  242. RSEQ_INJECT_C(9)
  243. __asm__ __volatile__ goto (
  244. RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
  245. /* Start rseq by storing table entry pointer into rseq_cs. */
  246. RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
  247. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  248. RSEQ_INJECT_ASM(3)
  249. LONG_CMP " %[expect], %[v]\n\t"
  250. "jnz %l[cmpfail]\n\t"
  251. RSEQ_INJECT_ASM(4)
  252. #ifdef RSEQ_COMPARE_TWICE
  253. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  254. LONG_CMP " %[expect], %[v]\n\t"
  255. "jnz %l[error2]\n\t"
  256. #endif
  257. /* try store */
  258. LONG_S " %[newv2], %[v2]\n\t"
  259. RSEQ_INJECT_ASM(5)
  260. /* final store */
  261. LONG_S " %[newv], %[v]\n\t"
  262. "2:\n\t"
  263. RSEQ_INJECT_ASM(6)
  264. RSEQ_ASM_DEFINE_ABORT(4, "", abort)
  265. : /* gcc asm goto does not allow outputs */
  266. : [cpu_id] "r" (cpu),
  267. [current_cpu_id] "m" (__rseq_abi.cpu_id),
  268. [rseq_cs] "m" (__rseq_abi.rseq_cs),
  269. /* try store input */
  270. [v2] "m" (*v2),
  271. [newv2] "r" (newv2),
  272. /* final store input */
  273. [v] "m" (*v),
  274. [expect] "r" (expect),
  275. [newv] "r" (newv)
  276. RSEQ_INJECT_INPUT
  277. : "memory", "cc", "r0"
  278. RSEQ_INJECT_CLOBBER
  279. : abort, cmpfail
  280. #ifdef RSEQ_COMPARE_TWICE
  281. , error1, error2
  282. #endif
  283. );
  284. return 0;
  285. abort:
  286. RSEQ_INJECT_FAILED
  287. return -1;
  288. cmpfail:
  289. return 1;
  290. #ifdef RSEQ_COMPARE_TWICE
  291. error1:
  292. rseq_bug("cpu_id comparison failed");
  293. error2:
  294. rseq_bug("expected value comparison failed");
  295. #endif
  296. }
  297. /* s390 is TSO. */
  298. static inline __attribute__((always_inline))
  299. int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
  300. intptr_t *v2, intptr_t newv2,
  301. intptr_t newv, int cpu)
  302. {
  303. return rseq_cmpeqv_trystorev_storev(v, expect, v2, newv2, newv, cpu);
  304. }
  305. static inline __attribute__((always_inline))
  306. int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
  307. intptr_t *v2, intptr_t expect2,
  308. intptr_t newv, int cpu)
  309. {
  310. RSEQ_INJECT_C(9)
  311. __asm__ __volatile__ goto (
  312. RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
  313. /* Start rseq by storing table entry pointer into rseq_cs. */
  314. RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
  315. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  316. RSEQ_INJECT_ASM(3)
  317. LONG_CMP " %[expect], %[v]\n\t"
  318. "jnz %l[cmpfail]\n\t"
  319. RSEQ_INJECT_ASM(4)
  320. LONG_CMP " %[expect2], %[v2]\n\t"
  321. "jnz %l[cmpfail]\n\t"
  322. RSEQ_INJECT_ASM(5)
  323. #ifdef RSEQ_COMPARE_TWICE
  324. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  325. LONG_CMP " %[expect], %[v]\n\t"
  326. "jnz %l[error2]\n\t"
  327. LONG_CMP " %[expect2], %[v2]\n\t"
  328. "jnz %l[error3]\n\t"
  329. #endif
  330. /* final store */
  331. LONG_S " %[newv], %[v]\n\t"
  332. "2:\n\t"
  333. RSEQ_INJECT_ASM(6)
  334. RSEQ_ASM_DEFINE_ABORT(4, "", abort)
  335. : /* gcc asm goto does not allow outputs */
  336. : [cpu_id] "r" (cpu),
  337. [current_cpu_id] "m" (__rseq_abi.cpu_id),
  338. [rseq_cs] "m" (__rseq_abi.rseq_cs),
  339. /* cmp2 input */
  340. [v2] "m" (*v2),
  341. [expect2] "r" (expect2),
  342. /* final store input */
  343. [v] "m" (*v),
  344. [expect] "r" (expect),
  345. [newv] "r" (newv)
  346. RSEQ_INJECT_INPUT
  347. : "memory", "cc", "r0"
  348. RSEQ_INJECT_CLOBBER
  349. : abort, cmpfail
  350. #ifdef RSEQ_COMPARE_TWICE
  351. , error1, error2, error3
  352. #endif
  353. );
  354. return 0;
  355. abort:
  356. RSEQ_INJECT_FAILED
  357. return -1;
  358. cmpfail:
  359. return 1;
  360. #ifdef RSEQ_COMPARE_TWICE
  361. error1:
  362. rseq_bug("cpu_id comparison failed");
  363. error2:
  364. rseq_bug("1st expected value comparison failed");
  365. error3:
  366. rseq_bug("2nd expected value comparison failed");
  367. #endif
  368. }
  369. static inline __attribute__((always_inline))
  370. int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
  371. void *dst, void *src, size_t len,
  372. intptr_t newv, int cpu)
  373. {
  374. uint64_t rseq_scratch[3];
  375. RSEQ_INJECT_C(9)
  376. __asm__ __volatile__ goto (
  377. RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
  378. LONG_S " %[src], %[rseq_scratch0]\n\t"
  379. LONG_S " %[dst], %[rseq_scratch1]\n\t"
  380. LONG_S " %[len], %[rseq_scratch2]\n\t"
  381. /* Start rseq by storing table entry pointer into rseq_cs. */
  382. RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
  383. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  384. RSEQ_INJECT_ASM(3)
  385. LONG_CMP " %[expect], %[v]\n\t"
  386. "jnz 5f\n\t"
  387. RSEQ_INJECT_ASM(4)
  388. #ifdef RSEQ_COMPARE_TWICE
  389. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
  390. LONG_CMP " %[expect], %[v]\n\t"
  391. "jnz 7f\n\t"
  392. #endif
  393. /* try memcpy */
  394. LONG_LT_R " %[len], %[len]\n\t"
  395. "jz 333f\n\t"
  396. "222:\n\t"
  397. "ic %%r0,0(%[src])\n\t"
  398. "stc %%r0,0(%[dst])\n\t"
  399. LONG_ADDI " %[src], 1\n\t"
  400. LONG_ADDI " %[dst], 1\n\t"
  401. LONG_ADDI " %[len], -1\n\t"
  402. "jnz 222b\n\t"
  403. "333:\n\t"
  404. RSEQ_INJECT_ASM(5)
  405. /* final store */
  406. LONG_S " %[newv], %[v]\n\t"
  407. "2:\n\t"
  408. RSEQ_INJECT_ASM(6)
  409. /* teardown */
  410. LONG_L " %[len], %[rseq_scratch2]\n\t"
  411. LONG_L " %[dst], %[rseq_scratch1]\n\t"
  412. LONG_L " %[src], %[rseq_scratch0]\n\t"
  413. RSEQ_ASM_DEFINE_ABORT(4,
  414. LONG_L " %[len], %[rseq_scratch2]\n\t"
  415. LONG_L " %[dst], %[rseq_scratch1]\n\t"
  416. LONG_L " %[src], %[rseq_scratch0]\n\t",
  417. abort)
  418. RSEQ_ASM_DEFINE_CMPFAIL(5,
  419. LONG_L " %[len], %[rseq_scratch2]\n\t"
  420. LONG_L " %[dst], %[rseq_scratch1]\n\t"
  421. LONG_L " %[src], %[rseq_scratch0]\n\t",
  422. cmpfail)
  423. #ifdef RSEQ_COMPARE_TWICE
  424. RSEQ_ASM_DEFINE_CMPFAIL(6,
  425. LONG_L " %[len], %[rseq_scratch2]\n\t"
  426. LONG_L " %[dst], %[rseq_scratch1]\n\t"
  427. LONG_L " %[src], %[rseq_scratch0]\n\t",
  428. error1)
  429. RSEQ_ASM_DEFINE_CMPFAIL(7,
  430. LONG_L " %[len], %[rseq_scratch2]\n\t"
  431. LONG_L " %[dst], %[rseq_scratch1]\n\t"
  432. LONG_L " %[src], %[rseq_scratch0]\n\t",
  433. error2)
  434. #endif
  435. : /* gcc asm goto does not allow outputs */
  436. : [cpu_id] "r" (cpu),
  437. [current_cpu_id] "m" (__rseq_abi.cpu_id),
  438. [rseq_cs] "m" (__rseq_abi.rseq_cs),
  439. /* final store input */
  440. [v] "m" (*v),
  441. [expect] "r" (expect),
  442. [newv] "r" (newv),
  443. /* try memcpy input */
  444. [dst] "r" (dst),
  445. [src] "r" (src),
  446. [len] "r" (len),
  447. [rseq_scratch0] "m" (rseq_scratch[0]),
  448. [rseq_scratch1] "m" (rseq_scratch[1]),
  449. [rseq_scratch2] "m" (rseq_scratch[2])
  450. RSEQ_INJECT_INPUT
  451. : "memory", "cc", "r0"
  452. RSEQ_INJECT_CLOBBER
  453. : abort, cmpfail
  454. #ifdef RSEQ_COMPARE_TWICE
  455. , error1, error2
  456. #endif
  457. );
  458. return 0;
  459. abort:
  460. RSEQ_INJECT_FAILED
  461. return -1;
  462. cmpfail:
  463. return 1;
  464. #ifdef RSEQ_COMPARE_TWICE
  465. error1:
  466. rseq_bug("cpu_id comparison failed");
  467. error2:
  468. rseq_bug("expected value comparison failed");
  469. #endif
  470. }
  471. /* s390 is TSO. */
  472. static inline __attribute__((always_inline))
  473. int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
  474. void *dst, void *src, size_t len,
  475. intptr_t newv, int cpu)
  476. {
  477. return rseq_cmpeqv_trymemcpy_storev(v, expect, dst, src, len,
  478. newv, cpu);
  479. }
  480. #endif /* !RSEQ_SKIP_FASTPATH */