1 // Test how creating and joining a lot of threads making only a few allocations
2 // each affect total quarantine (and overall heap) size.
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
12 #include <sanitizer/allocator_interface.h>
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
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;
26 void *ThreadFn(void *unused
) {
27 char *temp
= new char[kAllocSize
];
28 memset(temp
, -1, kAllocSize
);
34 // Warm up all internal structures.
36 pthread_create(&t
, 0, ThreadFn
, 0);
39 size_t heap_size
= __sanitizer_get_heap_size();
40 fprintf(stderr
, "Heap size: %zd\n", heap_size
);
42 for (int i
= 0; i
< kNumThreads
; i
++) {
44 pthread_create(&t
, 0, ThreadFn
, 0);
47 size_t new_heap_size
= __sanitizer_get_heap_size();
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");
56 // CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD: Heap growth is within limits