[PATCH] D18184: [tsan] Add interceptor for pthread_cond_timedwait_relative_np

Kuba Brecka via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 15 07:01:14 PDT 2016


kubabrecka created this revision.
kubabrecka added reviewers: dvyukov, samsonov, glider, kcc.
kubabrecka added subscribers: llvm-commits, zaks.anna, dcoughlin.

On OS X, we have `pthread_cond_timedwait_relative_np`.  TSan needs to intercept this API to avoid false positives when using condition variables.

http://reviews.llvm.org/D18184

Files:
  lib/tsan/rtl/tsan_interceptors.cc

Index: lib/tsan/rtl/tsan_interceptors.cc
===================================================================
--- lib/tsan/rtl/tsan_interceptors.cc
+++ lib/tsan/rtl/tsan_interceptors.cc
@@ -1101,49 +1101,47 @@
   return REAL(pthread_cond_init)(cond, a);
 }
 
+#define PTHREAD_COND_WAIT_BODY(call, c, m, t)                                  \
+  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);                    \
+  MutexUnlock(thr, pc, (uptr)m);                                               \
+  CondMutexUnlockCtx arg = {&si, thr, pc, m};                                  \
+  int res = 0;                                                                 \
+  /* This ensures that we handle mutex lock even in case of pthread_cancel. */ \
+  /* See test/tsan/cond_cancel.cc. */                                          \
+  {                                                                            \
+    /* Enable signal delivery while the thread is blocked. */                  \
+    BlockingCall bc(thr);                                                      \
+    res = call_pthread_cancel_with_cleanup(                                    \
+        call, c, m, t, (void (*)(void *arg))cond_mutex_unlock, &arg);          \
+  }                                                                            \
+  if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m);                  \
+  MutexLock(thr, pc, (uptr)m);                                                 \
+  return res
+
 INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
   void *cond = init_cond(c);
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m);
-  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
-  MutexUnlock(thr, pc, (uptr)m);
-  CondMutexUnlockCtx arg = {&si, thr, pc, m};
-  int res = 0;
-  // This ensures that we handle mutex lock even in case of pthread_cancel.
-  // See test/tsan/cond_cancel.cc.
-  {
-    // Enable signal delivery while the thread is blocked.
-    BlockingCall bc(thr);
-    res = call_pthread_cancel_with_cleanup(
-        (int(*)(void *c, void *m, void *abstime))REAL(pthread_cond_wait),
-        cond, m, 0, (void(*)(void *arg))cond_mutex_unlock, &arg);
-  }
-  if (res == errno_EOWNERDEAD)
-    MutexRepair(thr, pc, (uptr)m);
-  MutexLock(thr, pc, (uptr)m);
-  return res;
+  PTHREAD_COND_WAIT_BODY(
+      (int (*)(void *c, void *m, void *abstime))REAL(pthread_cond_wait), cond,
+      m, 0);
 }
 
 INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
   void *cond = init_cond(c);
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, cond, m, abstime);
-  MemoryAccessRange(thr, pc, (uptr)c, sizeof(uptr), false);
-  MutexUnlock(thr, pc, (uptr)m);
-  CondMutexUnlockCtx arg = {&si, thr, pc, m};
-  int res = 0;
-  // This ensures that we handle mutex lock even in case of pthread_cancel.
-  // See test/tsan/cond_cancel.cc.
-  {
-    BlockingCall bc(thr);
-    res = call_pthread_cancel_with_cleanup(
-        REAL(pthread_cond_timedwait), cond, m, abstime,
-        (void(*)(void *arg))cond_mutex_unlock, &arg);
-  }
-  if (res == errno_EOWNERDEAD)
-    MutexRepair(thr, pc, (uptr)m);
-  MutexLock(thr, pc, (uptr)m);
-  return res;
+  PTHREAD_COND_WAIT_BODY(REAL(pthread_cond_timedwait), cond, m, abstime);
 }
 
+#if SANITIZER_MAC
+INTERCEPTOR(int, pthread_cond_timedwait_relative_np, void *c, void *m,
+            void *reltime) {
+  void *cond = init_cond(c);
+  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_relative_np, cond, m, reltime);
+  PTHREAD_COND_WAIT_BODY(REAL(pthread_cond_timedwait_relative_np), cond, m,
+                         reltime);
+}
+#endif
+
 INTERCEPTOR(int, pthread_cond_signal, void *c) {
   void *cond = init_cond(c);
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, cond);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D18184.50726.patch
Type: text/x-patch
Size: 3774 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160315/7df6cdcc/attachment.bin>


More information about the llvm-commits mailing list