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
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:
17 // #1 init_one_static_tls
18 // #2 __pthread_init_static_tls
19 // [[ this is where main calls dlopen ]]
21 // Previous write of size 8 at 0x7f1fa9bfcdd0 by thread T1:
22 // #0 __tsan_tls_initialization
25 // https://lab.llvm.org/buildbot#builders/184/builds/1580
26 // https://lab.llvm.org/buildbot#builders/18/builds/3167
27 // UNSUPPORTED: target={{(aarch64|powerpc64).*}}
31 __attribute__((tls_model("initial-exec"))) __thread
char x
= 42;
32 __attribute__((tls_model("initial-exec"))) __thread
char y
;
34 extern "C" int sofunc() { return ++x
+ ++y
; }
48 void *thread(void *arg
) {
49 barrier_wait(&barrier
);
50 if (__atomic_load_n(&ready
, __ATOMIC_ACQUIRE
))
52 barrier_wait(&barrier
);
54 printf("error in dlclose: %s\n", dlerror());
60 int main(int argc
, char *argv
[]) {
61 barrier_init(&barrier
, 2);
63 pthread_create(&th
, 0, thread
, 0);
64 lib
= dlopen((std::string(argv
[0]) + "-so.so").c_str(), RTLD_NOW
);
66 printf("error in dlopen: %s\n", dlerror());
69 func
= (void (*)())dlsym(lib
, "sofunc");
71 printf("error in dlsym: %s\n", dlerror());
74 __atomic_store_n(&ready
, 1, __ATOMIC_RELEASE
);
75 barrier_wait(&barrier
);
77 barrier_wait(&barrier
);
79 fprintf(stderr
, "DONE\n");