xref: /llvm-project/compiler-rt/test/asan/TestCases/Linux/thread_local_quarantine_pthread_join.cpp (revision 673dc3d4a0b0fbb3b9b34ae2ecbfa522627fe582)
1 // Test how creating and joining a lot of threads making only a few allocations
2 // each affect total quarantine (and overall heap) size.
3 
4 // RUN: %clangxx_asan  %s -o %t
5 // RUN: %env_asan_opts=thread_local_quarantine_size_kb=64:quarantine_size_mb=1:allocator_release_to_os_interval_ms=-1 %run %t 2>&1 | \
6 // RUN:   FileCheck %s --allow-empty --check-prefix=CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD
7 
8 #include <pthread.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sanitizer/allocator_interface.h>
13 
14 // Thread local quarantine is merged to the global one when thread exits and
15 // this scenario (a few allocations per thread) used to generate a huge overhead
16 // of practically empty quarantine batches (one per thread).
17 static const size_t kHeapSizeIncrementLimit = 2 << 20;
18 static const int kNumThreads = 2048;
19 // The allocation size is so small because all we want to test is that
20 // quarantine block merging process does not leak memory used for quarantine
21 // blocks.
22 // TODO(alekseyshl): Add more comprehensive test verifying quarantine size
23 // directly (requires quarantine stats exposed in allocator stats and API).
24 static const int kAllocSize = 1;
25 
ThreadFn(void * unused)26 void *ThreadFn(void *unused) {
27   char *temp = new char[kAllocSize];
28   memset(temp, -1, kAllocSize);
29   delete [] (temp);
30   return NULL;
31 }
32 
main()33 int main() {
34   // Warm up all internal structures.
35   pthread_t t;
36   pthread_create(&t, 0, ThreadFn, 0);
37   pthread_join(t, 0);
38 
39   size_t heap_size = __sanitizer_get_heap_size();
40   fprintf(stderr, "Heap size: %zd\n", heap_size);
41 
42   for (int i = 0; i < kNumThreads; i++) {
43     pthread_t t;
44     pthread_create(&t, 0, ThreadFn, 0);
45     pthread_join(t, 0);
46 
47     size_t new_heap_size = __sanitizer_get_heap_size();
48   }
49 
50   size_t new_heap_size = __sanitizer_get_heap_size();
51   fprintf(stderr, "New heap size: %zd\n", new_heap_size);
52   if (new_heap_size - heap_size < kHeapSizeIncrementLimit)
53     fprintf(stderr, "Heap growth is within limits\n");
54 }
55 
56 // CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD: Heap growth is within limits
57