Skip to content

Commit 7c2acea

Browse files
committed
OxCaml runtime: additional atomic primitives
1 parent 9196cfe commit 7c2acea

File tree

2 files changed

+339
-0
lines changed

2 files changed

+339
-0
lines changed

runtime/js/domain.js

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ function caml_atomic_cas_field(b, i, o, n) {
5757
return 0;
5858
}
5959

60+
//Provides: caml_atomic_compare_exchange
61+
//Version: >= 5.2, < 5.3
62+
//OxCaml
63+
function caml_atomic_compare_exchange(ref, o, n) {
64+
var old = ref[1];
65+
if (old === o) ref[1] = n;
66+
return old;
67+
}
68+
6069
//Provides: caml_atomic_fetch_add
6170
//Version: >= 5
6271
function caml_atomic_fetch_add(ref, i) {
@@ -73,6 +82,46 @@ function caml_atomic_fetch_add_field(b, i, n) {
7382
return old;
7483
}
7584

85+
//Provides: caml_atomic_add
86+
//Version: >= 5.2, < 5.3
87+
//OxCaml
88+
function caml_atomic_add(ref, i) {
89+
ref[1] += i;
90+
return 0;
91+
}
92+
93+
//Provides: caml_atomic_sub
94+
//Version: >= 5.2, < 5.3
95+
//OxCaml
96+
function caml_atomic_sub(ref, i) {
97+
ref[1] -= i;
98+
return 0;
99+
}
100+
101+
//Provides: caml_atomic_land
102+
//Version: >= 5.2, < 5.3
103+
//OxCaml
104+
function caml_atomic_land(ref, i) {
105+
ref[1] &= i;
106+
return 0;
107+
}
108+
109+
//Provides: caml_atomic_lor
110+
//Version: >= 5.2, < 5.3
111+
//OxCaml
112+
function caml_atomic_lor(ref, i) {
113+
ref[1] |= i;
114+
return 0;
115+
}
116+
117+
//Provides: caml_atomic_lxor
118+
//Version: >= 5.2, < 5.3
119+
//OxCaml
120+
function caml_atomic_lxor(ref, i) {
121+
ref[1] ^= i;
122+
return 0;
123+
}
124+
76125
//Provides: caml_atomic_exchange
77126
//Version: >= 5
78127
function caml_atomic_exchange(ref, v) {
@@ -89,6 +138,14 @@ function caml_atomic_exchange_field(b, i, v) {
89138
return r;
90139
}
91140

141+
//Provides: caml_atomic_set
142+
//Version: >= 5.2, < 5.3
143+
//OxCaml
144+
function caml_atomic_set(ref, v) {
145+
ref[1] = v;
146+
return 0;
147+
}
148+
92149
//Provides: caml_atomic_make_contended
93150
//Version: >= 5.2
94151
function caml_atomic_make_contended(a) {
@@ -165,3 +222,98 @@ function caml_ml_domain_id(_unit) {
165222
function caml_ml_domain_cpu_relax(_unit) {
166223
return 0;
167224
}
225+
226+
//Provides: caml_atomic_load_field
227+
//Version: >= 5.2, < 5.3
228+
//OxCaml
229+
function caml_atomic_load_field(ref, field) {
230+
return ref[field + 1];
231+
}
232+
233+
//Provides: caml_atomic_add_field
234+
//Version: >= 5.2, < 5.3
235+
//OxCaml
236+
function caml_atomic_add_field(ref, field, i) {
237+
ref[field + 1] += i;
238+
return 0;
239+
}
240+
241+
//Provides: caml_atomic_fetch_add_field
242+
//Version: >= 5.2, < 5.3
243+
//OxCaml
244+
function caml_atomic_fetch_add_field(ref, field, i) {
245+
var old = ref[field + 1];
246+
ref[field + 1] += i;
247+
return old;
248+
}
249+
250+
//Provides: caml_atomic_cas_field
251+
//Version: >= 5.2, < 5.3
252+
//OxCaml
253+
function caml_atomic_cas_field(ref, field, o, n) {
254+
if (ref[field + 1] === o) {
255+
ref[field + 1] = n;
256+
return 1;
257+
}
258+
return 0;
259+
}
260+
261+
//Provides: caml_atomic_compare_exchange_field
262+
//Version: >= 5.2, < 5.3
263+
//OxCaml
264+
function caml_atomic_compare_exchange_field(ref, field, o, n) {
265+
var old = ref[field + 1];
266+
if (old === o) {
267+
ref[field + 1] = n;
268+
}
269+
return old;
270+
}
271+
272+
//Provides: caml_atomic_set_field
273+
//Version: >= 5.2, < 5.3
274+
//OxCaml
275+
function caml_atomic_set_field(ref, field, v) {
276+
ref[field + 1] = v;
277+
return 0;
278+
}
279+
280+
//Provides: caml_atomic_exchange_field
281+
//Version: >= 5.2, < 5.3
282+
//OxCaml
283+
function caml_atomic_exchange_field(ref, field, v) {
284+
var old = ref[field + 1];
285+
ref[field + 1] = v;
286+
return old;
287+
}
288+
289+
//Provides: caml_atomic_sub_field
290+
//Version: >= 5.2, < 5.3
291+
//OxCaml
292+
function caml_atomic_sub_field(ref, field, i) {
293+
ref[field + 1] -= i;
294+
return 0;
295+
}
296+
297+
//Provides: caml_atomic_land_field
298+
//Version: >= 5.2, < 5.3
299+
//OxCaml
300+
function caml_atomic_land_field(ref, field, i) {
301+
ref[field + 1] &= i;
302+
return 0;
303+
}
304+
305+
//Provides: caml_atomic_lor_field
306+
//Version: >= 5.2, < 5.3
307+
//OxCaml
308+
function caml_atomic_lor_field(ref, field, i) {
309+
ref[field + 1] |= i;
310+
return 0;
311+
}
312+
313+
//Provides: caml_atomic_lxor_field
314+
//Version: >= 5.2, < 5.3
315+
//OxCaml
316+
function caml_atomic_lxor_field(ref, field, i) {
317+
ref[field + 1] ^= i;
318+
return 0;
319+
}

runtime/wasm/domain.wat

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@
5555
(else
5656
(ref.i31 (i32.const 0)))))
5757

58+
(func (export "caml_atomic_compare_exchange")
59+
(param $ref (ref eq)) (param $o (ref eq)) (param $n (ref eq))
60+
(result (ref eq))
61+
(local $b (ref $block))
62+
(local $old (ref eq))
63+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
64+
(local.set $old (array.get $block (local.get $b) (i32.const 1)))
65+
(if (result (ref eq))
66+
(ref.eq (local.get $old) (local.get $o))
67+
(then
68+
(array.set $block (local.get $b) (i32.const 1) (local.get $n))
69+
(local.get $old))
70+
(else
71+
(local.get $old))))
72+
5873
(func (export "caml_atomic_load") (param (ref eq)) (result (ref eq))
5974
(array.get $block (ref.cast (ref $block) (local.get 0)) (i32.const 1)))
6075

@@ -89,6 +104,61 @@
89104
(i31.get_s (ref.cast (ref i31) (local.get $n))))))
90105
(local.get $old))
91106

107+
(func (export "caml_atomic_add")
108+
(param $ref (ref eq)) (param $i (ref eq)) (result (ref eq))
109+
(local $b (ref $block))
110+
(local $old (ref eq))
111+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
112+
(local.set $old (array.get $block (local.get $b) (i32.const 1)))
113+
(array.set $block (local.get $b) (i32.const 1)
114+
(ref.i31 (i32.add (i31.get_s (ref.cast (ref i31) (local.get $old)))
115+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
116+
(ref.i31 (i32.const 0)))
117+
118+
(func (export "caml_atomic_sub")
119+
(param $ref (ref eq)) (param $i (ref eq)) (result (ref eq))
120+
(local $b (ref $block))
121+
(local $old (ref eq))
122+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
123+
(local.set $old (array.get $block (local.get $b) (i32.const 1)))
124+
(array.set $block (local.get $b) (i32.const 1)
125+
(ref.i31 (i32.sub (i31.get_s (ref.cast (ref i31) (local.get $old)))
126+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
127+
(ref.i31 (i32.const 0)))
128+
129+
(func (export "caml_atomic_land")
130+
(param $ref (ref eq)) (param $i (ref eq)) (result (ref eq))
131+
(local $b (ref $block))
132+
(local $old (ref eq))
133+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
134+
(local.set $old (array.get $block (local.get $b) (i32.const 1)))
135+
(array.set $block (local.get $b) (i32.const 1)
136+
(ref.i31 (i32.and (i31.get_s (ref.cast (ref i31) (local.get $old)))
137+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
138+
(ref.i31 (i32.const 0)))
139+
140+
(func (export "caml_atomic_lor")
141+
(param $ref (ref eq)) (param $i (ref eq)) (result (ref eq))
142+
(local $b (ref $block))
143+
(local $old (ref eq))
144+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
145+
(local.set $old (array.get $block (local.get $b) (i32.const 1)))
146+
(array.set $block (local.get $b) (i32.const 1)
147+
(ref.i31 (i32.or (i31.get_s (ref.cast (ref i31) (local.get $old)))
148+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
149+
(ref.i31 (i32.const 0)))
150+
151+
(func (export "caml_atomic_lxor")
152+
(param $ref (ref eq)) (param $i (ref eq)) (result (ref eq))
153+
(local $b (ref $block))
154+
(local $old (ref eq))
155+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
156+
(local.set $old (array.get $block (local.get $b) (i32.const 1)))
157+
(array.set $block (local.get $b) (i32.const 1)
158+
(ref.i31 (i32.xor (i31.get_s (ref.cast (ref i31) (local.get $old)))
159+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
160+
(ref.i31 (i32.const 0)))
161+
92162
(func (export "caml_atomic_exchange")
93163
(param $ref (ref eq)) (param $v (ref eq)) (result (ref eq))
94164
(local $b (ref $block))
@@ -111,6 +181,15 @@
111181
(array.set $block (local.get $b) (local.get $j) (local.get $v))
112182
(local.get $r))
113183

184+
(func (export "caml_atomic_set")
185+
(param $ref (ref eq)) (param $v (ref eq)) (result (ref eq))
186+
(local $b (ref $block))
187+
(local $r (ref eq))
188+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
189+
(local.set $r (array.get $block (local.get $b) (i32.const 1)))
190+
(array.set $block (local.get $b) (i32.const 1) (local.get $v))
191+
(ref.i31 (i32.const 0)))
192+
114193
(func (export "caml_atomic_make_contended")
115194
(param $v (ref eq)) (result (ref eq))
116195
(array.new_fixed $block 2 (ref.i31 (i32.const 0)) (local.get $v)))
@@ -200,4 +279,112 @@
200279

201280
(func (export "caml_ml_domain_cpu_relax") (param (ref eq)) (result (ref eq))
202281
(ref.i31 (i32.const 0)))
282+
283+
(func (export "caml_atomic_add_field")
284+
(param $ref (ref eq)) (param $field (ref eq)) (param $i (ref eq))
285+
(result (ref eq))
286+
(local $b (ref $block))
287+
(local $idx i32)
288+
(local $old (ref eq))
289+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
290+
(local.set $idx
291+
(i32.add (i31.get_s (ref.cast (ref i31) (local.get $field)))
292+
(i32.const 1)))
293+
(local.set $old (array.get $block (local.get $b) (local.get $idx)))
294+
(array.set $block (local.get $b) (local.get $idx)
295+
(ref.i31 (i32.add (i31.get_s (ref.cast (ref i31) (local.get $old)))
296+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
297+
(ref.i31 (i32.const 0)))
298+
299+
(func (export "caml_atomic_sub_field")
300+
(param $ref (ref eq)) (param $field (ref eq)) (param $i (ref eq))
301+
(result (ref eq))
302+
(local $b (ref $block))
303+
(local $idx i32)
304+
(local $old (ref eq))
305+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
306+
(local.set $idx
307+
(i32.add (i31.get_s (ref.cast (ref i31) (local.get $field)))
308+
(i32.const 1)))
309+
(local.set $old (array.get $block (local.get $b) (local.get $idx)))
310+
(array.set $block (local.get $b) (local.get $idx)
311+
(ref.i31 (i32.sub (i31.get_s (ref.cast (ref i31) (local.get $old)))
312+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
313+
(ref.i31 (i32.const 0)))
314+
315+
(func (export "caml_atomic_land_field")
316+
(param $ref (ref eq)) (param $field (ref eq)) (param $i (ref eq))
317+
(result (ref eq))
318+
(local $b (ref $block))
319+
(local $idx i32)
320+
(local $old (ref eq))
321+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
322+
(local.set $idx
323+
(i32.add (i31.get_s (ref.cast (ref i31) (local.get $field)))
324+
(i32.const 1)))
325+
(local.set $old (array.get $block (local.get $b) (local.get $idx)))
326+
(array.set $block (local.get $b) (local.get $idx)
327+
(ref.i31 (i32.and (i31.get_s (ref.cast (ref i31) (local.get $old)))
328+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
329+
(ref.i31 (i32.const 0)))
330+
331+
(func (export "caml_atomic_lor_field")
332+
(param $ref (ref eq)) (param $field (ref eq)) (param $i (ref eq))
333+
(result (ref eq))
334+
(local $b (ref $block))
335+
(local $idx i32)
336+
(local $old (ref eq))
337+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
338+
(local.set $idx
339+
(i32.add (i31.get_s (ref.cast (ref i31) (local.get $field)))
340+
(i32.const 1)))
341+
(local.set $old (array.get $block (local.get $b) (local.get $idx)))
342+
(array.set $block (local.get $b) (local.get $idx)
343+
(ref.i31 (i32.or (i31.get_s (ref.cast (ref i31) (local.get $old)))
344+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
345+
(ref.i31 (i32.const 0)))
346+
347+
(func (export "caml_atomic_lxor_field")
348+
(param $ref (ref eq)) (param $field (ref eq)) (param $i (ref eq))
349+
(result (ref eq))
350+
(local $b (ref $block))
351+
(local $idx i32)
352+
(local $old (ref eq))
353+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
354+
(local.set $idx
355+
(i32.add (i31.get_s (ref.cast (ref i31) (local.get $field)))
356+
(i32.const 1)))
357+
(local.set $old (array.get $block (local.get $b) (local.get $idx)))
358+
(array.set $block (local.get $b) (local.get $idx)
359+
(ref.i31 (i32.xor (i31.get_s (ref.cast (ref i31) (local.get $old)))
360+
(i31.get_s (ref.cast (ref i31) (local.get $i))))))
361+
(ref.i31 (i32.const 0)))
362+
363+
(func (export "caml_atomic_compare_exchange_field")
364+
(param $ref (ref eq)) (param $field (ref eq)) (param $o (ref eq))
365+
(param $n (ref eq)) (result (ref eq))
366+
(local $b (ref $block))
367+
(local $idx i32)
368+
(local $old (ref eq))
369+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
370+
(local.set $idx
371+
(i32.add (i31.get_s (ref.cast (ref i31) (local.get $field)))
372+
(i32.const 1)))
373+
(local.set $old (array.get $block (local.get $b) (local.get $idx)))
374+
(if (ref.eq (local.get $old) (local.get $o))
375+
(then
376+
(array.set $block (local.get $b) (local.get $idx) (local.get $n))))
377+
(local.get $old))
378+
379+
(func (export "caml_atomic_set_field")
380+
(param $ref (ref eq)) (param $field (ref eq)) (param $v (ref eq))
381+
(result (ref eq))
382+
(local $b (ref $block))
383+
(local $idx i32)
384+
(local.set $b (ref.cast (ref $block) (local.get $ref)))
385+
(local.set $idx
386+
(i32.add (i31.get_s (ref.cast (ref i31) (local.get $field)))
387+
(i32.const 1)))
388+
(array.set $block (local.get $b) (local.get $idx) (local.get $v))
389+
(ref.i31 (i32.const 0)))
203390
)

0 commit comments

Comments
 (0)