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:
Dmitry Vyukov 2015-04-20 10:35:10 +00:00
parent c4ddfd865d
commit 8586e2352b
2 changed files with 36 additions and 1 deletions

View File

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

View File

@ -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