1 // RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so 2 // RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t && %run %t 2>&1 | FileCheck %s 3 4 // A test for loading a dynamic library with static TLS. 5 // Such static TLS is a hack that allows a dynamic library to have faster TLS, 6 // but it can be loaded only iff all threads happened to allocate some excess 7 // of static TLS space for whatever reason. If it's not the case loading fails with: 8 // dlopen: cannot load any more object with static TLS 9 // We used to produce a false positive because dlopen will write into TLS 10 // of all existing threads to initialize/zero TLS region for the loaded library. 11 // And this appears to be racing with initialization of TLS in the thread 12 // since we model a write into the whole static TLS region (we don't know what part 13 // of it is currently unused): 14 // WARNING: ThreadSanitizer: data race (pid=2317365) 15 // Write of size 1 at 0x7f1fa9bfcdd7 by main thread: 16 // #0 memset 17 // #1 init_one_static_tls 18 // #2 __pthread_init_static_tls 19 // [[ this is where main calls dlopen ]] 20 // #3 main 21 // Previous write of size 8 at 0x7f1fa9bfcdd0 by thread T1: 22 // #0 __tsan_tls_initialization 23 24 // Failing on bots: 25 // https://lab.llvm.org/buildbot#builders/184/builds/1580 26 // https://lab.llvm.org/buildbot#builders/18/builds/3167 27 // UNSUPPORTED: aarch64, powerpc64, powerpc64le 28 29 #ifdef BUILD_SO 30 31 __attribute__((tls_model("initial-exec"))) __thread char x = 42; 32 __attribute__((tls_model("initial-exec"))) __thread char y; 33 34 extern "C" int sofunc() { return ++x + ++y; } 35 36 #else // BUILD_SO 37 38 # include "../test.h" 39 # include <dlfcn.h> 40 # include <string> 41 42 __thread int x[1023]; 43 44 void *lib; 45 void (*func)(); 46 int ready; 47 48 void *thread(void *arg) { 49 barrier_wait(&barrier); 50 if (__atomic_load_n(&ready, __ATOMIC_ACQUIRE)) 51 func(); 52 barrier_wait(&barrier); 53 if (dlclose(lib)) { 54 printf("error in dlclose: %s\n", dlerror()); 55 exit(1); 56 } 57 return 0; 58 } 59 60 int main(int argc, char *argv[]) { 61 barrier_init(&barrier, 2); 62 pthread_t th; 63 pthread_create(&th, 0, thread, 0); 64 lib = dlopen((std::string(argv[0]) + "-so.so").c_str(), RTLD_NOW); 65 if (lib == 0) { 66 printf("error in dlopen: %s\n", dlerror()); 67 return 1; 68 } 69 func = (void (*)())dlsym(lib, "sofunc"); 70 if (func == 0) { 71 printf("error in dlsym: %s\n", dlerror()); 72 return 1; 73 } 74 __atomic_store_n(&ready, 1, __ATOMIC_RELEASE); 75 barrier_wait(&barrier); 76 func(); 77 barrier_wait(&barrier); 78 pthread_join(th, 0); 79 fprintf(stderr, "DONE\n"); 80 return 0; 81 } 82 83 #endif // BUILD_SO 84 85 // CHECK: DONE 86