diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/asan/TestCases/Linux/thread_local_quarantine_pthread_join.cc | 56 | ||||
-rw-r--r-- | test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc | 38 |
2 files changed, 76 insertions, 18 deletions
diff --git a/test/asan/TestCases/Linux/thread_local_quarantine_pthread_join.cc b/test/asan/TestCases/Linux/thread_local_quarantine_pthread_join.cc new file mode 100644 index 000000000..8a5bb25ee --- /dev/null +++ b/test/asan/TestCases/Linux/thread_local_quarantine_pthread_join.cc @@ -0,0 +1,56 @@ +// Test how creating and joining a lot of threads making only a few allocations +// each affect total quarantine (and overall heap) size. + +// RUN: %clangxx_asan %s -o %t +// 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 | \ +// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sanitizer/allocator_interface.h> + +// Thread local quarantine is merged to the global one when thread exits and +// this scenario (a few allocations per thread) used to generate a huge overhead +// of practically empty quarantine batches (one per thread). +static const size_t kHeapSizeIncrementLimit = 2 << 20; +static const int kNumThreads = 2048; +// The allocation size is so small because all we want to test is that +// quarantine block merging process does not leak memory used for quarantine +// blocks. +// TODO(alekseyshl): Add more comprehensive test verifying quarantine size +// directly (requires quarantine stats exposed in allocator stats and API). +static const int kAllocSize = 1; + +void *ThreadFn(void *unused) { + char *temp = new char[kAllocSize]; + memset(temp, -1, kAllocSize); + delete [] (temp); + return NULL; +} + +int main() { + // Warm up all internal structures. + pthread_t t; + pthread_create(&t, 0, ThreadFn, 0); + pthread_join(t, 0); + + size_t heap_size = __sanitizer_get_heap_size(); + fprintf(stderr, "Heap size: %zd\n", heap_size); + + for (int i = 0; i < kNumThreads; i++) { + pthread_t t; + pthread_create(&t, 0, ThreadFn, 0); + pthread_join(t, 0); + + size_t new_heap_size = __sanitizer_get_heap_size(); + } + + size_t new_heap_size = __sanitizer_get_heap_size(); + fprintf(stderr, "New heap size: %zd\n", new_heap_size); + if (new_heap_size - heap_size < kHeapSizeIncrementLimit) + fprintf(stderr, "Heap growth is within limits\n"); +} + +// CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD: Heap growth is within limits diff --git a/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc b/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc index 24022a140..46af1a0e0 100644 --- a/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc +++ b/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc @@ -1,12 +1,10 @@ // Test thread_local_quarantine_size_kb // RUN: %clangxx_asan %s -o %t -// RUN: %env_asan_opts=thread_local_quarantine_size_kb=256:verbosity=1 %run %t 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CHECK-VALUE -// RUN: %env_asan_opts=thread_local_quarantine_size_kb=64:quarantine_size_mb=64 %run %t 2>&1 | \ +// RUN: %env_asan_opts=thread_local_quarantine_size_kb=64:quarantine_size_mb=64:verbosity=1 %run %t 2>&1 | \ // RUN: FileCheck %s --allow-empty --check-prefix=CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD // RUN: %env_asan_opts=thread_local_quarantine_size_kb=0:quarantine_size_mb=0 %run %t 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CHECK-QUARANTINE-DISABLED +// RUN: FileCheck %s --check-prefix=CHECK-QUARANTINE-DISABLED-SMALL-OVERHEAD // RUN: %env_asan_opts=thread_local_quarantine_size_kb=0:quarantine_size_mb=64 not %run %t 2>&1 | \ // RUN: FileCheck %s --check-prefix=CHECK-FOR-PARAMETER-ERROR @@ -15,29 +13,33 @@ #include <string.h> #include <sanitizer/allocator_interface.h> -// The idea is allocate a lot of small blocks, totaling 5Mb of user memory -// total, and verify that quarantine does not incur too much memory overhead. +// The idea is allocate a lot of small blocks, totaling 5Mb of user memory, +// and verify that quarantine does not incur too much memory overhead. // There's always an overhead for red zones, shadow memory and such, but // quarantine accounting should not significantly contribute to that. +// The zero sized thread local cache is specifically tested since it used to +// generate a huge overhead of almost empty quarantine batches. +static const size_t kHeapSizeIncrementLimit = 12 << 20; static const int kNumAllocs = 20000; static const int kAllocSize = 256; -static const size_t kHeapSizeLimit = 12 << 20; int main() { - size_t old_heap_size = __sanitizer_get_heap_size(); + size_t heap_size = __sanitizer_get_heap_size(); + fprintf(stderr, "Heap size: %zd\n", heap_size); + for (int i = 0; i < kNumAllocs; i++) { - char *g = new char[kAllocSize]; - memset(g, -1, kAllocSize); - delete [] (g); + char *temp = new char[kAllocSize]; + memset(temp, -1, kAllocSize); + delete [] (temp); } + size_t new_heap_size = __sanitizer_get_heap_size(); - fprintf(stderr, "heap size: new: %zd old: %zd\n", new_heap_size, - old_heap_size); - if (new_heap_size - old_heap_size > kHeapSizeLimit) - fprintf(stderr, "Heap size limit exceeded"); + fprintf(stderr, "New heap size: %zd\n", new_heap_size); + if (new_heap_size - heap_size < kHeapSizeIncrementLimit) + fprintf(stderr, "Heap growth is within limits\n"); } -// CHECK-VALUE: thread_local_quarantine_size_kb=256K -// CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD-NOT: Heap size limit exceeded -// CHECK-QUARANTINE-DISABLED-NOT: Heap size limit exceeded +// CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD: thread_local_quarantine_size_kb=64K +// CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD: Heap growth is within limits +// CHECK-QUARANTINE-DISABLED-SMALL-OVERHEAD: Heap growth is within limits // CHECK-FOR-PARAMETER-ERROR: thread_local_quarantine_size_kb can be set to 0 only when quarantine_size_mb is set to 0 |