1 // RUN: %clang_tsan %s -o %t 2 // RUN: %clang_tsan %s -DBUILD_SO -fPIC -o %t-so.so -shared 3 // RUN: %run %t 2>&1 | FileCheck %s 4 5 // Test that tsan cleans up dynamic TLS memory between reuse. 6 7 #include "test.h" 8 9 #ifndef BUILD_SO 10 #include <assert.h> 11 #include <dlfcn.h> 12 13 typedef volatile long *(* get_t)(); 14 get_t GetTls; 15 16 void *Thread1(void *arg) { 17 pthread_detach(pthread_self()); 18 volatile long *x = GetTls(); 19 *x = 42; 20 fprintf(stderr, "stack: %p dtls: %p\n", &x, x); 21 barrier_wait(&barrier); 22 return 0; 23 } 24 25 void *Thread2(void *arg) { 26 volatile long *x = GetTls(); 27 *x = 42; 28 fprintf(stderr, "stack: %p dtls: %p\n", &x, x); 29 return 0; 30 } 31 32 int main(int argc, char *argv[]) { 33 char path[4096]; 34 snprintf(path, sizeof(path), "%s-so.so", argv[0]); 35 36 void *handle = dlopen(path, RTLD_LAZY); 37 if (!handle) fprintf(stderr, "%s\n", dlerror()); 38 assert(handle != 0); 39 GetTls = (get_t)dlsym(handle, "GetTls"); 40 assert(dlerror() == 0); 41 42 barrier_init(&barrier, 2); 43 pthread_t t[2]; 44 pthread_create(&t[0], 0, Thread1, 0); 45 barrier_wait(&barrier); 46 // Wait for actual thread termination without using pthread_join, 47 // which would synchronize threads. 48 sleep(1); 49 pthread_create(&t[1], 0, Thread2, 0); 50 pthread_join(t[1], 0); 51 fprintf(stderr, "DONE\n"); 52 return 0; 53 } 54 #else // BUILD_SO 55 __thread long huge_thread_local_array[1 << 17]; 56 long *GetTls() { 57 return &huge_thread_local_array[0]; 58 } 59 #endif 60 61 // CHECK-NOT: ThreadSanitizer: data race 62 // CHECK: DONE 63