summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2014-02-21 15:07:18 +0000
committerKostya Serebryany <kcc@google.com>2014-02-21 15:07:18 +0000
commitde60b3af716f062752e1dee410de1064438a20af (patch)
treee700e86fb5c432ad36724f4d428b8489ef5f00af /lib
parentdec7f55adcd8487a99cca5dbd90205a0fe1e73e7 (diff)
[tsan] add coarse-grained lock around the DeadlockDetector. We can do better than that, but that's a start.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@201861 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/tsan/rtl/tsan_mutex.h1
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc4
-rw-r--r--lib/tsan/rtl/tsan_rtl.h3
-rw-r--r--lib/tsan/rtl/tsan_rtl_mutex.cc34
-rw-r--r--lib/tsan/rtl/tsan_stat.cc1
-rw-r--r--lib/tsan/rtl/tsan_stat.h1
6 files changed, 28 insertions, 16 deletions
diff --git a/lib/tsan/rtl/tsan_mutex.h b/lib/tsan/rtl/tsan_mutex.h
index 4e47d7a31..0cb0e5be4 100644
--- a/lib/tsan/rtl/tsan_mutex.h
+++ b/lib/tsan/rtl/tsan_mutex.h
@@ -31,6 +31,7 @@ enum MutexType {
MutexTypeAtExit,
MutexTypeMBlock,
MutexTypeJavaMBlock,
+ MutexTypeDeadlockDetector,
// This must be the last.
MutexTypeCount
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index b0c2ee35f..408423db2 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -82,7 +82,9 @@ Context::Context()
CreateThreadContext, kMaxTid, kThreadQuarantineSize))
, racy_stacks(MBlockRacyStacks)
, racy_addresses(MBlockRacyAddresses)
- , fired_suppressions(8) {
+ , fired_suppressions(8)
+ , dd_mtx(MutexTypeDeadlockDetector, StatMtxDeadlockDetector) {
+ dd.clear();
}
// The objects are allocated in TLS, so one may rely on zero-initialization.
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index dc7ea0c26..b7090f918 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -549,6 +549,9 @@ struct Context {
// Number of fired suppressions may be large enough.
InternalMmapVector<FiredSuppression> fired_suppressions;
+ __sanitizer::DeadlockDetector<DDBV> dd;
+ Mutex dd_mtx;
+
Flags flags;
u64 stat[StatCnt];
diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc
index 364f4b57c..74aec4e6a 100644
--- a/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -22,11 +22,10 @@
namespace __tsan {
-static __sanitizer::DeadlockDetector<DDBV> g_dd;
-static void EnsureDeadlockDetectorID(ThreadState *thr, SyncVar *s) {
- if (!g_dd.nodeBelongsToCurrentEpoch(s->deadlock_detector_id))
- s->deadlock_detector_id = g_dd.newNode(reinterpret_cast<uptr>(s));
+static void EnsureDeadlockDetectorID(Context *ctx, SyncVar *s) {
+ if (!ctx->dd.nodeBelongsToCurrentEpoch(s->deadlock_detector_id))
+ s->deadlock_detector_id = ctx->dd.newNode(reinterpret_cast<uptr>(s));
}
void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
@@ -61,8 +60,9 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
if (s == 0)
return;
if (common_flags()->detect_deadlocks) {
- if (g_dd.nodeBelongsToCurrentEpoch(s->deadlock_detector_id))
- g_dd.removeNode(s->deadlock_detector_id);
+ Lock lk(&ctx->dd_mtx);
+ if (ctx->dd.nodeBelongsToCurrentEpoch(s->deadlock_detector_id))
+ ctx->dd.removeNode(s->deadlock_detector_id);
s->deadlock_detector_id = 0;
}
if (IsAppMem(addr)) {
@@ -92,11 +92,12 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
}
void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec) {
+ Context *ctx = CTX();
DPrintf("#%d: MutexLock %zx rec=%d\n", thr->tid, addr, rec);
CHECK_GT(rec, 0);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeLock, s->GetId());
if (s->owner_tid == SyncVar::kInvalidTid) {
@@ -119,24 +120,25 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec) {
s->recursion += rec;
thr->mset.Add(s->GetId(), true, thr->fast_state.epoch());
if (common_flags()->detect_deadlocks) {
- EnsureDeadlockDetectorID(thr, s);
- if (g_dd.isHeld(&thr->deadlock_detector_tls, s->deadlock_detector_id)) {
+ Lock lk(&ctx->dd_mtx);
+ EnsureDeadlockDetectorID(ctx, s);
+ if (ctx->dd.isHeld(&thr->deadlock_detector_tls, s->deadlock_detector_id)) {
// FIXME: add tests, handle the real recursive locks.
Printf("ThreadSanitizer: reursive-lock\n");
}
// Printf("MutexLock: %zx\n", s->deadlock_detector_id);
bool has_deadlock =
- g_dd.onLock(&thr->deadlock_detector_tls, s->deadlock_detector_id);
+ ctx->dd.onLock(&thr->deadlock_detector_tls, s->deadlock_detector_id);
if (has_deadlock) {
uptr path[10];
- uptr len = g_dd.findPathToHeldLock(&thr->deadlock_detector_tls,
+ uptr len = ctx->dd.findPathToHeldLock(&thr->deadlock_detector_tls,
s->deadlock_detector_id, path,
ARRAY_SIZE(path));
CHECK_GT(len, 0U); // Hm.. cycle of 10 locks? I'd like to see that.
ThreadRegistryLock l(CTX()->thread_registry);
ScopedReport rep(ReportTypeDeadlock);
for (uptr i = 0; i < len; i++)
- rep.AddMutex(reinterpret_cast<SyncVar*>(g_dd.getData(path[i])));
+ rep.AddMutex(reinterpret_cast<SyncVar*>(ctx->dd.getData(path[i])));
StackTrace trace;
trace.ObtainCurrent(thr, pc);
rep.AddStack(&trace);
@@ -147,10 +149,11 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr, int rec) {
}
int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
+ Context *ctx = CTX();
DPrintf("#%d: MutexUnlock %zx all=%d\n", thr->tid, addr, all);
if (IsAppMem(addr))
MemoryReadAtomic(thr, pc, addr, kSizeLog1);
- SyncVar *s = CTX()->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
thr->fast_state.IncrementEpoch();
TraceAddEvent(thr, thr->fast_state, EventTypeUnlock, s->GetId());
int rec = 0;
@@ -180,9 +183,10 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
}
thr->mset.Del(s->GetId(), true);
if (common_flags()->detect_deadlocks) {
- EnsureDeadlockDetectorID(thr, s);
+ Lock lk(&ctx->dd_mtx);
+ EnsureDeadlockDetectorID(ctx, s);
// Printf("MutexUnlock: %zx\n", s->deadlock_detector_id);
- g_dd.onUnlock(&thr->deadlock_detector_tls,
+ ctx->dd.onUnlock(&thr->deadlock_detector_tls,
s->deadlock_detector_id);
}
s->mtx.Unlock();
diff --git a/lib/tsan/rtl/tsan_stat.cc b/lib/tsan/rtl/tsan_stat.cc
index 4da75589d..010a2317f 100644
--- a/lib/tsan/rtl/tsan_stat.cc
+++ b/lib/tsan/rtl/tsan_stat.cc
@@ -145,6 +145,7 @@ void StatOutput(u64 *stat) {
name[StatMtxAnnotations] = " Annotations ";
name[StatMtxMBlock] = " MBlock ";
name[StatMtxJavaMBlock] = " JavaMBlock ";
+ name[StatMtxDeadlockDetector] = " DeadlockDetector ";
name[StatMtxFD] = " FD ";
Printf("Statistics:\n");
diff --git a/lib/tsan/rtl/tsan_stat.h b/lib/tsan/rtl/tsan_stat.h
index 789c4c725..6453bda5f 100644
--- a/lib/tsan/rtl/tsan_stat.h
+++ b/lib/tsan/rtl/tsan_stat.h
@@ -143,6 +143,7 @@ enum StatType {
StatMtxAtExit,
StatMtxMBlock,
StatMtxJavaMBlock,
+ StatMtxDeadlockDetector,
StatMtxFD,
// This must be the last.