tsan: catch races on condition variables

llvm-svn: 189816
This commit is contained in:
Dmitry Vyukov 2013-09-03 15:04:15 +00:00
parent 2993506fa4
commit 4e27d1fdaf
3 changed files with 95 additions and 0 deletions

View File

@ -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");
}

View File

@ -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);
}

View File

@ -1053,24 +1053,28 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unlock, void *m) {
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_broadcast_2_3_2, void *c) {
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_timedwait_2_3_2, void *c, void *m,
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;