[PATCH] D99434: [TSAN] Honor failure memory orders in AtomicCAS
Dmitry Vyukov via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed May 12 23:48:02 PDT 2021
dvyukov accepted this revision.
dvyukov added a comment.
I don't see any issues now. Thanks for bearing with me.
================
Comment at: compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp:437
+
+ if (success && write_lock)
s->mtx.Unlock();
----------------
"success &&" is unnecessary here right?
I see it's not harmful, but it also makes me a but nervous because we used just the "write_lock" condition when locking, but we use a different one when unlocking. This is not symmetric and have some potential to get out of sync, so I would drop "success &&" part here.
================
Comment at: compiler-rt/lib/tsan/rtl/tsan_interface_atomic.cpp:453
+ // to use load style memory order.
+ s->mtx.ReadUnlock();
+ }
----------------
bruno wrote:
> dvyukov wrote:
> > There is some duplication here between handling of success case and failure case: adding to trace, acquire, unlock. And taking into account that fmo can be seq_cst, we will need even more duplication to fix this, e.g. we may need to do Release and WriteUnlock here.
> > I would structure it along the following lines (it should both handle all cases and avoid duplication at the same time):
> >
> > SyncVar *s = 0;
> > bool write_lock = IsReleaseOrder(mo) || IsReleaseOrder(fmo);
> > if (mo != mo_relaxed || fmo != mo_relaxed)
> > s = ctx->metamap.GetOrCreateAndLock(thr, pc, (uptr)a, write_lock);
> >
> > T cc = *c;
> > T pr = func_cas(a, cc, v);
> > bool success = pr == cc;
> > if (!success) {
> > *c = pr;
> > mo = fmo;
> > }
> > if (s) {
> > thr->fast_state.IncrementEpoch();
> > // Can't increment epoch w/o writing to the trace as well.
> > TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
> > if (IsAcqRelOrder(mo))
> > AcquireReleaseImpl(thr, pc, &s->clock);
> > else if (IsReleaseOrder(mo))
> > ReleaseImpl(thr, pc, &s->clock);
> > else if (IsAcquireOrder(mo))
> > AcquireImpl(thr, pc, &s->clock);
> >
> > if (write_lock)
> > s->mtx.Unlock();
> > else
> > s->mtx.ReadUnlock();
> > }
> > return success;
> fmo cannot be `mo_release` or `mo_acq_rel`, and when it's `mo_seq_cst` my understanding (which could be wrong) is that it has load semantics. @rjmccall @jfb does my understanding makes sense?
>
> With that in mind, `write_lock` only needs to track `IsReleaseOrder(mo)`, which is what the current patch does.
I think you are right. This makes sense.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D99434/new/
https://reviews.llvm.org/D99434
More information about the llvm-commits
mailing list