summaryrefslogtreecommitdiff
path: root/lib/tsan/rtl/tsan_rtl_mutex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsan/rtl/tsan_rtl_mutex.cc')
-rw-r--r--lib/tsan/rtl/tsan_rtl_mutex.cc128
1 files changed, 84 insertions, 44 deletions
diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc
index cf2e44dd09eec..409391678f013 100644
--- a/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -95,16 +95,13 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec) {
} else if (s->owner_tid == thr->tid) {
CHECK_GT(s->recursion, 0);
} else {
- Printf("ThreadSanitizer WARNING: double lock\n");
+ Printf("ThreadSanitizer WARNING: double lock of mutex %p\n", addr);
PrintCurrentStack(thr, pc);
}
if (s->recursion == 0) {
StatInc(thr, StatMutexLock);
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->clock.acquire(&s->clock);
- StatInc(thr, StatSyncAcquire);
- thr->clock.acquire(&s->read_clock);
- StatInc(thr, StatSyncAcquire);
+ AcquireImpl(thr, pc, &s->clock);
+ AcquireImpl(thr, pc, &s->read_clock);
} else if (!s->is_recursive) {
StatInc(thr, StatMutexRecLock);
}
@@ -125,13 +122,14 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
if (s->recursion == 0) {
if (!s->is_broken) {
s->is_broken = true;
- Printf("ThreadSanitizer WARNING: unlock of unlocked mutex\n");
+ Printf("ThreadSanitizer WARNING: unlock of unlocked mutex %p\n", addr);
PrintCurrentStack(thr, pc);
}
} else if (s->owner_tid != thr->tid) {
if (!s->is_broken) {
s->is_broken = true;
- Printf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
+ Printf("ThreadSanitizer WARNING: mutex %p is unlocked by wrong thread\n",
+ addr);
PrintCurrentStack(thr, pc);
}
} else {
@@ -140,10 +138,7 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
if (s->recursion == 0) {
StatInc(thr, StatMutexUnlock);
s->owner_tid = SyncVar::kInvalidTid;
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->fast_synch_epoch = thr->fast_state.epoch();
- thr->clock.ReleaseStore(&s->clock);
- StatInc(thr, StatSyncRelease);
+ ReleaseStoreImpl(thr, pc, &s->clock);
} else {
StatInc(thr, StatMutexRecUnlock);
}
@@ -163,13 +158,12 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr) {
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRLock, s->GetId());
if (s->owner_tid != SyncVar::kInvalidTid) {
- Printf("ThreadSanitizer WARNING: read lock of a write locked mutex\n");
+ Printf("ThreadSanitizer WARNING: read lock of a write locked mutex %p\n",
+ addr);
PrintCurrentStack(thr, pc);
}
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->clock.acquire(&s->clock);
+ AcquireImpl(thr, pc, &s->clock);
s->last_lock = thr->fast_state.raw();
- StatInc(thr, StatSyncAcquire);
thr->mset.Add(s->GetId(), false, thr->fast_state.epoch());
s->mtx.ReadUnlock();
}
@@ -184,14 +178,11 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
if (s->owner_tid != SyncVar::kInvalidTid) {
- Printf("ThreadSanitizer WARNING: read unlock of a write "
- "locked mutex\n");
+ Printf("ThreadSanitizer WARNING: read unlock of a write locked mutex %p\n",
+ addr);
PrintCurrentStack(thr, pc);
}
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->fast_synch_epoch = thr->fast_state.epoch();
- thr->clock.release(&s->read_clock);
- StatInc(thr, StatSyncRelease);
+ ReleaseImpl(thr, pc, &s->read_clock);
s->mtx.Unlock();
thr->mset.Del(s->GetId(), false);
}
@@ -209,10 +200,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
StatInc(thr, StatMutexReadUnlock);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeRUnlock, s->GetId());
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->fast_synch_epoch = thr->fast_state.epoch();
- thr->clock.release(&s->read_clock);
- StatInc(thr, StatSyncRelease);
+ ReleaseImpl(thr, pc, &s->read_clock);
} else if (s->owner_tid == thr->tid) {
// Seems to be write unlock.
thr->fast_state.IncrementEpoch();
@@ -222,33 +210,37 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
if (s->recursion == 0) {
StatInc(thr, StatMutexUnlock);
s->owner_tid = SyncVar::kInvalidTid;
- // FIXME: Refactor me, plz.
- // The sequence of events is quite tricky and doubled in several places.
- // First, it's a bug to increment the epoch w/o writing to the trace.
- // Then, the acquire/release logic can be factored out as well.
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->fast_synch_epoch = thr->fast_state.epoch();
- thr->clock.ReleaseStore(&s->clock);
- StatInc(thr, StatSyncRelease);
+ ReleaseImpl(thr, pc, &s->clock);
} else {
StatInc(thr, StatMutexRecUnlock);
}
} else if (!s->is_broken) {
s->is_broken = true;
- Printf("ThreadSanitizer WARNING: mutex unlock by another thread\n");
+ Printf("ThreadSanitizer WARNING: mutex %p is unlock by wrong thread\n",
+ addr);
PrintCurrentStack(thr, pc);
}
thr->mset.Del(s->GetId(), write);
s->mtx.Unlock();
}
+void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
+ Context *ctx = CTX();
+ CHECK_GT(thr->in_rtl, 0);
+ DPrintf("#%d: MutexRepair %zx\n", thr->tid, addr);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ s->owner_tid = SyncVar::kInvalidTid;
+ s->recursion = 0;
+ s->mtx.Unlock();
+}
+
void Acquire(ThreadState *thr, uptr pc, uptr addr) {
CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
+ if (thr->ignore_sync)
+ return;
SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, false);
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->clock.acquire(&s->clock);
- StatInc(thr, StatSyncAcquire);
+ AcquireImpl(thr, pc, &s->clock);
s->mtx.ReadUnlock();
}
@@ -262,6 +254,9 @@ static void UpdateClockCallback(ThreadContextBase *tctx_base, void *arg) {
}
void AcquireGlobal(ThreadState *thr, uptr pc) {
+ DPrintf("#%d: AcquireGlobal\n", thr->tid);
+ if (thr->ignore_sync)
+ return;
ThreadRegistryLock l(CTX()->thread_registry);
CTX()->thread_registry->RunCallbackForEachThreadLocked(
UpdateClockCallback, thr);
@@ -270,20 +265,26 @@ void AcquireGlobal(ThreadState *thr, uptr pc) {
void Release(ThreadState *thr, uptr pc, uptr addr) {
CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: Release %zx\n", thr->tid, addr);
+ if (thr->ignore_sync)
+ return;
SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->clock.release(&s->clock);
- StatInc(thr, StatSyncRelease);
+ thr->fast_state.IncrementEpoch();
+ // Can't increment epoch w/o writing to the trace as well.
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
+ ReleaseImpl(thr, pc, &s->clock);
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);
+ if (thr->ignore_sync)
+ return;
SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
- thr->clock.set(thr->tid, thr->fast_state.epoch());
- thr->clock.ReleaseStore(&s->clock);
- StatInc(thr, StatSyncRelease);
+ thr->fast_state.IncrementEpoch();
+ // Can't increment epoch w/o writing to the trace as well.
+ TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0);
+ ReleaseStoreImpl(thr, pc, &s->clock);
s->mtx.Unlock();
}
@@ -298,6 +299,9 @@ static void UpdateSleepClockCallback(ThreadContextBase *tctx_base, void *arg) {
}
void AfterSleep(ThreadState *thr, uptr pc) {
+ DPrintf("#%d: AfterSleep %zx\n", thr->tid);
+ if (thr->ignore_sync)
+ return;
thr->last_sleep_stack_id = CurrentStackId(thr, pc);
ThreadRegistryLock l(CTX()->thread_registry);
CTX()->thread_registry->RunCallbackForEachThreadLocked(
@@ -305,4 +309,40 @@ void AfterSleep(ThreadState *thr, uptr pc) {
}
#endif
+void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) {
+ if (thr->ignore_sync)
+ return;
+ thr->clock.set(thr->tid, thr->fast_state.epoch());
+ thr->clock.acquire(c);
+ StatInc(thr, StatSyncAcquire);
+}
+
+void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
+ if (thr->ignore_sync)
+ return;
+ thr->clock.set(thr->tid, thr->fast_state.epoch());
+ thr->fast_synch_epoch = thr->fast_state.epoch();
+ thr->clock.release(c);
+ StatInc(thr, StatSyncRelease);
+}
+
+void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c) {
+ if (thr->ignore_sync)
+ return;
+ thr->clock.set(thr->tid, thr->fast_state.epoch());
+ thr->fast_synch_epoch = thr->fast_state.epoch();
+ thr->clock.ReleaseStore(c);
+ StatInc(thr, StatSyncRelease);
+}
+
+void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) {
+ if (thr->ignore_sync)
+ return;
+ thr->clock.set(thr->tid, thr->fast_state.epoch());
+ thr->fast_synch_epoch = thr->fast_state.epoch();
+ thr->clock.acq_rel(c);
+ StatInc(thr, StatSyncAcquire);
+ StatInc(thr, StatSyncRelease);
+}
+
} // namespace __tsan