Skip to content

Commit a5f0405

Browse files
clef-mengasche
authored andcommitted
runtime: Add atomic primitives [caml_atomic_load_field], [caml_atomic_exchange_field] and [caml_atomic_fetch_add_field].
1 parent c7b4b36 commit a5f0405

File tree

1 file changed

+28
-16
lines changed

1 file changed

+28
-16
lines changed

runtime/memory.c

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -314,36 +314,43 @@ CAMLexport CAMLweakdef void caml_initialize (volatile value *fp, value val)
314314
Ref_table_add(&Caml_state->minor_tables->major_ref, fp);
315315
}
316316

317-
318-
CAMLprim value caml_atomic_load (value ref)
317+
CAMLprim value caml_atomic_load_field (value obj, value vfield)
319318
{
319+
intnat field = Long_val(vfield);
320320
if (caml_domain_alone()) {
321-
return Field(ref, 0);
321+
return Field(obj, field);
322322
} else {
323-
value v;
324323
/* See Note [MM] above */
325324
atomic_thread_fence(memory_order_acquire);
326-
v = atomic_load(Op_atomic_val(ref));
327-
return v;
325+
return atomic_load(&Op_atomic_val(obj)[field]);
328326
}
329327
}
328+
CAMLprim value caml_atomic_load (value ref)
329+
{
330+
return caml_atomic_load_field(ref, Val_long(0));
331+
}
330332

331333
/* stores are implemented as exchanges */
332-
CAMLprim value caml_atomic_exchange (value ref, value v)
334+
CAMLprim value caml_atomic_exchange_field (value obj, value vfield, value v)
333335
{
334336
value ret;
337+
intnat field = Long_val(vfield);
335338
if (caml_domain_alone()) {
336-
ret = Field(ref, 0);
337-
Field(ref, 0) = v;
339+
ret = Field(obj, field);
340+
Field(obj, field) = v;
338341
} else {
339342
/* See Note [MM] above */
340343
atomic_thread_fence(memory_order_acquire);
341-
ret = atomic_exchange(Op_atomic_val(ref), v);
344+
ret = atomic_exchange(&Op_atomic_val(obj)[field], v);
342345
atomic_thread_fence(memory_order_release); /* generates `dmb ish` on Arm64*/
343346
}
344-
write_barrier(ref, 0, ret, v);
347+
write_barrier(obj, field, ret, v);
345348
return ret;
346349
}
350+
CAMLprim value caml_atomic_exchange (value ref, value v)
351+
{
352+
return caml_atomic_exchange_field(ref, Val_long(0), v);
353+
}
347354

348355
CAMLexport value caml_atomic_cas_field (
349356
value obj, value vfield, value oldval, value newval)
@@ -377,22 +384,27 @@ CAMLprim value caml_atomic_cas (value ref, value oldval, value newval)
377384
return caml_atomic_cas_field(ref, Val_long(0), oldval, newval);
378385
}
379386

380-
CAMLprim value caml_atomic_fetch_add (value ref, value incr)
387+
CAMLprim value caml_atomic_fetch_add_field (value obj, value vfield, value incr)
381388
{
389+
intnat field = Long_val(vfield);
382390
value ret;
383391
if (caml_domain_alone()) {
384-
value* p = Op_val(ref);
385-
CAMLassert(Is_long(*p));
392+
value* p = &Op_val(obj)[field];
386393
ret = *p;
394+
CAMLassert(Is_long(ret));
387395
*p = Val_long(Long_val(ret) + Long_val(incr));
388396
/* no write barrier needed, integer write */
389397
} else {
390-
atomic_value *p = &Op_atomic_val(ref)[0];
391-
ret = atomic_fetch_add(p, 2*Long_val(incr));
398+
atomic_value *p = &Op_atomic_val(obj)[field];
399+
ret = atomic_fetch_add(p, 2 * Long_val(incr));
392400
atomic_thread_fence(memory_order_release); /* generates `dmb ish` on Arm64*/
393401
}
394402
return ret;
395403
}
404+
CAMLprim value caml_atomic_fetch_add (value ref, value incr)
405+
{
406+
return caml_atomic_fetch_add_field(ref, Val_long(0), incr);
407+
}
396408

397409
CAMLexport void caml_set_fields (value obj, value v)
398410
{

0 commit comments

Comments
 (0)