[compiler-rt] 180d211 - tsan: Adding releaseAcquire() to ThreadClock
Dmitry Vyukov via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 24 03:28:02 PDT 2020
Author: Dmitry Vyukov
Date: 2020-03-24T11:27:46+01:00
New Revision: 180d211770a0a1f82d483433fab007cd4d14cbd9
URL: https://github.com/llvm/llvm-project/commit/180d211770a0a1f82d483433fab007cd4d14cbd9
DIFF: https://github.com/llvm/llvm-project/commit/180d211770a0a1f82d483433fab007cd4d14cbd9.diff
LOG: tsan: Adding releaseAcquire() to ThreadClock
realeaseAcquire() is a new function added to TSan in support of the Go data-race detector.
It's semantics is:
void ThreadClock::releaseAcquire(SyncClock *sc) const {
for (int i = 0; i < kMaxThreads; i++) {
tmp = clock[i];
clock[i] = max(clock[i], sc->clock[i]);
sc->clock[i] = tmp;
}
}
For context see: https://go-review.googlesource.com/c/go/+/220419
Reviewed-in: https://reviews.llvm.org/D76322
Author: dfava (Daniel Fava)
Added:
Modified:
compiler-rt/lib/tsan/go/test.c
compiler-rt/lib/tsan/go/tsan_go.cpp
compiler-rt/lib/tsan/rtl/tsan_clock.cpp
compiler-rt/lib/tsan/rtl/tsan_clock.h
compiler-rt/lib/tsan/rtl/tsan_rtl.h
compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
compiler-rt/lib/tsan/rtl/tsan_stat.h
Removed:
################################################################################
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
index 61be48442c80..787b4c5b7dc1 100644
--- a/compiler-rt/lib/tsan/go/test.c
+++ b/compiler-rt/lib/tsan/go/test.c
@@ -32,6 +32,7 @@ void __tsan_malloc(void *thr, void *pc, void *p, unsigned long sz);
void __tsan_free(void *p, unsigned long sz);
void __tsan_acquire(void *thr, void *addr);
void __tsan_release(void *thr, void *addr);
+void __tsan_release_acquire(void *thr, void *addr);
void __tsan_release_merge(void *thr, void *addr);
void *current_proc;
@@ -77,6 +78,7 @@ int main(void) {
__tsan_func_enter(thr0, (char*)&main + 1);
__tsan_malloc(thr0, (char*)&barfoo + 1, buf, 10);
__tsan_release(thr0, buf);
+ __tsan_release_acquire(thr0, buf);
__tsan_release_merge(thr0, buf);
void *thr1 = 0;
__tsan_go_start(thr0, &thr1, (char*)&barfoo + 1);
diff --git a/compiler-rt/lib/tsan/go/tsan_go.cpp b/compiler-rt/lib/tsan/go/tsan_go.cpp
index f5998c0c7816..77987f43bf54 100644
--- a/compiler-rt/lib/tsan/go/tsan_go.cpp
+++ b/compiler-rt/lib/tsan/go/tsan_go.cpp
@@ -244,6 +244,10 @@ void __tsan_acquire(ThreadState *thr, void *addr) {
Acquire(thr, 0, (uptr)addr);
}
+void __tsan_release_acquire(ThreadState *thr, void *addr) {
+ ReleaseStoreAcquire(thr, 0, (uptr)addr);
+}
+
void __tsan_release(ThreadState *thr, void *addr) {
ReleaseStore(thr, 0, (uptr)addr);
}
diff --git a/compiler-rt/lib/tsan/rtl/tsan_clock.cpp b/compiler-rt/lib/tsan/rtl/tsan_clock.cpp
index 2aeb18df1ed2..7989a90837cd 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_clock.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_clock.cpp
@@ -30,6 +30,14 @@
// dst->clock[i] = max(dst->clock[i], clock[i]);
// }
//
+// void ThreadClock::releaseStoreAcquire(SyncClock *sc) const {
+// for (int i = 0; i < kMaxThreads; i++) {
+// tmp = clock[i];
+// clock[i] = max(clock[i], sc->clock[i]);
+// sc->clock[i] = tmp;
+// }
+// }
+//
// void ThreadClock::ReleaseStore(SyncClock *dst) const {
// for (int i = 0; i < kMaxThreads; i++)
// dst->clock[i] = clock[i];
@@ -177,6 +185,36 @@ void ThreadClock::acquire(ClockCache *c, SyncClock *src) {
}
}
+void ThreadClock::releaseStoreAcquire(ClockCache *c, SyncClock *sc) {
+ DCHECK_LE(nclk_, kMaxTid);
+ DCHECK_LE(dst->size_, kMaxTid);
+
+ if (sc->size_ == 0) {
+ // ReleaseStore will correctly set release_store_tid_,
+ // which can be important for future operations.
+ ReleaseStore(c, sc);
+ return;
+ }
+
+ // Check if we need to resize dst.
+ if (sc->size_ < nclk_)
+ sc->Resize(c, nclk_);
+
+ sc->Unshare(c);
+ // Update sc->clk_.
+ sc->FlushDirty();
+ uptr i = 0;
+ for (ClockElem &ce : *sc) {
+ u64 tmp = clk_[i];
+ clk_[i] = max(ce.epoch, clk_[i]);
+ ce.epoch = tmp;
+ ce.reused = 0;
+ i++;
+ }
+ sc->release_store_tid_ = kInvalidTid;
+ sc->release_store_reused_ = 0;
+}
+
void ThreadClock::release(ClockCache *c, SyncClock *dst) {
DCHECK_LE(nclk_, kMaxTid);
DCHECK_LE(dst->size_, kMaxTid);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_clock.h b/compiler-rt/lib/tsan/rtl/tsan_clock.h
index 6a1d15a2a16d..c66431f54ee4 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_clock.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_clock.h
@@ -134,6 +134,7 @@ class ThreadClock {
uptr size() const;
void acquire(ClockCache *c, SyncClock *src);
+ void releaseStoreAcquire(ClockCache *c, SyncClock *src);
void release(ClockCache *c, SyncClock *dst);
void acq_rel(ClockCache *c, SyncClock *dst);
void ReleaseStore(ClockCache *c, SyncClock *dst);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
index 20f7a99157ab..d3bb61ff87d3 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
@@ -813,10 +813,12 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr);
// approximation of the actual required synchronization.
void AcquireGlobal(ThreadState *thr, uptr pc);
void Release(ThreadState *thr, uptr pc, uptr addr);
+void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr);
void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
void AfterSleep(ThreadState *thr, uptr pc);
void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c);
void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c);
+void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c);
void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c);
void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
index ce6e7cb2c4ef..bca194f064b4 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
@@ -429,6 +429,18 @@ void AcquireGlobal(ThreadState *thr, uptr pc) {
UpdateClockCallback, thr);
}
+void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: ReleaseStoreAcquire %zx\n", thr->tid, addr);
+ if (thr->ignore_sync)
+ return;
+ SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
+ thr->fast_state.IncrementEpoch();
+ // Can't increment epoch w/o writing to the trace as well.
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
+ ReleaseStoreAcquireImpl(thr, pc, &s->clock);
+ s->mtx.Unlock();
+}
+
void Release(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: Release %zx\n", thr->tid, addr);
if (thr->ignore_sync)
@@ -482,6 +494,15 @@ void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) {
StatInc(thr, StatSyncAcquire);
}
+void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) {
+ if (thr->ignore_sync)
+ return;
+ thr->clock.set(thr->fast_state.epoch());
+ thr->fast_synch_epoch = thr->fast_state.epoch();
+ thr->clock.releaseStoreAcquire(&thr->proc()->clock_cache, c);
+ StatInc(thr, StatSyncReleaseStoreAcquire);
+}
+
void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
if (thr->ignore_sync)
return;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.h b/compiler-rt/lib/tsan/rtl/tsan_stat.h
index 94e18bc66df9..8b26a59bb2ed 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_stat.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_stat.h
@@ -68,6 +68,7 @@ enum StatType {
StatSyncDestroyed,
StatSyncAcquire,
StatSyncRelease,
+ StatSyncReleaseStoreAcquire,
// Clocks - acquire.
StatClockAcquire,
More information about the llvm-commits
mailing list