[PATCH] tsan: fix handling of condition variable destruction

Dmitry Vyukov dvyukov at google.com
Wed Jun 24 08:20:18 PDT 2015


Hi EricWF,

POSIX states that "It shall  be  safe  to destroy an initialized condition variable upon which no threads are currently blocked", and later clarifies "A condition variable can be destroyed immediately after all the threads that are blocked on it are awakened) (in examples section). Tsan reported such destruction as a data race.
Fixes https://llvm.org/bugs/show_bug.cgi?id=23616

http://reviews.llvm.org/D10693

Files:
  lib/tsan/rtl/tsan_interceptors.cc
  test/tsan/cond_destruction.cc

Index: lib/tsan/rtl/tsan_interceptors.cc
===================================================================
--- lib/tsan/rtl/tsan_interceptors.cc
+++ lib/tsan/rtl/tsan_interceptors.cc
@@ -992,8 +992,8 @@
 INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
   void *cond = init_cond(c);
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, cond, m);
-  MutexUnlock(thr, pc, (uptr)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.
@@ -1014,8 +1014,8 @@
 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);
-  MutexUnlock(thr, pc, (uptr)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.
Index: test/tsan/cond_destruction.cc
===================================================================
--- test/tsan/cond_destruction.cc
+++ test/tsan/cond_destruction.cc
@@ -0,0 +1,53 @@
+// RUN: %clangxx_tsan -O1 %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %run %t arg 2>&1 | FileCheck %s
+// RUN: %run %t arg arg 2>&1 | FileCheck %s
+#include "test.h"
+
+// Test for destruction of pthread_cond_t.
+// POSIX states that it is safe  to destroy a condition variable upon which no
+// threads are currently blocked. That is, it is not necessary to wait untill
+// other threads return from pthread_cond_wait, they just need to be unblocked.
+
+pthread_mutex_t m;
+pthread_cond_t c;
+bool done1, done2;
+
+void *thr(void *p) {
+  pthread_mutex_lock(&m);
+  done1 = true;
+  pthread_cond_signal(&c);
+  while (!done2)
+    pthread_cond_wait(&c, &m);
+  pthread_mutex_unlock(&m);
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  pthread_t th;
+  pthread_mutex_init(&m, 0);
+  pthread_cond_init(&c, 0);
+  pthread_create(&th, 0, thr, 0);
+  pthread_mutex_lock(&m);
+  while (!done1)
+    pthread_cond_wait(&c, &m);
+  done2 = true;
+  // Any of these sequences is legal.
+  if (argc == 1) {
+    pthread_cond_signal(&c);
+    pthread_mutex_unlock(&m);
+    pthread_cond_destroy(&c);
+  } else if (argc == 2) {
+    pthread_mutex_unlock(&m);
+    pthread_cond_signal(&c);
+    pthread_cond_destroy(&c);
+  } else {
+    pthread_cond_signal(&c);
+    pthread_cond_destroy(&c);
+    pthread_mutex_unlock(&m);
+  }
+  pthread_join(th, 0);
+  fprintf(stderr, "DONE\n");
+}
+
+// CHECK-NOT: ThreadSanitizer: data race

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D10693.28356.patch
Type: text/x-patch
Size: 2713 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150624/68e6045a/attachment.bin>


More information about the llvm-commits mailing list