forked from OSchip/llvm-project
[tsan] in deadlock detector do not register locks on their creation and unregister them on destruction; added a relevant test
llvm-svn: 201568
This commit is contained in:
parent
a50abe6656
commit
aa416c39cd
|
|
@ -45,10 +45,6 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
|
||||||
s->is_rw = rw;
|
s->is_rw = rw;
|
||||||
s->is_recursive = recursive;
|
s->is_recursive = recursive;
|
||||||
s->is_linker_init = linker_init;
|
s->is_linker_init = linker_init;
|
||||||
if (common_flags()->detect_deadlocks) {
|
|
||||||
EnsureDeadlockDetectorID(thr, s);
|
|
||||||
Printf("MutexCreate: %zx\n", s->deadlock_detector_id);
|
|
||||||
}
|
|
||||||
s->mtx.Unlock();
|
s->mtx.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,8 +62,9 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
|
||||||
if (s == 0)
|
if (s == 0)
|
||||||
return;
|
return;
|
||||||
if (common_flags()->detect_deadlocks) {
|
if (common_flags()->detect_deadlocks) {
|
||||||
EnsureDeadlockDetectorID(thr, s);
|
if (s->deadlock_detector_id)
|
||||||
Printf("MutexDestroy: %zx\n", s->deadlock_detector_id);
|
g_deadlock_detector.removeNode(s->deadlock_detector_id);
|
||||||
|
s->deadlock_detector_id = 0;
|
||||||
}
|
}
|
||||||
if (IsAppMem(addr)) {
|
if (IsAppMem(addr)) {
|
||||||
CHECK(!thr->is_freeing);
|
CHECK(!thr->is_freeing);
|
||||||
|
|
@ -169,7 +166,7 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
|
||||||
thr->mset.Del(s->GetId(), true);
|
thr->mset.Del(s->GetId(), true);
|
||||||
if (common_flags()->detect_deadlocks) {
|
if (common_flags()->detect_deadlocks) {
|
||||||
EnsureDeadlockDetectorID(thr, s);
|
EnsureDeadlockDetectorID(thr, s);
|
||||||
Printf("MutexUnlock: %zx\n", s->deadlock_detector_id);
|
// Printf("MutexUnlock: %zx\n", s->deadlock_detector_id);
|
||||||
g_deadlock_detector.onUnlock(&thr->deadlock_detector_tls,
|
g_deadlock_detector.onUnlock(&thr->deadlock_detector_tls,
|
||||||
s->deadlock_detector_id);
|
s->deadlock_detector_id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ class LockTest {
|
||||||
locks_[i].unlock();
|
locks_[i].unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simple lock order onversion.
|
||||||
void Test1() {
|
void Test1() {
|
||||||
fprintf(stderr, "Starting Test1\n");
|
fprintf(stderr, "Starting Test1\n");
|
||||||
// CHECK: Starting Test1
|
// CHECK: Starting Test1
|
||||||
|
|
@ -42,6 +43,7 @@ class LockTest {
|
||||||
// CHECK-NOT: ThreadSanitizer:
|
// CHECK-NOT: ThreadSanitizer:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simple lock order inversion with 3 locks.
|
||||||
void Test2() {
|
void Test2() {
|
||||||
fprintf(stderr, "Starting Test2\n");
|
fprintf(stderr, "Starting Test2\n");
|
||||||
// CHECK: Starting Test2
|
// CHECK: Starting Test2
|
||||||
|
|
@ -51,7 +53,24 @@ class LockTest {
|
||||||
// CHECK-NOT: ThreadSanitizer:
|
// CHECK-NOT: ThreadSanitizer:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lock order inversion with lots of new locks created (but not used)
|
||||||
|
// between. Since the new locks are not used we should still detect the
|
||||||
|
// deadlock.
|
||||||
|
void Test3() {
|
||||||
|
fprintf(stderr, "Starting Test3\n");
|
||||||
|
// CHECK: Starting Test3
|
||||||
|
L(0); L(1); U(0); U(1);
|
||||||
|
CreateAndDestroyManyLocks();
|
||||||
|
L(1); L(0); U(0); U(1);
|
||||||
|
// CHECK: ThreadSanitizer: lock-order-inversion (potential deadlock)
|
||||||
|
// CHECK-NOT: ThreadSanitizer:
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void CreateAndDestroyManyLocks() {
|
||||||
|
PaddedLock create_many_locks_but_never_acquire[kDeadlockGraphSize];
|
||||||
|
}
|
||||||
|
static const size_t kDeadlockGraphSize = 4096;
|
||||||
size_t n_;
|
size_t n_;
|
||||||
PaddedLock *locks_;
|
PaddedLock *locks_;
|
||||||
};
|
};
|
||||||
|
|
@ -59,6 +78,7 @@ class LockTest {
|
||||||
int main() {
|
int main() {
|
||||||
{ LockTest t(5); t.Test1(); }
|
{ LockTest t(5); t.Test1(); }
|
||||||
{ LockTest t(5); t.Test2(); }
|
{ LockTest t(5); t.Test2(); }
|
||||||
|
{ LockTest t(5); t.Test3(); }
|
||||||
fprintf(stderr, "DONE\n");
|
fprintf(stderr, "DONE\n");
|
||||||
// CHECK: DONE
|
// CHECK: DONE
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue