1d2e0f207SKamil Rytarowski // Test that lsan handles tls correctly for many threads
2f7877dd4SKamil Rytarowski // RUN: %clangxx_lsan %s -o %t
3d08e5d4cSClemens Wasser // RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=0" not %run %t 2>&1 | FileCheck %s
4d08e5d4cSClemens Wasser // RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=1" %run %t 2>&1
5f7877dd4SKamil Rytarowski // RUN: %env_lsan_opts="" %run %t 2>&1
6d2e0f207SKamil Rytarowski
7fdf97bc7SFangrui Song // On glibc, this requires the range returned by GetTLS to include
8fdf97bc7SFangrui Song // specific_1stblock and specific in `struct pthread`.
9afec9538SFangrui Song // UNSUPPORTED: arm-linux, armhf-linux
10d2e0f207SKamil Rytarowski
11f7877dd4SKamil Rytarowski // TSD on NetBSD does not use TLS
120773a5cbSPaul Robinson // UNSUPPORTED: target={{.*netbsd.*}}
13f7877dd4SKamil Rytarowski
14d2e0f207SKamil Rytarowski #include <assert.h>
15d2e0f207SKamil Rytarowski #include <limits.h>
16d2e0f207SKamil Rytarowski #include <pthread.h>
17d2e0f207SKamil Rytarowski #include <stdlib.h>
18d2e0f207SKamil Rytarowski #include <unistd.h>
19d2e0f207SKamil Rytarowski
20d2e0f207SKamil Rytarowski static const int NUM_THREADS = 10;
21d2e0f207SKamil Rytarowski
22d2e0f207SKamil Rytarowski pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
23d2e0f207SKamil Rytarowski pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
24d2e0f207SKamil Rytarowski int finished = 0;
25d2e0f207SKamil Rytarowski
26d2e0f207SKamil Rytarowski // We won't be able to create the maximum number of keys, due to other users
27d2e0f207SKamil Rytarowski // of the tls, but we'll use as many keys as we can before failing to create
28d2e0f207SKamil Rytarowski // a new key.
29d2e0f207SKamil Rytarowski pthread_key_t keys[PTHREAD_KEYS_MAX];
30d2e0f207SKamil Rytarowski static const int PTHREAD_KEY_INVALID = 0xffffffff;
31d2e0f207SKamil Rytarowski
alloc()32d2e0f207SKamil Rytarowski void alloc() {
33d2e0f207SKamil Rytarowski for (int i = 0; i < PTHREAD_KEYS_MAX; ++i) {
34d2e0f207SKamil Rytarowski void *ptr = malloc(123);
35d2e0f207SKamil Rytarowski if ((keys[i] == PTHREAD_KEY_INVALID) || pthread_setspecific(keys[i], ptr)) {
36d2e0f207SKamil Rytarowski free(ptr);
37d2e0f207SKamil Rytarowski break;
38d2e0f207SKamil Rytarowski }
39d2e0f207SKamil Rytarowski }
40d2e0f207SKamil Rytarowski }
41d2e0f207SKamil Rytarowski
pthread_destructor(void * arg)42d2e0f207SKamil Rytarowski void pthread_destructor(void *arg) {
43d2e0f207SKamil Rytarowski assert(0 && "pthread destructors shouldn't be called");
44d2e0f207SKamil Rytarowski }
45d2e0f207SKamil Rytarowski
thread_start(void * arg)46d2e0f207SKamil Rytarowski void *thread_start(void *arg) {
47d2e0f207SKamil Rytarowski alloc();
48d2e0f207SKamil Rytarowski
49d2e0f207SKamil Rytarowski pthread_mutex_lock(&mutex);
50d2e0f207SKamil Rytarowski finished++;
51d2e0f207SKamil Rytarowski pthread_mutex_unlock(&mutex);
52d2e0f207SKamil Rytarowski
53d2e0f207SKamil Rytarowski // don't exit, to intentionally leak tls data
54d2e0f207SKamil Rytarowski while (1)
55d2e0f207SKamil Rytarowski sleep(100);
56d2e0f207SKamil Rytarowski }
57d2e0f207SKamil Rytarowski
main()58d2e0f207SKamil Rytarowski int main() {
59d2e0f207SKamil Rytarowski for (int i = 0; i < PTHREAD_KEYS_MAX; ++i) {
60d2e0f207SKamil Rytarowski if (pthread_key_create(&keys[i], pthread_destructor)) {
61d2e0f207SKamil Rytarowski keys[i] = PTHREAD_KEY_INVALID;
62d2e0f207SKamil Rytarowski break;
63d2e0f207SKamil Rytarowski }
64d2e0f207SKamil Rytarowski }
65d2e0f207SKamil Rytarowski
66d2e0f207SKamil Rytarowski pthread_t thread[NUM_THREADS];
67d2e0f207SKamil Rytarowski for (int i = 0; i < NUM_THREADS; ++i) {
68d2e0f207SKamil Rytarowski assert(0 == pthread_create(&thread[i], 0, thread_start, 0));
69d2e0f207SKamil Rytarowski }
70d2e0f207SKamil Rytarowski // spin until all threads have finished
71d2e0f207SKamil Rytarowski while (finished < NUM_THREADS)
72d2e0f207SKamil Rytarowski sleep(1);
73d2e0f207SKamil Rytarowski exit(0);
74d2e0f207SKamil Rytarowski }
75d2e0f207SKamil Rytarowski
76d2e0f207SKamil Rytarowski // CHECK: LeakSanitizer: detected memory leaks
77*029b410dSKirill Stoimenov // CHECK: SUMMARY: {{.*}}Sanitizer:
78