Index: compiler-rt/lib/tsan/go/test.c =================================================================== --- compiler-rt/lib/tsan/go/test.c +++ compiler-rt/lib/tsan/go/test.c @@ -32,6 +32,7 @@ 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 @@ __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); Index: compiler-rt/lib/tsan/go/tsan_go.cpp =================================================================== --- compiler-rt/lib/tsan/go/tsan_go.cpp +++ compiler-rt/lib/tsan/go/tsan_go.cpp @@ -244,6 +244,10 @@ 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); } Index: compiler-rt/lib/tsan/rtl/tsan_clock.h =================================================================== --- compiler-rt/lib/tsan/rtl/tsan_clock.h +++ compiler-rt/lib/tsan/rtl/tsan_clock.h @@ -134,6 +134,7 @@ 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); Index: compiler-rt/lib/tsan/rtl/tsan_clock.cpp =================================================================== --- compiler-rt/lib/tsan/rtl/tsan_clock.cpp +++ 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::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); Index: compiler-rt/lib/tsan/rtl/tsan_rtl.h =================================================================== --- compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -813,10 +813,12 @@ // 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); Index: compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp =================================================================== --- compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp +++ compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp @@ -429,6 +429,18 @@ 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 @@ 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; Index: compiler-rt/lib/tsan/rtl/tsan_stat.h =================================================================== --- compiler-rt/lib/tsan/rtl/tsan_stat.h +++ compiler-rt/lib/tsan/rtl/tsan_stat.h @@ -68,6 +68,7 @@ StatSyncDestroyed, StatSyncAcquire, StatSyncRelease, + StatSyncReleaseStoreAcquire, // Clocks - acquire. StatClockAcquire,