tsan: deadlock detector: print 2 stacks per deadlock edge

llvm-svn: 204149
This commit is contained in:
Dmitry Vyukov 2014-03-18 12:53:05 +00:00
parent 7fbceb2a3f
commit b72bc2ec9c
2 changed files with 48 additions and 13 deletions

View File

@ -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;
}

View File

@ -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)