diff --git a/compiler-rt/test/lsan/TestCases/many_threads.cpp b/compiler-rt/test/lsan/TestCases/many_threads.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/lsan/TestCases/many_threads.cpp @@ -0,0 +1,94 @@ +// Test that threads are reused. +// RUN: %clangxx_lsan %s -o %t -lpthread +// RUN: %run %t 2>&1 + +#include +#include + +pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + +static const size_t kTestThreads = 10000; + +void *waiting_func(void *args) { + pthread_mutex_lock(&mu); + pthread_cond_broadcast(&cond); + pthread_mutex_unlock(&mu); + return NULL; +} + +void *null_func(void *args) { + return NULL; +} + +void join(void) { + for (size_t i = 0; i < kTestThreads; i++) { + pthread_t thread; + pthread_create(&thread, NULL, null_func, NULL); + pthread_join(thread, NULL); + } +} + +void join_exited(void) { + pthread_mutex_lock(&mu); + + for (size_t i = 0; i < kTestThreads; i++) { + pthread_t thread; + pthread_create(&thread, NULL, waiting_func, NULL); + pthread_cond_wait(&cond, &mu); + pthread_join(thread, NULL); + } + + pthread_mutex_unlock(&mu); +} + +void detach_live(void) { + pthread_mutex_lock(&mu); + + for (size_t i = 0; i < kTestThreads; i++) { + pthread_t thread; + pthread_create(&thread, NULL, waiting_func, NULL); + pthread_cond_wait(&cond, &mu); + pthread_detach(thread); + } + + pthread_mutex_unlock(&mu); +} + +void detach_exited(void) { + pthread_mutex_lock(&mu); + + for (size_t i = 0; i < kTestThreads; i++) { + pthread_t thread; + pthread_create(&thread, NULL, waiting_func, NULL); + pthread_detach(thread); + pthread_cond_wait(&cond, &mu); + } + + pthread_mutex_unlock(&mu); +} + +void starts_detached(void) { + pthread_attr_t attrs; + pthread_attr_init(&attrs); + pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED); + + pthread_mutex_lock(&mu); + + for (size_t i = 0; i < kTestThreads; i++) { + pthread_t thread; + pthread_create(&thread, &attrs, waiting_func, NULL); + pthread_cond_wait(&cond, &mu); + } + + pthread_mutex_unlock(&mu); +} + +int main() { + detach_live(); + detach_exited(); + starts_detached(); + join(); + join_exited(); + return 0; +}