[compiler-rt] r189816 - tsan: catch races on condition variables

Dmitry Vyukov dvyukov at google.com
Tue Sep 3 08:04:15 PDT 2013


Author: dvyukov
Date: Tue Sep  3 10:04:15 2013
New Revision: 189816

URL: http://llvm.org/viewvc/llvm-project?rev=189816&view=rev
Log:
tsan: catch races on condition variables

Added:
    compiler-rt/trunk/lib/tsan/lit_tests/cond.c
    compiler-rt/trunk/lib/tsan/lit_tests/cond_race.cc
Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc

Added: compiler-rt/trunk/lib/tsan/lit_tests/cond.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/cond.c?rev=189816&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/cond.c (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/cond.c Tue Sep  3 10:04:15 2013
@@ -0,0 +1,53 @@
+// RUN: %clang_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+// CHECK-NOT: WARNING: ThreadSanitizer: data race
+// CHECK-NOT: ThreadSanitizer WARNING: double lock
+// CHECK-NOT: ThreadSanitizer WARNING: mutex unlock by another thread
+// CHECK: OK
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+pthread_mutex_t m;
+pthread_cond_t c;
+int x;
+
+void *thr1(void *p) {
+  int i;
+
+  for (i = 0; i < 10; i += 2) {
+    pthread_mutex_lock(&m);
+    while (x != i)
+      pthread_cond_wait(&c, &m);
+    x = i + 1;
+    pthread_cond_signal(&c);
+    pthread_mutex_unlock(&m);
+  }
+  return 0;
+}
+
+void *thr2(void *p) {
+  int i;
+
+  for (i = 1; i < 10; i += 2) {
+    pthread_mutex_lock(&m);
+    while (x != i)
+      pthread_cond_wait(&c, &m);
+    x = i + 1;
+    pthread_mutex_unlock(&m);
+    pthread_cond_broadcast(&c);
+  }
+  return 0;
+}
+
+int main() {
+  pthread_t th1, th2;
+
+  pthread_mutex_init(&m, 0);
+  pthread_cond_init(&c, 0);
+  pthread_create(&th1, 0, thr1, 0);
+  pthread_create(&th2, 0, thr2, 0);
+  pthread_join(th1, 0);
+  pthread_join(th2, 0);
+  fprintf(stderr, "OK\n");
+}

Added: compiler-rt/trunk/lib/tsan/lit_tests/cond_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/cond_race.cc?rev=189816&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/lit_tests/cond_race.cc (added)
+++ compiler-rt/trunk/lib/tsan/lit_tests/cond_race.cc Tue Sep  3 10:04:15 2013
@@ -0,0 +1,36 @@
+// RUN: %clang_tsan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// CHECK: ThreadSanitizer: data race
+// CHECK: pthread_cond_signal
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+struct Ctx {
+  pthread_mutex_t m;
+  pthread_cond_t c;
+  bool done;
+};
+
+void *thr(void *p) {
+  Ctx *c = (Ctx*)p;
+  pthread_mutex_lock(&c->m);
+  c->done = true;
+  pthread_mutex_unlock(&c->m);
+  pthread_cond_signal(&c->c);
+  return 0;
+}
+
+int main() {
+  Ctx *c = new Ctx();
+  pthread_mutex_init(&c->m, 0);
+  pthread_cond_init(&c->c, 0);
+  pthread_t th;
+  pthread_create(&th, 0, thr, c);
+  pthread_mutex_lock(&c->m);
+  while (!c->done)
+    pthread_cond_wait(&c->c, &c->m);
+  pthread_mutex_unlock(&c->m);
+  delete c;
+  pthread_join(th, 0);
+}

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=189816&r1=189815&r2=189816&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Tue Sep  3 10:04:15 2013
@@ -1053,24 +1053,28 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unl
 
 TSAN_INTERCEPTOR(int, pthread_cond_init_2_3_2, void *c, void *a) {
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_init_2_3_2, c, a);
+  MemoryWrite(thr, pc, (uptr)c, kSizeLog1);
   int res = REAL(pthread_cond_init_2_3_2)(c, a);
   return res;
 }
 
 TSAN_INTERCEPTOR(int, pthread_cond_destroy_2_3_2, void *c) {
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy_2_3_2, c);
+  MemoryWrite(thr, pc, (uptr)c, kSizeLog1);
   int res = REAL(pthread_cond_destroy_2_3_2)(c);
   return res;
 }
 
 TSAN_INTERCEPTOR(int, pthread_cond_signal_2_3_2, void *c) {
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal_2_3_2, c);
+  MemoryRead(thr, pc, (uptr)c, kSizeLog1);
   int res = REAL(pthread_cond_signal_2_3_2)(c);
   return res;
 }
 
 TSAN_INTERCEPTOR(int, pthread_cond_broadcast_2_3_2, void *c) {
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast_2_3_2, c);
+  MemoryRead(thr, pc, (uptr)c, kSizeLog1);
   int res = REAL(pthread_cond_broadcast_2_3_2)(c);
   return res;
 }
@@ -1078,6 +1082,7 @@ TSAN_INTERCEPTOR(int, pthread_cond_broad
 TSAN_INTERCEPTOR(int, pthread_cond_wait_2_3_2, void *c, void *m) {
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait_2_3_2, c, m);
   MutexUnlock(thr, pc, (uptr)m);
+  MemoryRead(thr, pc, (uptr)c, kSizeLog1);
   int res = REAL(pthread_cond_wait_2_3_2)(c, m);
   MutexLock(thr, pc, (uptr)m);
   return res;
@@ -1087,6 +1092,7 @@ TSAN_INTERCEPTOR(int, pthread_cond_timed
     void *abstime) {
   SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_2_3_2, c, m, abstime);
   MutexUnlock(thr, pc, (uptr)m);
+  MemoryRead(thr, pc, (uptr)c, kSizeLog1);
   int res = REAL(pthread_cond_timedwait_2_3_2)(c, m, abstime);
   MutexLock(thr, pc, (uptr)m);
   return res;





More information about the llvm-commits mailing list