[compiler-rt] r347383 - tsan: add pthread_tryjoin_np and pthread_timedjoin_np interceptors
Dmitry Vyukov via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 21 01:31:21 PST 2018
Author: dvyukov
Date: Wed Nov 21 01:31:21 2018
New Revision: 347383
URL: http://llvm.org/viewvc/llvm-project?rev=347383&view=rev
Log:
tsan: add pthread_tryjoin_np and pthread_timedjoin_np interceptors
Add pthread_tryjoin_np() and pthread_timedjoin_np() interceptors on Linux,
so that ThreadSanitizer can handle programs using these functions.
Author: Yuri Per (yuri)
Reviewed in: https://reviews.llvm.org/D54521
Added:
compiler-rt/trunk/test/tsan/Linux/thread_timedjoin.c
compiler-rt/trunk/test/tsan/Linux/thread_tryjoin.c
Modified:
compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.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_thread.cc
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc?rev=347383&r1=347382&r2=347383&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.cc Wed Nov 21 01:31:21 2018
@@ -338,4 +338,15 @@ ThreadContextBase *ThreadRegistry::Quara
return tctx;
}
+void ThreadRegistry::SetThreadUserId(u32 tid, uptr user_id) {
+ BlockingMutexLock l(&mtx_);
+ CHECK_LT(tid, n_contexts_);
+ ThreadContextBase *tctx = threads_[tid];
+ CHECK_NE(tctx, 0);
+ CHECK_NE(tctx->status, ThreadStatusInvalid);
+ CHECK_NE(tctx->status, ThreadStatusDead);
+ CHECK_EQ(tctx->user_id, 0);
+ tctx->user_id = user_id;
+}
+
} // namespace __sanitizer
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h?rev=347383&r1=347382&r2=347383&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_thread_registry.h Wed Nov 21 01:31:21 2018
@@ -122,6 +122,7 @@ class ThreadRegistry {
void JoinThread(u32 tid, void *arg);
void FinishThread(u32 tid);
void StartThread(u32 tid, tid_t os_id, bool workerthread, void *arg);
+ void SetThreadUserId(u32 tid, uptr user_id);
private:
const ThreadContextFactory context_factory_;
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=347383&r1=347382&r2=347383&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Wed Nov 21 01:31:21 2018
@@ -1056,6 +1056,35 @@ TSAN_INTERCEPTOR(int, pthread_detach, vo
return res;
}
+#if SANITIZER_LINUX
+TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_tryjoin_np, th, ret);
+ int tid = ThreadTid(thr, pc, (uptr)th);
+ ThreadIgnoreBegin(thr, pc);
+ int res = REAL(pthread_tryjoin_np)(th, ret);
+ ThreadIgnoreEnd(thr, pc);
+ if (res == 0)
+ ThreadJoin(thr, pc, tid);
+ else
+ ThreadNotJoined(thr, pc, tid, (uptr)th);
+ return res;
+}
+
+TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret,
+ const struct timespec *abstime) {
+ SCOPED_TSAN_INTERCEPTOR(pthread_timedjoin_np, th, ret, abstime);
+ int tid = ThreadTid(thr, pc, (uptr)th);
+ ThreadIgnoreBegin(thr, pc);
+ int res = BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime);
+ ThreadIgnoreEnd(thr, pc);
+ if (res == 0)
+ ThreadJoin(thr, pc, tid);
+ else
+ ThreadNotJoined(thr, pc, tid, (uptr)th);
+ return res;
+}
+#endif
+
// Problem:
// NPTL implementation of pthread_cond has 2 versions (2.2.5 and 2.3.2).
// pthread_cond_t has different size in the different versions.
@@ -2652,6 +2681,10 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(pthread_create);
TSAN_INTERCEPT(pthread_join);
TSAN_INTERCEPT(pthread_detach);
+ #if SANITIZER_LINUX
+ TSAN_INTERCEPT(pthread_tryjoin_np);
+ TSAN_INTERCEPT(pthread_timedjoin_np);
+ #endif
TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE);
TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
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=347383&r1=347382&r2=347383&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Wed Nov 21 01:31:21 2018
@@ -772,6 +772,7 @@ void ThreadFinalize(ThreadState *thr);
void ThreadSetName(ThreadState *thr, const char *name);
int ThreadCount(ThreadState *thr);
void ProcessPendingSignals(ThreadState *thr);
+void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid);
Processor *ProcCreate();
void ProcDestroy(Processor *proc);
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc?rev=347383&r1=347382&r2=347383&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc Wed Nov 21 01:31:21 2018
@@ -312,6 +312,12 @@ void ThreadDetach(ThreadState *thr, uptr
ctx->thread_registry->DetachThread(tid, thr);
}
+void ThreadNotJoined(ThreadState *thr, uptr pc, int tid, uptr uid) {
+ CHECK_GT(tid, 0);
+ CHECK_LT(tid, kMaxTid);
+ ctx->thread_registry->SetThreadUserId(tid, uid);
+}
+
void ThreadSetName(ThreadState *thr, const char *name) {
ctx->thread_registry->SetThreadName(thr->tid, name);
}
Added: compiler-rt/trunk/test/tsan/Linux/thread_timedjoin.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Linux/thread_timedjoin.c?rev=347383&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Linux/thread_timedjoin.c (added)
+++ compiler-rt/trunk/test/tsan/Linux/thread_timedjoin.c Wed Nov 21 01:31:21 2018
@@ -0,0 +1,39 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#define _GNU_SOURCE
+#include "../test.h"
+#include <errno.h>
+
+int var;
+
+void *Thread(void *x) {
+ barrier_wait(&barrier);
+ var = 1;
+ return 0;
+}
+
+static void check(int res, int expect) {
+ if (res != expect) {
+ fprintf(stderr, "Unexpected result of pthread_timedjoin_np: %d\n", res);
+ exit(1);
+ }
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ pthread_t t;
+ pthread_create(&t, 0, Thread, 0);
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ check(pthread_timedjoin_np(t, 0, &ts), ETIMEDOUT);
+ barrier_wait(&barrier);
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += 10000;
+ check(pthread_timedjoin_np(t, 0, &ts), 0);
+ var = 2;
+ fprintf(stderr, "PASS\n");
+ return 0;
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
+// CHECK-NOT: WARNING: ThreadSanitizer: thread leak
+// CHECK: PASS
Added: compiler-rt/trunk/test/tsan/Linux/thread_tryjoin.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Linux/thread_tryjoin.c?rev=347383&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Linux/thread_tryjoin.c (added)
+++ compiler-rt/trunk/test/tsan/Linux/thread_tryjoin.c Wed Nov 21 01:31:21 2018
@@ -0,0 +1,41 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#define _GNU_SOURCE
+#include "../test.h"
+#include <errno.h>
+
+int var;
+
+void *Thread(void *x) {
+ barrier_wait(&barrier);
+ var = 1;
+ return 0;
+}
+
+static void check(int res) {
+ if (res != EBUSY) {
+ fprintf(stderr, "Unexpected result of pthread_tryjoin_np: %d\n", res);
+ exit(1);
+ }
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ pthread_t t;
+ pthread_create(&t, 0, Thread, 0);
+ check(pthread_tryjoin_np(t, 0));
+ barrier_wait(&barrier);
+ for (;;) {
+ int res = pthread_tryjoin_np(t, 0);
+ if (!res)
+ break;
+ check(res);
+ pthread_yield();
+ }
+ var = 2;
+ fprintf(stderr, "PASS\n");
+ return 0;
+}
+
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
+// CHECK-NOT: WARNING: ThreadSanitizer: thread leak
+// CHECK: PASS
More information about the llvm-commits
mailing list