[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