atomic.odin 6.9 KB

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