diff options
Diffstat (limited to 'byterun/obj.c')
-rw-r--r-- | byterun/obj.c | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/byterun/obj.c b/byterun/obj.c index dcc13ce833..3603c0a8b7 100644 --- a/byterun/obj.c +++ b/byterun/obj.c @@ -55,35 +55,46 @@ CAMLprim value caml_obj_set_tag (value arg, value new_tag) return Val_unit; } +static int obj_update_tag (value blk, int old_tag, int new_tag) +{ + header_t hd; + tag_t tag; + +again: + hd = Hd_val(blk); + tag = Tag_hd(hd); + + if (tag != old_tag) return 0; + if (caml_domain_alone()) { + Tag_val (blk) = new_tag; + return 1; + } + + if (atomic_compare_exchange_strong(Hp_atomic_val(blk), &hd, + (hd & ~0xFF) | new_tag)) + return 1; + + goto again; +} + CAMLprim value caml_obj_update_tag (value blk, value old_tag, value new_tag) { - return Val_unit; + if (obj_update_tag(blk, Int_val(old_tag), Int_val(new_tag))) + return Val_true; + return Val_false; } CAMLprim value caml_obj_forward_lazy (value blk, value fwd) { - header_t hd; - /* Modify field before setting tag */ caml_modify_field(blk, 0, fwd); - again: - hd = Hd_val(blk); /* This function is only called on Lazy_tag objects. The only racy write to * this object is by the GC threads. */ - CAMLassert (Tag_hd(hd) == Lazy_tag); - if (caml_domain_alone()) { - Tag_val (blk) = Forward_tag; - return Val_unit; - } else { - int cas_result = - atomic_compare_exchange_strong(Hp_atomic_val(blk), &hd, - (hd & ~0xFF) | Forward_tag); - if (cas_result) - return Val_unit; - else - goto again; - } + CAMLassert (Tag_val(blk) == Forcing_tag); + obj_update_tag (blk, Forcing_tag, Forward_tag); + + return Val_unit; } |