atomic.odin 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. package sync
  2. import "intrinsics"
  3. Ordering :: enum {
  4. Relaxed, // Monotonic
  5. Release,
  6. Acquire,
  7. Acquire_Release,
  8. Sequentially_Consistent,
  9. }
  10. strongest_failure_ordering :: inline proc "contextless" (order: Ordering) -> Ordering {
  11. #complete switch order {
  12. case .Relaxed: return .Relaxed;
  13. case .Release: return .Relaxed;
  14. case .Acquire: return .Acquire;
  15. case .Acquire_Release: return .Acquire;
  16. case .Sequentially_Consistent: return .Sequentially_Consistent;
  17. }
  18. return .Relaxed;
  19. }
  20. fence :: inline proc "contextless" ($order: Ordering) {
  21. #complete switch order {
  22. case .Relaxed: panic("there is no such thing as a relaxed fence");
  23. case .Release: intrinsics.atomic_fence_rel();
  24. case .Acquire: intrinsics.atomic_fence_acq();
  25. case .Acquire_Release: intrinsics.atomic_fence_acqrel();
  26. case .Sequentially_Consistent: intrinsics.atomic_fence();
  27. case: panic("unknown order");
  28. }
  29. }
  30. atomic_store :: inline proc "contextless" (dst: ^$T, val: T, $order: Ordering) {
  31. #complete switch order {
  32. case .Relaxed: intrinsics.atomic_store_relaxed(dst, val);
  33. case .Release: intrinsics.atomic_store_rel(dst, val);
  34. case .Sequentially_Consistent: intrinsics.atomic_store(dst, val);
  35. case .Acquire: panic("there is not such thing as an acquire store");
  36. case .Acquire_Release: panic("there is not such thing as an acquire/release store");
  37. case: panic("unknown order");
  38. }
  39. }
  40. atomic_load :: inline proc "contextless" (dst: ^$T, $order: Ordering) -> T {
  41. #complete switch order {
  42. case .Relaxed: return intrinsics.atomic_load_relaxed(dst);
  43. case .Acquire: return intrinsics.atomic_load_acq(dst);
  44. case .Sequentially_Consistent: return intrinsics.atomic_load(dst);
  45. case .Release: panic("there is no such thing as a release load");
  46. case .Acquire_Release: panic("there is no such thing as an acquire/release load");
  47. }
  48. panic("unknown order");
  49. return T{};
  50. }
  51. atomic_swap :: inline proc "contextless" (dst: ^$T, val: T, $order: Ordering) -> T {
  52. #complete switch order {
  53. case .Relaxed: return intrinsics.atomic_xchg_relaxed(dst, val);
  54. case .Release: return intrinsics.atomic_xchg_rel(dst, val);
  55. case .Acquire: return intrinsics.atomic_xchg_acq(dst, val);
  56. case .Acquire_Release: return intrinsics.atomic_xchg_acqrel(dst, val);
  57. case .Sequentially_Consistent: return intrinsics.atomic_xchg(dst, val);
  58. }
  59. panic("unknown order");
  60. return T{};
  61. }
  62. atomic_compare_exchange :: inline proc "contextless" (dst: ^$T, old, new: T, $success, $failure: Ordering) -> (val: T, ok: bool) {
  63. switch failure {
  64. case .Relaxed:
  65. switch success {
  66. case .Relaxed: return intrinsics.atomic_cxchg_relaxed(dst, old, new);
  67. case .Acquire: return intrinsics.atomic_cxchg_acq_failrelaxed(dst, old, new);
  68. case .Acquire_Release: return intrinsics.atomic_cxchg_acqrel_failrelaxed(dst, old, new);
  69. case .Sequentially_Consistent: return intrinsics.atomic_cxchg_failrelaxed(dst, old, new);
  70. case .Release: return intrinsics.atomic_cxchg_rel(dst, old, new);
  71. case: panic("an unknown ordering combination");
  72. }
  73. case .Acquire:
  74. switch success {
  75. case .Release: return intrinsics.atomic_cxchg_acqrel(dst, old, new);
  76. case .Acquire: return intrinsics.atomic_cxchg_acq(dst, old, new);
  77. case: panic("an unknown ordering combination");
  78. }
  79. case .Sequentially_Consistent:
  80. switch success {
  81. case .Sequentially_Consistent: return intrinsics.atomic_cxchg(dst, old, new);
  82. case: panic("an unknown ordering combination");
  83. }
  84. case .Acquire_Release:
  85. panic("there is not such thing as an acquire/release failure ordering");
  86. case .Release:
  87. switch success {
  88. case .Acquire: return instrinsics.atomic_cxchg_failacq(dst, old, new);
  89. case: panic("an unknown ordering combination");
  90. }
  91. }
  92. return T{}, false;
  93. }
  94. atomic_compare_exchange_weak :: inline proc "contextless" (dst: ^$T, old, new: T, $success, $failure: Ordering) -> (val: T, ok: bool) {
  95. switch failure {
  96. case .Relaxed:
  97. switch success {
  98. case .Relaxed: return intrinsics.atomic_cxchgweak_relaxed(dst, old, new);
  99. case .Acquire: return intrinsics.atomic_cxchgweak_acq_failrelaxed(dst, old, new);
  100. case .Acquire_Release: return intrinsics.atomic_cxchgweak_acqrel_failrelaxed(dst, old, new);
  101. case .Sequentially_Consistent: return intrinsics.atomic_cxchgweak_failrelaxed(dst, old, new);
  102. case .Release: return intrinsics.atomic_cxchgweak_rel(dst, old, new);
  103. case: panic("an unknown ordering combination");
  104. }
  105. case .Acquire:
  106. switch success {
  107. case .Release: return intrinsics.atomic_cxchgweak_acqrel(dst, old, new);
  108. case .Acquire: return intrinsics.atomic_cxchgweak_acq(dst, old, new);
  109. case: panic("an unknown ordering combination");
  110. }
  111. case .Sequentially_Consistent:
  112. switch success {
  113. case .Sequentially_Consistent: return intrinsics.atomic_cxchgweak(dst, old, new);
  114. case: panic("an unknown ordering combination");
  115. }
  116. case .Acquire_Release:
  117. panic("there is not such thing as an acquire/release failure ordering");
  118. case .Release:
  119. switch success {
  120. case .Acquire: return intrinsics.atomic_cxchgweak_failacq(dst, old, new);
  121. case: panic("an unknown ordering combination");
  122. }
  123. }
  124. return T{}, false;
  125. }
  126. atomic_add :: inline proc "contextless" (dst: ^$T, val: T, $order: Ordering) -> T {
  127. #complete switch order {
  128. case .Relaxed: return intrinsics.atomic_add_relaxed(dst, val);
  129. case .Release: return intrinsics.atomic_add_rel(dst, val);
  130. case .Acquire: return intrinsics.atomic_add_acq(dst, val);
  131. case .Acquire_Release: return intrinsics.atomic_add_acqrel(dst, val);
  132. case .Sequentially_Consistent: return intrinsics.atomic_add(dst, val);
  133. }
  134. panic("unknown order");
  135. return T{};
  136. }
  137. atomic_sub :: inline proc "contextless" (dst: ^$T, val: T, $order: Ordering) -> T {
  138. #complete switch order {
  139. case .Relaxed: return intrinsics.atomic_sub_relaxed(dst, val);
  140. case .Release: return intrinsics.atomic_sub_rel(dst, val);
  141. case .Acquire: return intrinsics.atomic_sub_acq(dst, val);
  142. case .Acquire_Release: return intrinsics.atomic_sub_acqrel(dst, val);
  143. case .Sequentially_Consistent: return intrinsics.atomic_sub(dst, val);
  144. }
  145. panic("unknown order");
  146. return T{};
  147. }
  148. atomic_and :: inline proc "contextless" (dst: ^$T, val: T, $order: Ordering) -> T {
  149. #complete switch order {
  150. case .Relaxed: return intrinsics.atomic_and_relaxed(dst, val);
  151. case .Release: return intrinsics.atomic_and_rel(dst, val);
  152. case .Acquire: return intrinsics.atomic_and_acq(dst, val);
  153. case .Acquire_Release: return intrinsics.atomic_and_acqrel(dst, val);
  154. case .Sequentially_Consistent: return intrinsics.atomic_and(dst, val);
  155. }
  156. panic("unknown order");
  157. return T{};
  158. }
  159. atomic_nand :: inline proc "contextless" (dst: ^$T, val: T, $order: Ordering) -> T {
  160. #complete switch order {
  161. case .Relaxed: return intrinsics.atomic_nand_relaxed(dst, val);
  162. case .Release: return intrinsics.atomic_nand_rel(dst, val);
  163. case .Acquire: return intrinsics.atomic_nand_acq(dst, val);
  164. case .Acquire_Release: return intrinsics.atomic_nand_acqrel(dst, val);
  165. case .Sequentially_Consistent: return intrinsics.atomic_nand(dst, val);
  166. }
  167. panic("unknown order");
  168. return T{};
  169. }
  170. atomic_or :: inline proc "contextless" (dst: ^$T, val: T, $order: Ordering) -> T {
  171. #complete switch order {
  172. case .Relaxed: return intrinsics.atomic_or_relaxed(dst, val);
  173. case .Release: return intrinsics.atomic_or_rel(dst, val);
  174. case .Acquire: return intrinsics.atomic_or_acq(dst, val);
  175. case .Acquire_Release: return intrinsics.atomic_or_acqrel(dst, val);
  176. case .Sequentially_Consistent: return intrinsics.atomic_or(dst, val);
  177. }
  178. panic("unknown order");
  179. return T{};
  180. }
  181. atomic_xor :: inline proc "contextless" (dst: ^$T, val: T, $order: Ordering) -> T {
  182. #complete switch order {
  183. case .Relaxed: return intrinsics.atomic_xor_relaxed(dst, val);
  184. case .Release: return intrinsics.atomic_xor_rel(dst, val);
  185. case .Acquire: return intrinsics.atomic_xor_acq(dst, val);
  186. case .Acquire_Release: return intrinsics.atomic_xor_acqrel(dst, val);
  187. case .Sequentially_Consistent: return intrinsics.atomic_xor(dst, val);
  188. }
  189. panic("unknown order");
  190. return T{};
  191. }