tsan: add ReleaseStore() function that merely copies vector clock rather than combines two clocks
fix clock setup for finalizer goroutine (Go runtime) llvm-svn: 160918
This commit is contained in:
parent
44f9b5343d
commit
904d3f9c06
|
@ -74,5 +74,5 @@ echo as gotsan.s -o race_$SUFFIX.syso
|
|||
as gotsan.s -o race_$SUFFIX.syso
|
||||
|
||||
gcc test.c race_$SUFFIX.syso -lpthread -o test
|
||||
./test
|
||||
TSAN_OPTIONS="exitcode=0" ./test
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ int main(void) {
|
|||
__tsan_read(0, buf, 0);
|
||||
__tsan_free(buf);
|
||||
__tsan_func_exit(0);
|
||||
printf("OK\n");
|
||||
__tsan_fini();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ void __tsan_acquire(int goid, void *addr) {
|
|||
void __tsan_release(int goid, void *addr) {
|
||||
ThreadState *thr = goroutines[goid];
|
||||
thr->in_rtl++;
|
||||
Release(thr, 0, (uptr)addr);
|
||||
ReleaseStore(thr, 0, (uptr)addr);
|
||||
thr->in_rtl--;
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,6 @@ void __tsan_release_merge(int goid, void *addr) {
|
|||
ThreadState *thr = goroutines[goid];
|
||||
thr->in_rtl++;
|
||||
Release(thr, 0, (uptr)addr);
|
||||
//ReleaseMerge(thr, 0, (uptr)addr);
|
||||
thr->in_rtl--;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,14 +88,28 @@ void ThreadClock::release(SyncClock *dst) const {
|
|||
}
|
||||
}
|
||||
|
||||
void ThreadClock::ReleaseStore(SyncClock *dst) const {
|
||||
DCHECK(nclk_ <= kMaxTid);
|
||||
DCHECK(dst->clk_.Size() <= kMaxTid);
|
||||
|
||||
if (dst->clk_.Size() < nclk_)
|
||||
dst->clk_.Resize(nclk_);
|
||||
for (uptr i = 0; i < nclk_; i++)
|
||||
dst->clk_[i] = clk_[i];
|
||||
for (uptr i = nclk_; i < dst->clk_.Size(); i++)
|
||||
dst->clk_[i] = 0;
|
||||
}
|
||||
|
||||
void ThreadClock::acq_rel(SyncClock *dst) {
|
||||
acquire(dst);
|
||||
release(dst);
|
||||
}
|
||||
|
||||
void ThreadClock::Disable() {
|
||||
void ThreadClock::Disable(unsigned tid) {
|
||||
u64 c0 = clk_[tid];
|
||||
for (uptr i = 0; i < kMaxTidInClock; i++)
|
||||
clk_[i] = (u64)-1;
|
||||
clk_[tid] = c0;
|
||||
}
|
||||
|
||||
SyncClock::SyncClock()
|
||||
|
|
|
@ -61,7 +61,7 @@ struct ThreadClock {
|
|||
nclk_ = tid + 1;
|
||||
}
|
||||
|
||||
void Disable();
|
||||
void Disable(unsigned tid);
|
||||
|
||||
uptr size() const {
|
||||
return nclk_;
|
||||
|
@ -70,6 +70,7 @@ struct ThreadClock {
|
|||
void acquire(const SyncClock *src);
|
||||
void release(SyncClock *dst) const;
|
||||
void acq_rel(SyncClock *dst);
|
||||
void ReleaseStore(SyncClock *dst) const;
|
||||
|
||||
private:
|
||||
uptr nclk_;
|
||||
|
|
|
@ -449,6 +449,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
|
|||
|
||||
void Acquire(ThreadState *thr, uptr pc, uptr addr);
|
||||
void Release(ThreadState *thr, uptr pc, uptr addr);
|
||||
void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
|
||||
|
||||
// The hacky call uses custom calling convention and an assembly thunk.
|
||||
// It is considerably faster that a normal call for the caller
|
||||
|
|
|
@ -207,4 +207,14 @@ void Release(ThreadState *thr, uptr pc, uptr addr) {
|
|||
s->mtx.Unlock();
|
||||
}
|
||||
|
||||
void ReleaseStore(ThreadState *thr, uptr pc, uptr addr) {
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: ReleaseStore %zx\n", thr->tid, addr);
|
||||
SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
|
||||
thr->clock.set(thr->tid, thr->fast_state.epoch());
|
||||
thr->clock.ReleaseStore(&s->clock);
|
||||
StatInc(thr, StatSyncRelease);
|
||||
s->mtx.Unlock();
|
||||
}
|
||||
|
||||
} // namespace __tsan
|
||||
|
|
|
@ -299,7 +299,7 @@ void ThreadDetach(ThreadState *thr, uptr pc, int tid) {
|
|||
}
|
||||
|
||||
void ThreadFinalizerGoroutine(ThreadState *thr) {
|
||||
thr->clock.Disable();
|
||||
thr->clock.Disable(thr->tid);
|
||||
}
|
||||
|
||||
void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
|
||||
|
|
Loading…
Reference in New Issue