[compiler-rt] r194823 - tsan: add support for robust mutexes
Dmitry Vyukov
dvyukov at google.com
Fri Nov 15 08:58:12 PST 2013
Author: dvyukov
Date: Fri Nov 15 10:58:12 2013
New Revision: 194823
URL: http://llvm.org/viewvc/llvm-project?rev=194823&view=rev
Log:
tsan: add support for robust mutexes
Added:
compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust.cc
compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust2.cc
Modified:
compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=194823&r1=194822&r2=194823&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Fri Nov 15 10:58:12 2013
@@ -23,6 +23,7 @@
// COMMON_INTERCEPTOR_ON_EXIT
// COMMON_INTERCEPTOR_MUTEX_LOCK
// COMMON_INTERCEPTOR_MUTEX_UNLOCK
+// COMMON_INTERCEPTOR_MUTEX_REPAIR
// COMMON_INTERCEPTOR_SET_PTHREAD_NAME
//===----------------------------------------------------------------------===//
#include "interception/interception.h"
@@ -50,6 +51,10 @@
#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {}
#endif
+#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR
+#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
+#endif
+
#if SANITIZER_INTERCEPT_STRCMP
static inline int CharCmpX(unsigned char c1, unsigned char c2) {
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
@@ -2179,7 +2184,10 @@ INTERCEPTOR(int, pthread_mutex_lock, voi
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
int res = REAL(pthread_mutex_lock)(m);
- if (res == 0) COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
+ if (res == errno_EOWNERDEAD)
+ COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
+ if (res == 0 || res == errno_EOWNERDEAD)
+ COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
return res;
}
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc?rev=194823&r1=194822&r2=194823&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc Fri Nov 15 10:58:12 2013
@@ -21,6 +21,7 @@
#include <arpa/inet.h>
#include <dirent.h>
+#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <net/if.h>
@@ -762,6 +763,8 @@ namespace __sanitizer {
unsigned IOCTL_TIOCSERSETMULTI = TIOCSERSETMULTI;
unsigned IOCTL_TIOCSSERIAL = TIOCSSERIAL;
#endif
+
+ extern const int errno_EOWNERDEAD = EOWNERDEAD;
} // namespace __sanitizer
COMPILER_CHECK(sizeof(__sanitizer_pthread_attr_t) >= sizeof(pthread_attr_t));
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h?rev=194823&r1=194822&r2=194823&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h Fri Nov 15 10:58:12 2013
@@ -921,6 +921,7 @@ namespace __sanitizer {
extern unsigned IOCTL_TIOCSSERIAL;
#endif
+ extern const int errno_EOWNERDEAD;
} // namespace __sanitizer
#define CHECK_TYPE_SIZE(TYPE) \
Added: compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust.cc?rev=194823&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust.cc Fri Nov 15 10:58:12 2013
@@ -0,0 +1,36 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+pthread_mutex_t m;
+
+void *thr(void *p) {
+ pthread_mutex_lock(&m);
+ return 0;
+}
+
+int main() {
+ pthread_mutexattr_t a;
+ pthread_mutexattr_init(&a);
+ pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
+ pthread_mutex_init(&m, &a);
+ pthread_t th;
+ pthread_create(&th, 0, thr, 0);
+ sleep(1);
+ if (pthread_mutex_lock(&m) != EOWNERDEAD) {
+ fprintf(stderr, "not EOWNERDEAD\n");
+ exit(1);
+ }
+ pthread_join(th, 0);
+ fprintf(stderr, "DONE\n");
+}
+
+// This is a correct code, and tsan must not bark.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK-NOT: EOWNERDEAD
+// CHECK: DONE
+// CHECK-NOT: WARNING: ThreadSanitizer
+
Added: compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust2.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust2.cc?rev=194823&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust2.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/mutex_robust2.cc Fri Nov 15 10:58:12 2013
@@ -0,0 +1,41 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+pthread_mutex_t m;
+int x;
+
+void *thr(void *p) {
+ pthread_mutex_lock(&m);
+ x = 42;
+ return 0;
+}
+
+int main() {
+ pthread_mutexattr_t a;
+ pthread_mutexattr_init(&a);
+ pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
+ pthread_mutex_init(&m, &a);
+ pthread_t th;
+ pthread_create(&th, 0, thr, 0);
+ sleep(1);
+ if (pthread_mutex_trylock(&m) != EOWNERDEAD) {
+ fprintf(stderr, "not EOWNERDEAD\n");
+ exit(1);
+ }
+ x = 43;
+ pthread_join(th, 0);
+ fprintf(stderr, "DONE\n");
+}
+
+// This is a false positive, tsan must not bark at the data race.
+// But currently it does.
+// CHECK-NOT: WARNING: ThreadSanitizer WARNING: double lock of mutex
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK-NOT: EOWNERDEAD
+// CHECK: DONE
+// CHECK-NOT: WARNING: ThreadSanitizer
+
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=194823&r1=194822&r2=194823&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Fri Nov 15 10:58:12 2013
@@ -66,6 +66,7 @@ const int PTHREAD_MUTEX_RECURSIVE = 1;
const int PTHREAD_MUTEX_RECURSIVE_NP = 1;
const int EINVAL = 22;
const int EBUSY = 16;
+const int EOWNERDEAD = 130;
const int EPOLL_CTL_ADD = 1;
const int SIGILL = 4;
const int SIGABRT = 6;
@@ -948,9 +949,10 @@ TSAN_INTERCEPTOR(int, pthread_mutex_dest
TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) {
SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m);
int res = REAL(pthread_mutex_trylock)(m);
- if (res == 0) {
+ if (res == EOWNERDEAD)
+ MutexRepair(thr, pc, (uptr)m);
+ if (res == 0 || res == EOWNERDEAD)
MutexLock(thr, pc, (uptr)m);
- }
return res;
}
@@ -1892,6 +1894,10 @@ struct TsanInterceptorContext {
MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \
((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \
+ MutexRepair(((TsanInterceptorContext *)ctx)->thr, \
+ ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+
#include "sanitizer_common/sanitizer_common_interceptors.inc"
#define TSAN_SYSCALL() \
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=194823&r1=194822&r2=194823&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Fri Nov 15 10:58:12 2013
@@ -705,6 +705,7 @@ int MutexUnlock(ThreadState *thr, uptr
void MutexReadLock(ThreadState *thr, uptr pc, uptr addr);
void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
+void MutexRepair(ThreadState *thr, uptr pc, uptr addr); // call on EOWNERDEAD
void Acquire(ThreadState *thr, uptr pc, uptr addr);
void AcquireGlobal(ThreadState *thr, uptr pc);
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc?rev=194823&r1=194822&r2=194823&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc Fri Nov 15 10:58:12 2013
@@ -224,6 +224,16 @@ void MutexReadOrWriteUnlock(ThreadState
s->mtx.Unlock();
}
+void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
+ Context *ctx = CTX();
+ CHECK_GT(thr->in_rtl, 0);
+ DPrintf("#%d: MutexRepair %zx\n", thr->tid, addr);
+ SyncVar *s = ctx->synctab.GetOrCreateAndLock(thr, pc, addr, true);
+ s->owner_tid = SyncVar::kInvalidTid;
+ s->recursion = 0;
+ s->mtx.Unlock();
+}
+
void Acquire(ThreadState *thr, uptr pc, uptr addr) {
CHECK_GT(thr->in_rtl, 0);
DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
More information about the llvm-commits
mailing list