forked from OSchip/llvm-project
tsan: fix handling of pthread_detach
Fixes https://llvm.org/bugs/show_bug.cgi?id=23235 If pthread_create is followed by pthread_detach, the new thread may not acquire synchronize with the parent thread. llvm-svn: 235293
This commit is contained in:
parent
c4ddfd865d
commit
8586e2352b
|
@ -935,8 +935,8 @@ extern "C" void *__tsan_thread_start_func(void *arg) {
|
|||
ThreadIgnoreEnd(thr, 0);
|
||||
while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0)
|
||||
pthread_yield();
|
||||
atomic_store(&p->tid, 0, memory_order_release);
|
||||
ThreadStart(thr, tid, GetTid());
|
||||
atomic_store(&p->tid, 0, memory_order_release);
|
||||
}
|
||||
void *res = callback(param);
|
||||
// Prevent the callback from being tail called,
|
||||
|
@ -984,6 +984,13 @@ TSAN_INTERCEPTOR(int, pthread_create,
|
|||
if (res == 0) {
|
||||
int tid = ThreadCreate(thr, pc, *(uptr*)th, detached);
|
||||
CHECK_NE(tid, 0);
|
||||
// Synchronization on p.tid serves two purposes:
|
||||
// 1. ThreadCreate must finish before the new thread starts.
|
||||
// Otherwise the new thread can call pthread_detach, but the pthread_t
|
||||
// identifier is not yet registered in ThreadRegistry by ThreadCreate.
|
||||
// 2. ThreadStart must finish before this thread continues.
|
||||
// Otherwise, this thread can call pthread_detach and reset thr->sync
|
||||
// before the new thread got a chance to acquire from it in ThreadStart.
|
||||
atomic_store(&p.tid, tid, memory_order_release);
|
||||
while (atomic_load(&p.tid, memory_order_acquire) != 0)
|
||||
pthread_yield();
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
|
||||
#include "test.h"
|
||||
|
||||
// Test for https://llvm.org/bugs/show_bug.cgi?id=23235
|
||||
// The bug was that synchronization between thread creation and thread start
|
||||
// is not established if pthread_create is followed by pthread_detach.
|
||||
|
||||
int x;
|
||||
|
||||
void *Thread(void *a) {
|
||||
x = 42;
|
||||
barrier_wait(&barrier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
barrier_init(&barrier, 2);
|
||||
pthread_t t;
|
||||
x = 43;
|
||||
pthread_create(&t, 0, Thread, 0);
|
||||
pthread_detach(t);
|
||||
barrier_wait(&barrier);
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK-NOT: WARNING: ThreadSanitizer: data race
|
||||
// CHECK: PASS
|
Loading…
Reference in New Issue