@salang/sa 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/bin/sa.js +13 -1
  2. package/package.json +8 -7
  3. package/sa_std/alloc/layout.sal +12 -0
  4. package/sa_std/alloc/prelude.sa +1 -0
  5. package/sa_std/alloc/prelude.sal +1 -0
  6. package/sa_std/alloc/string.sa +3 -0
  7. package/sa_std/alloc/vec.sa +684 -0
  8. package/sa_std/alloc/vec.sal +4 -0
  9. package/sa_std/any.sa +130 -0
  10. package/sa_std/any.sal +23 -0
  11. package/sa_std/array.sa +1876 -0
  12. package/sa_std/ascii.sa +2 -0
  13. package/sa_std/ascii.sal +1 -0
  14. package/sa_std/async.sla +116 -0
  15. package/sa_std/binary_heap.sa +3003 -0
  16. package/sa_std/binary_heap.sal +7 -0
  17. package/sa_std/borrow.sa +171 -0
  18. package/sa_std/borrow.sal +13 -0
  19. package/sa_std/btree_map.sa +2210 -0
  20. package/sa_std/btree_map.sal +11 -0
  21. package/sa_std/btree_set.sa +1072 -0
  22. package/sa_std/btree_set.sal +6 -0
  23. package/sa_std/char.sa +1309 -0
  24. package/sa_std/char.sal +50 -0
  25. package/sa_std/cmp.sa +554 -0
  26. package/sa_std/cmp.sal +14 -0
  27. package/sa_std/collections/binary_heap.sa +1 -0
  28. package/sa_std/collections/btree_map.sa +1 -0
  29. package/sa_std/collections/btree_set.sa +1 -0
  30. package/sa_std/collections/hashmap.sa +1 -0
  31. package/sa_std/collections/hashset.sa +1 -0
  32. package/sa_std/collections/linked_list.sa +1120 -0
  33. package/sa_std/collections/linked_list.sal +10 -0
  34. package/sa_std/collections/prelude.sa +7 -0
  35. package/sa_std/collections/prelude.sal +1 -0
  36. package/sa_std/collections/vec_deque.sa +1 -0
  37. package/sa_std/collections.sal +13 -0
  38. package/sa_std/convert.sa +1115 -0
  39. package/sa_std/convert.sal +24 -0
  40. package/sa_std/core/arc.sa +233 -0
  41. package/sa_std/core/arc.sal +4 -0
  42. package/sa_std/core/ascii.sa +784 -0
  43. package/sa_std/core/ascii.sal +34 -0
  44. package/sa_std/core/bit.sa +41 -0
  45. package/sa_std/core/box.sa +1 -0
  46. package/sa_std/core/box.sal +2 -0
  47. package/sa_std/core/cell.sa +108 -0
  48. package/sa_std/core/cell.sal +5 -0
  49. package/sa_std/core/cleanup.sa +26 -0
  50. package/sa_std/core/control.sa +20 -0
  51. package/sa_std/core/derive.sa +60 -0
  52. package/sa_std/core/derive.sal +1 -0
  53. package/sa_std/core/dispatch.sa +7 -0
  54. package/sa_std/core/dispatch.sal +5 -0
  55. package/sa_std/core/future.sa +777 -0
  56. package/sa_std/core/future.sal +73 -0
  57. package/sa_std/core/hash.sa +48 -0
  58. package/sa_std/core/iter.sa +2805 -0
  59. package/sa_std/core/iter.sal +4 -0
  60. package/sa_std/core/loop.sa +60 -0
  61. package/sa_std/core/mem.sa +220 -0
  62. package/sa_std/core/option.sa +825 -0
  63. package/sa_std/core/option.sal +11 -0
  64. package/sa_std/core/panic.sa +23 -0
  65. package/sa_std/core/panic.sal +12 -0
  66. package/sa_std/core/prelude.sa +18 -0
  67. package/sa_std/core/prelude.sal +18 -0
  68. package/sa_std/core/rc.sa +225 -0
  69. package/sa_std/core/rc.sal +4 -0
  70. package/sa_std/core/refcell.sa +283 -0
  71. package/sa_std/core/refcell.sal +13 -0
  72. package/sa_std/core/result.sa +708 -0
  73. package/sa_std/core/result.sal +6 -0
  74. package/sa_std/core/rust_patterns.sal +295 -0
  75. package/sa_std/core/sa_core.sa +84 -0
  76. package/sa_std/core/slice.sa +4021 -0
  77. package/sa_std/core/slice.sal +7 -0
  78. package/sa_std/core/task.sa +112 -0
  79. package/sa_std/core/task.sal +15 -0
  80. package/sa_std/core/trait_object.sa +26 -0
  81. package/sa_std/core/trait_object.sal +4 -0
  82. package/sa_std/core/waker.sa +289 -0
  83. package/sa_std/core/waker.sal +31 -0
  84. package/sa_std/core/weak.sa +2 -0
  85. package/sa_std/core/weak.sal +4 -0
  86. package/sa_std/cow.sa +3 -0
  87. package/sa_std/cow.sal +2 -0
  88. package/sa_std/cstring.sa +3 -0
  89. package/sa_std/cstring.sal +2 -0
  90. package/sa_std/default.sa +99 -0
  91. package/sa_std/duration.sa +3 -0
  92. package/sa_std/duration.sal +2 -0
  93. package/sa_std/encoding/json.sa +259 -0
  94. package/sa_std/encoding/json.sai +54 -0
  95. package/sa_std/encoding/json.sal +35 -0
  96. package/sa_std/encoding/prelude.sa +1 -0
  97. package/sa_std/encoding/prelude.sal +0 -0
  98. package/sa_std/env.sa +390 -0
  99. package/sa_std/env.sai +25 -0
  100. package/sa_std/error.sa +253 -0
  101. package/sa_std/error.sal +44 -0
  102. package/sa_std/ffi/cstring.sa +3 -0
  103. package/sa_std/ffi/cstring.sal +1 -0
  104. package/sa_std/ffi/prelude.sa +2 -0
  105. package/sa_std/ffi/prelude.sal +2 -0
  106. package/sa_std/ffi.sa +635 -0
  107. package/sa_std/ffi.sal +51 -0
  108. package/sa_std/fmt.sa +2 -0
  109. package/sa_std/fmt.sai +18 -0
  110. package/sa_std/fmt.sal +35 -0
  111. package/sa_std/fs.sa +1023 -0
  112. package/sa_std/fs.sai +127 -0
  113. package/sa_std/fs.sal +51 -0
  114. package/sa_std/future.sa +2 -0
  115. package/sa_std/future.sal +1 -0
  116. package/sa_std/hash.sa +1486 -0
  117. package/sa_std/hash.sal +13 -0
  118. package/sa_std/hashmap.sa +1962 -0
  119. package/sa_std/hashmap.sal +20 -0
  120. package/sa_std/hashset.sa +1004 -0
  121. package/sa_std/hashset.sal +18 -0
  122. package/sa_std/http2.sa +78 -0
  123. package/sa_std/http2.sai +26 -0
  124. package/sa_std/http2.sal +36 -0
  125. package/sa_std/instant.sa +3 -0
  126. package/sa_std/instant.sal +2 -0
  127. package/sa_std/io/buf_reader.sa +43 -0
  128. package/sa_std/io/buf_writer.sa +35 -0
  129. package/sa_std/io/bufio.sa +4 -0
  130. package/sa_std/io/bufio.sal +4 -0
  131. package/sa_std/io/prelude.sa +1 -0
  132. package/sa_std/io/prelude.sal +1 -0
  133. package/sa_std/io/print.sa +2 -0
  134. package/sa_std/io/print.sai +3 -0
  135. package/sa_std/io.sa +925 -0
  136. package/sa_std/io.sai +25 -0
  137. package/sa_std/io.sal +84 -0
  138. package/sa_std/iter.sa +2 -0
  139. package/sa_std/iter.sal +1 -0
  140. package/sa_std/join_handle.sa +3 -0
  141. package/sa_std/join_handle.sal +2 -0
  142. package/sa_std/libsa_async.sa +80 -0
  143. package/sa_std/m_async.sa +137 -0
  144. package/sa_std/m_async.sal +30 -0
  145. package/sa_std/m_async.sla +2 -0
  146. package/sa_std/manually_drop.sa +3 -0
  147. package/sa_std/manually_drop.sal +2 -0
  148. package/sa_std/marker/phantom_data.sa +3 -0
  149. package/sa_std/marker/phantom_data.sal +1 -0
  150. package/sa_std/marker/prelude.sa +4 -0
  151. package/sa_std/marker/prelude.sal +4 -0
  152. package/sa_std/marker.sa +220 -0
  153. package/sa_std/marker.sal +15 -0
  154. package/sa_std/math.sa +84 -0
  155. package/sa_std/math.sai +10 -0
  156. package/sa_std/mem/manually_drop.sa +3 -0
  157. package/sa_std/mem/manually_drop.sal +1 -0
  158. package/sa_std/mem/prelude.sa +2 -0
  159. package/sa_std/mem/prelude.sal +2 -0
  160. package/sa_std/mem.sa +564 -0
  161. package/sa_std/mem.sal +40 -0
  162. package/sa_std/modstate.sai +19 -0
  163. package/sa_std/net.sa +4227 -0
  164. package/sa_std/net.sai +239 -0
  165. package/sa_std/net.sal +159 -0
  166. package/sa_std/netx.sa +85 -0
  167. package/sa_std/netx.sai +11 -0
  168. package/sa_std/netx.sal +39 -0
  169. package/sa_std/nonzero.sa +3 -0
  170. package/sa_std/nonzero.sal +2 -0
  171. package/sa_std/num/nonzero.sa +3 -0
  172. package/sa_std/num/nonzero.sal +1 -0
  173. package/sa_std/num/prelude.sa +3 -0
  174. package/sa_std/num/prelude.sal +3 -0
  175. package/sa_std/num.sa +17302 -0
  176. package/sa_std/num.sai +11 -0
  177. package/sa_std/num.sal +341 -0
  178. package/sa_std/ops.sa +1884 -0
  179. package/sa_std/ops.sal +68 -0
  180. package/sa_std/option.sa +2 -0
  181. package/sa_std/option.sal +1 -0
  182. package/sa_std/os/fd.sa +96 -0
  183. package/sa_std/os/fd.sai +7 -0
  184. package/sa_std/os/fd.sal +11 -0
  185. package/sa_std/os/prelude.sa +2 -0
  186. package/sa_std/os/prelude.sal +1 -0
  187. package/sa_std/os/unix_ffi.sa +271 -0
  188. package/sa_std/panic.sa +1 -0
  189. package/sa_std/panic.sal +1 -0
  190. package/sa_std/path.sa +3170 -0
  191. package/sa_std/path.sal +12 -0
  192. package/sa_std/phantom_data.sa +3 -0
  193. package/sa_std/phantom_data.sal +2 -0
  194. package/sa_std/pin.sa +79 -0
  195. package/sa_std/pin.sal +5 -0
  196. package/sa_std/plugin_async.sa +90 -0
  197. package/sa_std/plugin_async.sal +29 -0
  198. package/sa_std/plugin_async.sla +4 -0
  199. package/sa_std/plugin_http_async.sa +46 -0
  200. package/sa_std/plugin_http_server.sa +61 -0
  201. package/sa_std/plugin_http_server.sla +2 -0
  202. package/sa_std/plugin_sqlite.sa +106 -0
  203. package/sa_std/plugin_sqlite.sla +2 -0
  204. package/sa_std/prelude.sa +60 -0
  205. package/sa_std/prelude.sal +55 -0
  206. package/sa_std/process.sa +916 -0
  207. package/sa_std/process.sai +57 -0
  208. package/sa_std/process.sal +27 -0
  209. package/sa_std/ptr.sa +503 -0
  210. package/sa_std/ptr.sal +2 -0
  211. package/sa_std/result.sa +2 -0
  212. package/sa_std/result.sal +1 -0
  213. package/sa_std/rust_core.sa +51 -0
  214. package/sa_std/rust_core.sal +26 -0
  215. package/sa_std/sa.mod +7 -0
  216. package/sa_std/sort.sa +156 -0
  217. package/sa_std/str.sla +13 -0
  218. package/sa_std/string.sa +12240 -0
  219. package/sa_std/string.sai +25 -0
  220. package/sa_std/string.sal +17 -0
  221. package/sa_std/string_format.sa +269 -0
  222. package/sa_std/sync/atomic.sa +1500 -0
  223. package/sa_std/sync/atomic.sal +45 -0
  224. package/sa_std/sync/barrier.sa +105 -0
  225. package/sa_std/sync/barrier.sal +7 -0
  226. package/sa_std/sync/condvar.sa +240 -0
  227. package/sa_std/sync/condvar.sal +4 -0
  228. package/sa_std/sync/mpsc.sa +758 -0
  229. package/sa_std/sync/mpsc.sal +42 -0
  230. package/sa_std/sync/mpsc_list.sa +255 -0
  231. package/sa_std/sync/mpsc_list.sal +3 -0
  232. package/sa_std/sync/mutex.sa +182 -0
  233. package/sa_std/sync/mutex.sal +7 -0
  234. package/sa_std/sync/once.sa +371 -0
  235. package/sa_std/sync/once.sal +31 -0
  236. package/sa_std/sync/poison.sa +36 -0
  237. package/sa_std/sync/poison.sal +11 -0
  238. package/sa_std/sync/prelude.sa +8 -0
  239. package/sa_std/sync/prelude.sal +7 -0
  240. package/sa_std/sync/rwlock.sa +369 -0
  241. package/sa_std/sync/rwlock.sal +13 -0
  242. package/sa_std/task.sa +2 -0
  243. package/sa_std/task.sal +1 -0
  244. package/sa_std/term.sa +2 -0
  245. package/sa_std/term.sai +10 -0
  246. package/sa_std/term.sal +33 -0
  247. package/sa_std/testing/assert.sai +4 -0
  248. package/sa_std/testing/mock_io.sa +174 -0
  249. package/sa_std/testing/mock_io.sal +5 -0
  250. package/sa_std/testing/prelude.sa +2 -0
  251. package/sa_std/testing/prelude.sal +1 -0
  252. package/sa_std/text/prelude.sa +1 -0
  253. package/sa_std/text/prelude.sal +1 -0
  254. package/sa_std/text/regex.sa +2 -0
  255. package/sa_std/text/regex.sai +9 -0
  256. package/sa_std/text/regex.sal +33 -0
  257. package/sa_std/thread/join_handle.sa +3 -0
  258. package/sa_std/thread/join_handle.sal +1 -0
  259. package/sa_std/thread/prelude.sa +4 -0
  260. package/sa_std/thread/prelude.sal +3 -0
  261. package/sa_std/thread.sa +160 -0
  262. package/sa_std/thread.sai +11 -0
  263. package/sa_std/thread.sal +4 -0
  264. package/sa_std/thread_local.sa +45 -0
  265. package/sa_std/thread_local.sai +9 -0
  266. package/sa_std/time/duration.sa +3 -0
  267. package/sa_std/time/duration.sal +1 -0
  268. package/sa_std/time/instant.sa +3 -0
  269. package/sa_std/time/instant.sal +1 -0
  270. package/sa_std/time/prelude.sa +4 -0
  271. package/sa_std/time/prelude.sal +4 -0
  272. package/sa_std/time.sa +850 -0
  273. package/sa_std/time.sai +37 -0
  274. package/sa_std/time.sal +35 -0
  275. package/sa_std/time.sla +67 -0
  276. package/sa_std/tls_client.sai +39 -0
  277. package/sa_std/vec.sa +5754 -0
  278. package/sa_std/vec.sal +1 -0
  279. package/sa_std/vec_deque.sa +4925 -0
  280. package/sa_std/vec_deque.sal +8 -0
  281. package/sa_std/vec_runtime_macros.sa +11 -0
  282. package/sa_std/ws_client.sai +57 -0
@@ -0,0 +1,45 @@
1
+ #def AtomicBool_SIZE = 1
2
+ #def AtomicBool_value = +0
3
+
4
+ #def AtomicU8_SIZE = 1
5
+ #def AtomicU8_value = +0
6
+
7
+ #def AtomicI8_SIZE = 1
8
+ #def AtomicI8_value = +0
9
+
10
+ #def AtomicU16_SIZE = 2
11
+ #def AtomicU16_value = +0
12
+
13
+ #def AtomicI16_SIZE = 2
14
+ #def AtomicI16_value = +0
15
+
16
+ #def AtomicU32_SIZE = 4
17
+ #def AtomicU32_value = +0
18
+
19
+ #def AtomicI32_SIZE = 4
20
+ #def AtomicI32_value = +0
21
+
22
+ #def AtomicU64_SIZE = 8
23
+ #def AtomicU64_value = +0
24
+
25
+ #def AtomicI64_SIZE = 8
26
+ #def AtomicI64_value = +0
27
+
28
+ #def AtomicUsize_SIZE = 8
29
+ #def AtomicUsize_value = +0
30
+
31
+ #def AtomicIsize_SIZE = 8
32
+ #def AtomicIsize_value = +0
33
+
34
+ #def AtomicPtr_SIZE = 8
35
+ #def AtomicPtr_value = +0
36
+
37
+ #def AtomicOrdering_SIZE = 1
38
+ #def AtomicOrdering_ALIGN = 1
39
+ #def AtomicOrdering_value = +0
40
+
41
+ #def ATOMIC_ORDERING_RELAXED = 0
42
+ #def ATOMIC_ORDERING_RELEASE = 1
43
+ #def ATOMIC_ORDERING_ACQUIRE = 2
44
+ #def ATOMIC_ORDERING_ACQ_REL = 3
45
+ #def ATOMIC_ORDERING_SEQ_CST = 4
@@ -0,0 +1,105 @@
1
+ // Concrete Barrier subset: wait until N waiters arrive, then release.
2
+ // Spin/backoff based (no OS futex). Leader = last waiter to arrive.
3
+ // Scope: single-generation spin barrier for concrete N; not full Rust generation object.
4
+ @import "barrier.sal"
5
+ @import "../time.sai"
6
+
7
+ @__barrier_wait_spin(barrier: ptr) -> u64:
8
+ L_ENTRY:
9
+ n = load barrier+Barrier_n as u64
10
+ prev = atomic_rmw_add barrier+Barrier_count, 1 as u64 seq_cst
11
+ arrived = add prev, 1
12
+ is_leader = eq arrived, n
13
+ br is_leader -> L_LEADER, L_FOLLOWER
14
+
15
+ L_LEADER:
16
+ atomic_store barrier+Barrier_count, 0 as u64 seq_cst
17
+ !barrier
18
+ !arrived
19
+ !prev
20
+ !n
21
+ return 1
22
+
23
+ L_FOLLOWER:
24
+ backoff_slot = stack_alloc 8
25
+ store backoff_slot+0, 1 as u64
26
+ arrived_slot = stack_alloc 8
27
+ store arrived_slot+0, arrived as u64
28
+ !arrived
29
+ !prev
30
+ !n
31
+ jmp L_SPIN
32
+
33
+ L_SPIN:
34
+ cur = atomic_load barrier+Barrier_count as u64 acquire
35
+ // Leader reset count to 0, or a new generation started below our marker.
36
+ done = eq cur, 0
37
+ br done -> L_FOLLOWER_DONE, L_CHECK_GEN
38
+
39
+ L_CHECK_GEN:
40
+ arrived_v = load arrived_slot+0 as u64
41
+ still_waiting = uge cur, arrived_v
42
+ !arrived_v
43
+ br still_waiting -> L_BACKOFF, L_FOLLOWER_DONE
44
+
45
+ L_BACKOFF:
46
+ backoff_ns = load backoff_slot+0 as u64
47
+ call @sa_time_sleep_ns(backoff_ns)
48
+ at_limit = uge backoff_ns, 1024
49
+ br at_limit -> L_KEEP, L_GROW
50
+
51
+ L_GROW:
52
+ next_backoff = shl backoff_ns, 1
53
+ store backoff_slot+0, next_backoff as u64
54
+ !next_backoff
55
+ !at_limit
56
+ !backoff_ns
57
+ !still_waiting
58
+ !done
59
+ !cur
60
+ jmp L_SPIN
61
+
62
+ L_KEEP:
63
+ !at_limit
64
+ !backoff_ns
65
+ !still_waiting
66
+ !done
67
+ !cur
68
+ jmp L_SPIN
69
+
70
+ L_FOLLOWER_DONE:
71
+ !barrier
72
+ return 0
73
+
74
+ [MACRO] BARRIER_NEW %out_barrier, %n
75
+ %out_barrier = alloc Barrier_SIZE
76
+ __barrier_n_zero_%out_barrier = eq %n, 0
77
+ __barrier_n_norm_%out_barrier = add %n, __barrier_n_zero_%out_barrier
78
+ store %out_barrier+Barrier_n, __barrier_n_norm_%out_barrier as u64
79
+ store %out_barrier+Barrier_count, 0 as u64
80
+ !__barrier_n_norm_%out_barrier
81
+ !__barrier_n_zero_%out_barrier
82
+ [END_MACRO]
83
+
84
+ [MACRO] BARRIER_WAIT %out_is_leader, %barrier_reg
85
+ %out_is_leader = call @__barrier_wait_spin(%barrier_reg)
86
+ [END_MACRO]
87
+
88
+ [MACRO] BARRIER_N %out_n, %barrier_reg
89
+ %out_n = load %barrier_reg+Barrier_n as u64
90
+ [END_MACRO]
91
+
92
+ [MACRO] BARRIER_DEFAULT %out_barrier
93
+ EXPAND BARRIER_NEW %out_barrier, 2
94
+ [END_MACRO]
95
+
96
+ [MACRO] BARRIER_WAIT_RESULT %out_result, %barrier_reg
97
+ %out_result = alloc BarrierWaitResult_SIZE
98
+ __bw_leader_%out_result = call @__barrier_wait_spin(%barrier_reg)
99
+ store %out_result+BarrierWaitResult_is_leader, __bw_leader_%out_result as u64
100
+ !__bw_leader_%out_result
101
+ [END_MACRO]
102
+
103
+ [MACRO] BARRIER_WAIT_RESULT_IS_LEADER %out_bool, %result_reg
104
+ %out_bool = load %result_reg+BarrierWaitResult_is_leader as u64
105
+ [END_MACRO]
@@ -0,0 +1,7 @@
1
+ // Concrete Barrier facade for N waiters (single-generation spin barrier).
2
+ #def Barrier_SIZE = 16
3
+ #def Barrier_n = +0
4
+ #def Barrier_count = +8
5
+
6
+ #def BarrierWaitResult_SIZE = 8
7
+ #def BarrierWaitResult_is_leader = +0
@@ -0,0 +1,240 @@
1
+ // Concrete Condvar subset: notify_one/notify_all + wait with Mutex.
2
+ // Spin/backoff based. Single-thread wait_while(false) is non-blocking.
3
+ @import "condvar.sal"
4
+ @import "mutex.sal"
5
+ @import "mutex.sa"
6
+ @import "../time.sa"
7
+ @import "../time.sai"
8
+
9
+ @__condvar_dec_waiter(cond: ptr) -> u64:
10
+ L_ENTRY:
11
+ waiters = atomic_load cond+Condvar_waiters as u64 acquire
12
+ has_waiter = ne waiters, 0
13
+ br has_waiter -> L_CLAIM, L_EMPTY
14
+ L_CLAIM:
15
+ next_waiters = sub waiters, 1
16
+ old_waiters, released = cmpxchg cond+Condvar_waiters, waiters, next_waiters as u64 seq_cst seq_cst
17
+ br released -> L_DONE, L_RETRY
18
+ L_RETRY:
19
+ !old_waiters
20
+ !next_waiters
21
+ !released
22
+ !has_waiter
23
+ !waiters
24
+ jmp L_ENTRY
25
+ L_EMPTY:
26
+ !has_waiter
27
+ !waiters
28
+ return 0
29
+ L_DONE:
30
+ !old_waiters
31
+ !next_waiters
32
+ !released
33
+ !has_waiter
34
+ !waiters
35
+ return 1
36
+ @__condvar_wait_spin(cond: ptr, mutex: ptr) -> void:
37
+ L_ENTRY:
38
+ old_waiters = atomic_rmw_add cond+Condvar_waiters, 1 as u64 seq_cst
39
+ !old_waiters
40
+ atomic_store mutex+Mutex_lock, 0 as u64 release
41
+ backoff_slot = stack_alloc 8
42
+ store backoff_slot+0, 1 as u64
43
+ jmp L_SPIN
44
+
45
+ L_SPIN:
46
+ note = atomic_load cond+Condvar_notify as u64 acquire
47
+ has_note = ne note, 0
48
+ br has_note -> L_NOTIFIED, L_BACKOFF
49
+
50
+ L_BACKOFF:
51
+ backoff_ns = load backoff_slot+0 as u64
52
+ call @sa_time_sleep_ns(backoff_ns)
53
+ at_limit = uge backoff_ns, 1024
54
+ br at_limit -> L_KEEP, L_GROW
55
+
56
+ L_GROW:
57
+ next_backoff = shl backoff_ns, 1
58
+ store backoff_slot+0, next_backoff as u64
59
+ !next_backoff
60
+ !at_limit
61
+ !backoff_ns
62
+ !has_note
63
+ !note
64
+ jmp L_SPIN
65
+
66
+ L_KEEP:
67
+ !at_limit
68
+ !backoff_ns
69
+ !has_note
70
+ !note
71
+ jmp L_SPIN
72
+
73
+ L_NOTIFIED:
74
+ prev = atomic_rmw_xchg cond+Condvar_notify, 0 as u64 seq_cst
75
+ old_w = call @__condvar_dec_waiter(cond)
76
+ !old_w
77
+ was_all = ugt prev, 1
78
+ br was_all -> L_REARM_ALL, L_RELOCK
79
+
80
+ L_REARM_ALL:
81
+ atomic_store cond+Condvar_notify, 2 as u64 release
82
+ jmp L_RELOCK
83
+
84
+ L_RELOCK:
85
+ call @__mutex_lock_spin(mutex)
86
+ !was_all
87
+ !prev
88
+ !has_note
89
+ !note
90
+ return
91
+
92
+ [MACRO] CONDVAR_NEW %out_cond
93
+ %out_cond = alloc Condvar_SIZE
94
+ store %out_cond+Condvar_waiters, 0 as u64
95
+ store %out_cond+Condvar_notify, 0 as u64
96
+ [END_MACRO]
97
+
98
+ [MACRO] CONDVAR_DEFAULT %out_cond
99
+ EXPAND CONDVAR_NEW %out_cond
100
+ [END_MACRO]
101
+
102
+ [MACRO] CONDVAR_NOTIFY_ONE %cond_reg
103
+ atomic_store %cond_reg+Condvar_notify, 1 as u64 release
104
+ [END_MACRO]
105
+
106
+ [MACRO] CONDVAR_NOTIFY_ALL %cond_reg
107
+ atomic_store %cond_reg+Condvar_notify, 2 as u64 release
108
+ [END_MACRO]
109
+
110
+ [MACRO] CONDVAR_WAIT %cond_reg, %mutex_reg
111
+ call @__condvar_wait_spin(%cond_reg, %mutex_reg)
112
+ [END_MACRO]
113
+
114
+ [MACRO] CONDVAR_WAIT_WHILE %cond_reg, %mutex_reg, %pred_fn
115
+ jmp L_COND_WW_HEAD_%cond_reg
116
+ L_COND_WW_HEAD_%cond_reg:
117
+ __cond_ww_keep_%cond_reg = call %pred_fn(%mutex_reg)
118
+ __cond_ww_done_%cond_reg = eq __cond_ww_keep_%cond_reg, 0
119
+ br __cond_ww_done_%cond_reg -> L_COND_WW_DONE_%cond_reg, L_COND_WW_BODY_%cond_reg
120
+ L_COND_WW_BODY_%cond_reg:
121
+ call @__condvar_wait_spin(%cond_reg, %mutex_reg)
122
+ !__cond_ww_done_%cond_reg
123
+ !__cond_ww_keep_%cond_reg
124
+ jmp L_COND_WW_HEAD_%cond_reg
125
+ L_COND_WW_DONE_%cond_reg:
126
+ !__cond_ww_done_%cond_reg
127
+ !__cond_ww_keep_%cond_reg
128
+ [END_MACRO]
129
+
130
+ [MACRO] CONDVAR_WAITERS %out_count, %cond_reg
131
+ %out_count = atomic_load %cond_reg+Condvar_waiters as u64 acquire
132
+ [END_MACRO]
133
+
134
+ // Timed wait: returns 1 if notified, 0 if timeout. Spins with sleep until deadline.
135
+ @__condvar_wait_timeout_ns(cond: ptr, mutex: ptr, timeout_ns: u64) -> u64:
136
+ L_ENTRY:
137
+ start = call @sa_time_instant_ns()
138
+ old_waiters = atomic_rmw_add cond+Condvar_waiters, 1 as u64 seq_cst
139
+ !old_waiters
140
+ atomic_store mutex+Mutex_lock, 0 as u64 release
141
+ backoff_slot = stack_alloc 8
142
+ store backoff_slot+0, 1 as u64
143
+ jmp L_TO_SPIN
144
+
145
+ L_TO_SPIN:
146
+ note = atomic_load cond+Condvar_notify as u64 acquire
147
+ has_note = ne note, 0
148
+ br has_note -> L_TO_NOTIFIED, L_TO_CHECK
149
+
150
+ L_TO_CHECK:
151
+ now = call @sa_time_instant_ns()
152
+ elapsed = sub now, start
153
+ timed_out = uge elapsed, timeout_ns
154
+ !now
155
+ !elapsed
156
+ br timed_out -> L_TO_TIMEOUT, L_TO_BACKOFF
157
+
158
+ L_TO_BACKOFF:
159
+ backoff_ns = load backoff_slot+0 as u64
160
+ call @sa_time_sleep_ns(backoff_ns)
161
+ at_limit = uge backoff_ns, 1024
162
+ br at_limit -> L_TO_KEEP, L_TO_GROW
163
+
164
+ L_TO_GROW:
165
+ next_backoff = shl backoff_ns, 1
166
+ store backoff_slot+0, next_backoff as u64
167
+ !next_backoff
168
+ !at_limit
169
+ !backoff_ns
170
+ !timed_out
171
+ !has_note
172
+ !note
173
+ jmp L_TO_SPIN
174
+
175
+ L_TO_KEEP:
176
+ !at_limit
177
+ !backoff_ns
178
+ !timed_out
179
+ !has_note
180
+ !note
181
+ jmp L_TO_SPIN
182
+
183
+ L_TO_TIMEOUT:
184
+ old_w = call @__condvar_dec_waiter(cond)
185
+ !old_w
186
+ call @__mutex_lock_spin(mutex)
187
+ !timed_out
188
+ !has_note
189
+ !note
190
+ !start
191
+ !timeout_ns
192
+ !cond
193
+ !mutex
194
+ return 0
195
+
196
+ L_TO_NOTIFIED:
197
+ prev = atomic_rmw_xchg cond+Condvar_notify, 0 as u64 seq_cst
198
+ old_w2 = call @__condvar_dec_waiter(cond)
199
+ !old_w2
200
+ was_all = ugt prev, 1
201
+ br was_all -> L_TO_REARM, L_TO_RELOCK
202
+
203
+ L_TO_REARM:
204
+ atomic_store cond+Condvar_notify, 2 as u64 release
205
+ jmp L_TO_RELOCK
206
+
207
+ L_TO_RELOCK:
208
+ call @__mutex_lock_spin(mutex)
209
+ !was_all
210
+ !prev
211
+ !has_note
212
+ !note
213
+ !start
214
+ !timeout_ns
215
+ !cond
216
+ !mutex
217
+ return 1
218
+
219
+ [MACRO] CONDVAR_WAIT_TIMEOUT_NS %out_notified, %cond_reg, %mutex_reg, %timeout_ns
220
+ %out_notified = call @__condvar_wait_timeout_ns(%cond_reg, %mutex_reg, %timeout_ns)
221
+ [END_MACRO]
222
+
223
+ [MACRO] CONDVAR_WAIT_TIMEOUT_MS %out_notified, %cond_reg, %mutex_reg, %timeout_ms
224
+ EXPAND TIME_CHECKED_MUL_NS __cond_ms_ok_%out_notified, __cond_to_ns_%out_notified, %timeout_ms, Time_NS_PER_MS
225
+ br __cond_ms_ok_%out_notified -> L_CONDVAR_TIMEOUT_MS_OK_%out_notified, L_CONDVAR_TIMEOUT_MS_OVERFLOW_%out_notified
226
+ L_CONDVAR_TIMEOUT_MS_OK_%out_notified:
227
+ EXPAND CONDVAR_WAIT_TIMEOUT_NS %out_notified, %cond_reg, %mutex_reg, __cond_to_ns_%out_notified
228
+ !__cond_to_ns_%out_notified
229
+ !__cond_ms_ok_%out_notified
230
+ jmp L_CONDVAR_TIMEOUT_MS_DONE_%out_notified
231
+ L_CONDVAR_TIMEOUT_MS_OVERFLOW_%out_notified:
232
+ %out_notified = add 0, 0
233
+ !__cond_to_ns_%out_notified
234
+ !__cond_ms_ok_%out_notified
235
+ L_CONDVAR_TIMEOUT_MS_DONE_%out_notified:
236
+ [END_MACRO]
237
+
238
+ [MACRO] CONDVAR_WAIT_TIMEOUT_DURATION_NS %out_notified, %cond_reg, %mutex_reg, %duration_ns
239
+ EXPAND CONDVAR_WAIT_TIMEOUT_NS %out_notified, %cond_reg, %mutex_reg, %duration_ns
240
+ [END_MACRO]
@@ -0,0 +1,4 @@
1
+ // Concrete Condvar facade over spin/backoff notify flags (single-thread testable).
2
+ #def Condvar_SIZE = 16
3
+ #def Condvar_waiters = +0
4
+ #def Condvar_notify = +8