summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sanitizer_common/sanitizer_deadlock_detector2.cc57
-rw-r--r--lib/tsan/dd/dd_rtl.cc4
2 files changed, 48 insertions, 13 deletions
diff --git a/lib/sanitizer_common/sanitizer_deadlock_detector2.cc b/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
index 85d73904e..3e9052ee0 100644
--- a/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
+++ b/lib/sanitizer_common/sanitizer_deadlock_detector2.cc
@@ -43,13 +43,15 @@ struct Link {
u32 id;
u32 seq;
u32 tid;
- u32 stk;
+ u32 stk0;
+ u32 stk1;
- explicit Link(u32 id = 0, u32 seq = 0, u32 tid = 0, u32 stk = 0)
+ explicit Link(u32 id = 0, u32 seq = 0, u32 tid = 0, u32 s0 = 0, u32 s1 = 0)
: id(id)
, seq(seq)
, tid(tid)
- , stk(stk) {
+ , stk0(s0)
+ , stk1(s1) {
}
};
@@ -61,10 +63,15 @@ struct DDPhysicalThread {
Link path[kMaxMutex];
};
+struct ThreadMutex {
+ u32 id;
+ u32 stk;
+};
+
struct DDLogicalThread {
- u64 ctx;
- u32 locked[kMaxNesting];
- int nlocked;
+ u64 ctx;
+ ThreadMutex locked[kMaxNesting];
+ int nlocked;
};
struct Mutex {
@@ -201,7 +208,9 @@ void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {
if (m->id == kNoId)
m->id = allocateId(cb);
- lt->locked[lt->nlocked++] = m->id;
+ ThreadMutex *tm = &lt->locked[lt->nlocked++];
+ tm->id = m->id;
+ tm->stk = cb->Unwind();
if (lt->nlocked == 1) {
VPrintf(3, "#%llu: DD::MutexBeforeLock first mutex\n",
cb->lt->ctx);
@@ -211,7 +220,8 @@ void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {
bool added = false;
Mutex *mtx = getMutex(m->id);
for (int i = 0; i < lt->nlocked - 1; i++) {
- u32 id1 = lt->locked[i];
+ u32 id1 = lt->locked[i].id;
+ u32 stk1 = lt->locked[i].stk;
Mutex *mtx1 = getMutex(id1);
SpinMutexLock l(&mtx1->mtx);
if (mtx1->nlink == kMaxLink) {
@@ -225,7 +235,8 @@ void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {
if (link->seq != mtx->seq) {
link->seq = mtx->seq;
link->tid = lt->ctx;
- link->stk = cb->Unwind();
+ link->stk0 = stk1;
+ link->stk1 = cb->Unwind();
added = true;
VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
cb->lt->ctx, getMutexId(mtx1), m->id);
@@ -239,7 +250,8 @@ void DD::MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) {
link->id = m->id;
link->seq = mtx->seq;
link->tid = lt->ctx;
- link->stk = cb->Unwind();
+ link->stk0 = stk1;
+ link->stk1 = cb->Unwind();
added = true;
VPrintf(3, "#%llu: DD::MutexBeforeLock added %d->%d link\n",
cb->lt->ctx, getMutexId(mtx1), m->id);
@@ -282,7 +294,9 @@ void DD::MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock,
CHECK_LE(lt->nlocked, kMaxNesting);
if (m->id == kNoId)
m->id = allocateId(cb);
- lt->locked[lt->nlocked++] = m->id;
+ ThreadMutex *tm = &lt->locked[lt->nlocked++];
+ tm->id = m->id;
+ tm->stk = cb->Unwind();
}
void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
@@ -301,7 +315,7 @@ void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
CHECK_NE(m->id, kNoId);
int last = lt->nlocked - 1;
for (int i = last; i >= 0; i--) {
- if (cb->lt->locked[i] == m->id) {
+ if (cb->lt->locked[i].id == m->id) {
lt->locked[i] = lt->locked[last];
lt->nlocked--;
break;
@@ -312,14 +326,30 @@ void DD::MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) {
void DD::MutexDestroy(DDCallback *cb, DDMutex *m) {
VPrintf(2, "#%llu: DD::MutexDestroy(%p)\n",
cb->lt->ctx, m);
+ DDLogicalThread *lt = cb->lt;
+
if (m->id == kNoId)
return;
+
+ // Remove the mutex from lt->locked if there.
+ int last = lt->nlocked - 1;
+ for (int i = last; i >= 0; i--) {
+ if (lt->locked[i].id == m->id) {
+ lt->locked[i] = lt->locked[last];
+ lt->nlocked--;
+ break;
+ }
+ }
+
+ // Clear and invalidate the mutex descriptor.
{
Mutex *mtx = getMutex(m->id);
SpinMutexLock l(&mtx->mtx);
mtx->seq++;
mtx->nlink = 0;
}
+
+ // Return id to cache.
{
SpinMutexLock l(&mtx);
free_id.push_back(m->id);
@@ -377,7 +407,8 @@ void DD::Report(DDPhysicalThread *pt, DDLogicalThread *lt, int npath) {
rep->loop[i].thr_ctx = link->tid;
rep->loop[i].mtx_ctx0 = link0->id;
rep->loop[i].mtx_ctx1 = link->id;
- rep->loop[i].stk[1] = link->stk;
+ rep->loop[i].stk[0] = link->stk0;
+ rep->loop[i].stk[1] = link->stk1;
}
pt->report_pending = true;
}
diff --git a/lib/tsan/dd/dd_rtl.cc b/lib/tsan/dd/dd_rtl.cc
index aed9debef..38716d5c3 100644
--- a/lib/tsan/dd/dd_rtl.cc
+++ b/lib/tsan/dd/dd_rtl.cc
@@ -45,8 +45,12 @@ static void ReportDeadlock(Thread *thr, DDReport *rep) {
Printf("Thread %d locks mutex %llu while holding mutex %llu:\n",
rep->loop[i].thr_ctx, rep->loop[i].mtx_ctx1, rep->loop[i].mtx_ctx0);
PrintStackTrace(thr, rep->loop[i].stk[1]);
+ Printf("Mutex %llu was acquired here:\n",
+ rep->loop[i].mtx_ctx0);
+ PrintStackTrace(thr, rep->loop[i].stk[0]);
}
Printf("==============================\n");
+ Die();
}
Callback::Callback(Thread *thr)