forked from OSchip/llvm-project
[sanitizer] partially support pthread_rwlock_* (no rd* form yet)
llvm-svn: 202128
This commit is contained in:
parent
dd8c801871
commit
fd88edfddb
|
@ -1047,7 +1047,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_tryrdlock, void *m) {
|
|||
SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_tryrdlock, m);
|
||||
int res = REAL(pthread_rwlock_tryrdlock)(m);
|
||||
if (res == 0) {
|
||||
MutexReadLock(thr, pc, (uptr)m);
|
||||
MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -1074,7 +1074,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_trywrlock, void *m) {
|
|||
SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_trywrlock, m);
|
||||
int res = REAL(pthread_rwlock_trywrlock)(m);
|
||||
if (res == 0) {
|
||||
MutexLock(thr, pc, (uptr)m);
|
||||
MutexLock(thr, pc, (uptr)m, /*rec=*/1, /*try_lock=*/true);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,15 @@ static void EnsureDeadlockDetectorID(Context *ctx, ThreadState *thr,
|
|||
ctx->dd.ensureCurrentEpoch(&thr->deadlock_detector_tls);
|
||||
}
|
||||
|
||||
static void DDUnlock(Context *ctx, ThreadState *thr,
|
||||
SyncVar *s) {
|
||||
if (!common_flags()->detect_deadlocks) return;
|
||||
Lock lk(&ctx->dd_mtx);
|
||||
EnsureDeadlockDetectorID(ctx, thr, s);
|
||||
// Printf("MutexUnlock: %zx\n", s->deadlock_detector_id);
|
||||
ctx->dd.onUnlock(&thr->deadlock_detector_tls, s->deadlock_detector_id);
|
||||
}
|
||||
|
||||
void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
|
||||
bool rw, bool recursive, bool linker_init) {
|
||||
Context *ctx = CTX();
|
||||
|
@ -186,13 +195,7 @@ int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, bool all) {
|
|||
}
|
||||
}
|
||||
thr->mset.Del(s->GetId(), true);
|
||||
if (common_flags()->detect_deadlocks) {
|
||||
Lock lk(&ctx->dd_mtx);
|
||||
EnsureDeadlockDetectorID(ctx, thr, s);
|
||||
// Printf("MutexUnlock: %zx\n", s->deadlock_detector_id);
|
||||
ctx->dd.onUnlock(&thr->deadlock_detector_tls,
|
||||
s->deadlock_detector_id);
|
||||
}
|
||||
DDUnlock(ctx, thr, s);
|
||||
s->mtx.Unlock();
|
||||
return rec;
|
||||
}
|
||||
|
@ -230,6 +233,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
|
|||
PrintCurrentStack(thr, pc);
|
||||
}
|
||||
ReleaseImpl(thr, pc, &s->read_clock);
|
||||
DDUnlock(CTX(), thr, s);
|
||||
s->mtx.Unlock();
|
||||
thr->mset.Del(s->GetId(), false);
|
||||
}
|
||||
|
@ -267,6 +271,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
|
|||
PrintCurrentStack(thr, pc);
|
||||
}
|
||||
thr->mset.Del(s->GetId(), write);
|
||||
DDUnlock(CTX(), thr, s);
|
||||
s->mtx.Unlock();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
// RUN: %clangxx_tsan %s -o %t
|
||||
// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadMutex
|
||||
// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s
|
||||
// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadSpinLock
|
||||
// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s
|
||||
// RUN: %clangxx_tsan %s -o %t -DLockType=PthreadRWLock
|
||||
// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s
|
||||
#include <pthread.h>
|
||||
#undef NDEBUG
|
||||
|
@ -37,8 +41,22 @@ class PthreadSpinLock {
|
|||
char padding_[64 - sizeof(pthread_spinlock_t)];
|
||||
};
|
||||
|
||||
class PthreadRWLock {
|
||||
public:
|
||||
PthreadRWLock() { assert(0 == pthread_rwlock_init(&mu_, 0)); }
|
||||
~PthreadRWLock() {
|
||||
assert(0 == pthread_rwlock_destroy(&mu_));
|
||||
(void)padding_;
|
||||
}
|
||||
void lock() { assert(0 == pthread_rwlock_wrlock(&mu_)); }
|
||||
void unlock() { assert(0 == pthread_rwlock_unlock(&mu_)); }
|
||||
bool try_lock() { return 0 == pthread_rwlock_trywrlock(&mu_); }
|
||||
|
||||
private:
|
||||
pthread_rwlock_t mu_;
|
||||
char padding_[64 - sizeof(pthread_rwlock_t)];
|
||||
};
|
||||
|
||||
template <class LockType>
|
||||
class LockTest {
|
||||
public:
|
||||
LockTest(size_t n) : n_(n), locks_(new LockType[n]) { }
|
||||
|
@ -184,7 +202,9 @@ class LockTest {
|
|||
|
||||
void CreateAndDestroyManyLocks() {
|
||||
LockType create_many_locks_but_never_acquire[kDeadlockGraphSize];
|
||||
(void)create_many_locks_but_never_acquire;
|
||||
}
|
||||
|
||||
void CreateLockUnlockAndDestroyManyLocks() {
|
||||
LockType many_locks[kDeadlockGraphSize];
|
||||
for (size_t i = 0; i < kDeadlockGraphSize; i++) {
|
||||
|
@ -222,20 +242,14 @@ class LockTest {
|
|||
LockType *locks_;
|
||||
};
|
||||
|
||||
template <class LockType>
|
||||
void RunAllTests() {
|
||||
{ LockTest<LockType> t(5); t.Test1(); }
|
||||
{ LockTest<LockType> t(5); t.Test2(); }
|
||||
{ LockTest<LockType> t(5); t.Test3(); }
|
||||
{ LockTest<LockType> t(5); t.Test4(); }
|
||||
{ LockTest<LockType> t(5); t.Test5(); }
|
||||
{ LockTest<LockType> t(5); t.Test6(); }
|
||||
{ LockTest<LockType> t(10); t.Test7(); }
|
||||
}
|
||||
|
||||
int main () {
|
||||
RunAllTests<PthreadMutex>();
|
||||
RunAllTests<PthreadSpinLock>();
|
||||
{ LockTest t(5); t.Test1(); }
|
||||
{ LockTest t(5); t.Test2(); }
|
||||
{ LockTest t(5); t.Test3(); }
|
||||
{ LockTest t(5); t.Test4(); }
|
||||
{ LockTest t(5); t.Test5(); }
|
||||
{ LockTest t(5); t.Test6(); }
|
||||
{ LockTest t(10); t.Test7(); }
|
||||
fprintf(stderr, "DONE\n");
|
||||
// CHECK: DONE
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue