xref: /llvm-project/compiler-rt/test/tsan/cond_race.cpp (revision bcaeed49cb063de9fe504aa29e1cadff8a7be710)
1*bcaeed49SFangrui Song // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
2*bcaeed49SFangrui Song // CHECK-NOT: unlock of unlocked mutex
3*bcaeed49SFangrui Song // CHECK: ThreadSanitizer: data race
4*bcaeed49SFangrui Song // CHECK: pthread_cond_signal
5*bcaeed49SFangrui Song 
6*bcaeed49SFangrui Song #include "test.h"
7*bcaeed49SFangrui Song 
8*bcaeed49SFangrui Song struct Ctx {
9*bcaeed49SFangrui Song   pthread_mutex_t m;
10*bcaeed49SFangrui Song   pthread_cond_t c;
11*bcaeed49SFangrui Song   bool done;
12*bcaeed49SFangrui Song };
13*bcaeed49SFangrui Song 
thr(void * p)14*bcaeed49SFangrui Song void *thr(void *p) {
15*bcaeed49SFangrui Song   Ctx *c = (Ctx*)p;
16*bcaeed49SFangrui Song   pthread_mutex_lock(&c->m);
17*bcaeed49SFangrui Song   c->done = true;
18*bcaeed49SFangrui Song   pthread_mutex_unlock(&c->m);
19*bcaeed49SFangrui Song   pthread_cond_signal(&c->c);
20*bcaeed49SFangrui Song   barrier_wait(&barrier);
21*bcaeed49SFangrui Song   return 0;
22*bcaeed49SFangrui Song }
23*bcaeed49SFangrui Song 
main()24*bcaeed49SFangrui Song int main() {
25*bcaeed49SFangrui Song   barrier_init(&barrier, 2);
26*bcaeed49SFangrui Song   Ctx *c = new Ctx();
27*bcaeed49SFangrui Song   pthread_mutex_init(&c->m, 0);
28*bcaeed49SFangrui Song   pthread_cond_init(&c->c, 0);
29*bcaeed49SFangrui Song   pthread_t th;
30*bcaeed49SFangrui Song   pthread_create(&th, 0, thr, c);
31*bcaeed49SFangrui Song   pthread_mutex_lock(&c->m);
32*bcaeed49SFangrui Song   while (!c->done)
33*bcaeed49SFangrui Song     pthread_cond_wait(&c->c, &c->m);
34*bcaeed49SFangrui Song   pthread_mutex_unlock(&c->m);
35*bcaeed49SFangrui Song   // otherwise it can be reported as use-after-free
36*bcaeed49SFangrui Song   barrier_wait(&barrier);
37*bcaeed49SFangrui Song   delete c;
38*bcaeed49SFangrui Song   pthread_join(th, 0);
39*bcaeed49SFangrui Song }
40