File: dlopen_static_tls.cpp

package info (click to toggle)
swiftlang 6.1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,791,532 kB
  • sloc: cpp: 9,901,743; ansic: 2,201,431; asm: 1,091,827; python: 308,252; objc: 82,166; f90: 80,126; lisp: 38,358; pascal: 25,559; sh: 20,429; ml: 5,058; perl: 4,745; makefile: 4,484; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (85 lines) | stat: -rw-r--r-- 2,572 bytes parent folder | download | duplicates (21)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// RUN: %clangxx_tsan -O1 %s -DBUILD_SO -fPIC -shared -o %t-so.so
// RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t && %run %t 2>&1 | FileCheck %s

// A test for loading a dynamic library with static TLS.
// Such static TLS is a hack that allows a dynamic library to have faster TLS,
// but it can be loaded only iff all threads happened to allocate some excess
// of static TLS space for whatever reason. If it's not the case loading fails with:
// dlopen: cannot load any more object with static TLS
// We used to produce a false positive because dlopen will write into TLS
// of all existing threads to initialize/zero TLS region for the loaded library.
// And this appears to be racing with initialization of TLS in the thread
// since we model a write into the whole static TLS region (we don't know what part
// of it is currently unused):
// WARNING: ThreadSanitizer: data race (pid=2317365)
//   Write of size 1 at 0x7f1fa9bfcdd7 by main thread:
//     #0 memset
//     #1 init_one_static_tls
//     #2 __pthread_init_static_tls
//     [[ this is where main calls dlopen ]]
//     #3 main
//   Previous write of size 8 at 0x7f1fa9bfcdd0 by thread T1:
//     #0 __tsan_tls_initialization

// Failing on bots:
// https://lab.llvm.org/buildbot#builders/184/builds/1580
// https://lab.llvm.org/buildbot#builders/18/builds/3167
// UNSUPPORTED: target={{(aarch64|powerpc64).*}}

#ifdef BUILD_SO

__attribute__((tls_model("initial-exec"))) __thread char x = 42;
__attribute__((tls_model("initial-exec"))) __thread char y;

extern "C" int sofunc() { return ++x + ++y; }

#else // BUILD_SO

#  include "../test.h"
#  include <dlfcn.h>
#  include <string>

__thread int x[1023];

void *lib;
void (*func)();
int ready;

void *thread(void *arg) {
  barrier_wait(&barrier);
  if (__atomic_load_n(&ready, __ATOMIC_ACQUIRE))
    func();
  barrier_wait(&barrier);
  if (dlclose(lib)) {
    printf("error in dlclose: %s\n", dlerror());
    exit(1);
  }
  return 0;
}

int main(int argc, char *argv[]) {
  barrier_init(&barrier, 2);
  pthread_t th;
  pthread_create(&th, 0, thread, 0);
  lib = dlopen((std::string(argv[0]) + "-so.so").c_str(), RTLD_NOW);
  if (lib == 0) {
    printf("error in dlopen: %s\n", dlerror());
    return 1;
  }
  func = (void (*)())dlsym(lib, "sofunc");
  if (func == 0) {
    printf("error in dlsym: %s\n", dlerror());
    return 1;
  }
  __atomic_store_n(&ready, 1, __ATOMIC_RELEASE);
  barrier_wait(&barrier);
  func();
  barrier_wait(&barrier);
  pthread_join(th, 0);
  fprintf(stderr, "DONE\n");
  return 0;
}

#endif // BUILD_SO

// CHECK: DONE