1a7757f6cSEvgenii Stepanov // Stress test for https://reviews.llvm.org/D101881 2a7757f6cSEvgenii Stepanov // RUN: %clangxx_hwasan -DREUSE=0 %s -pthread -O2 -o %t && %run %t 2>&1 3a7757f6cSEvgenii Stepanov // RUN: %clangxx_hwasan -DREUSE=1 %s -pthread -O2 -o %t_reuse && %run %t_reuse 2>&1 4a7757f6cSEvgenii Stepanov 5a7757f6cSEvgenii Stepanov #include <thread> 6a7757f6cSEvgenii Stepanov #include <vector> 7a7757f6cSEvgenii Stepanov 8a7757f6cSEvgenii Stepanov #include <sys/types.h> 9a7757f6cSEvgenii Stepanov #include <sys/wait.h> 10a7757f6cSEvgenii Stepanov #include <unistd.h> 11a7757f6cSEvgenii Stepanov 12a7757f6cSEvgenii Stepanov #include <stdio.h> 13a7757f6cSEvgenii Stepanov 14a7757f6cSEvgenii Stepanov constexpr int kTopThreads = 20; 15a7757f6cSEvgenii Stepanov constexpr int kChildThreads = 30; 16a7757f6cSEvgenii Stepanov constexpr int kChildIterations = REUSE ? 8 : 1; 17a7757f6cSEvgenii Stepanov 18a7757f6cSEvgenii Stepanov constexpr int kProcessIterations = 20; 19a7757f6cSEvgenii Stepanov Thread()20a7757f6cSEvgenii Stepanovvoid Thread() { 21a7757f6cSEvgenii Stepanov for (int i = 0; i < kChildIterations; ++i) { 22a7757f6cSEvgenii Stepanov std::vector<std::thread> threads; 23*fab07927SVitaly Buka threads.reserve(kChildThreads); 24a7757f6cSEvgenii Stepanov for (int i = 0; i < kChildThreads; ++i) 25a7757f6cSEvgenii Stepanov threads.emplace_back([]() {}); 26a7757f6cSEvgenii Stepanov for (auto &t : threads) 27a7757f6cSEvgenii Stepanov t.join(); 28a7757f6cSEvgenii Stepanov } 29a7757f6cSEvgenii Stepanov } 30a7757f6cSEvgenii Stepanov run()31a7757f6cSEvgenii Stepanovvoid run() { 32a7757f6cSEvgenii Stepanov std::vector<std::thread> threads; 33*fab07927SVitaly Buka threads.reserve(kTopThreads); 34a7757f6cSEvgenii Stepanov for (int i = 0; i < kTopThreads; ++i) 35a7757f6cSEvgenii Stepanov threads.emplace_back(Thread); 36a7757f6cSEvgenii Stepanov for (auto &t : threads) 37a7757f6cSEvgenii Stepanov t.join(); 38a7757f6cSEvgenii Stepanov } 39a7757f6cSEvgenii Stepanov main()40a7757f6cSEvgenii Stepanovint main() { 41a7757f6cSEvgenii Stepanov #if REUSE 42a7757f6cSEvgenii Stepanov // Test thread reuse with multiple iterations of thread create / join in a single process. 43a7757f6cSEvgenii Stepanov run(); 44a7757f6cSEvgenii Stepanov #else 45a7757f6cSEvgenii Stepanov // Test new, non-reused thread creation by running a single iteration of create / join in a freshly started process. 46a7757f6cSEvgenii Stepanov for (int i = 0; i < kProcessIterations; ++i) { 47a7757f6cSEvgenii Stepanov int pid = fork(); 48a7757f6cSEvgenii Stepanov if (pid) { 49a7757f6cSEvgenii Stepanov int wstatus; 50a7757f6cSEvgenii Stepanov do { 51a7757f6cSEvgenii Stepanov waitpid(pid, &wstatus, 0); 52a7757f6cSEvgenii Stepanov } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus)); 53a7757f6cSEvgenii Stepanov if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) { 54a7757f6cSEvgenii Stepanov fprintf(stderr, "failed at iteration %d / %d\n", i, kProcessIterations); 55a7757f6cSEvgenii Stepanov return 1; 56a7757f6cSEvgenii Stepanov } 57a7757f6cSEvgenii Stepanov } else { 58a7757f6cSEvgenii Stepanov run(); 59a7757f6cSEvgenii Stepanov return 0; 60a7757f6cSEvgenii Stepanov } 61a7757f6cSEvgenii Stepanov } 62a7757f6cSEvgenii Stepanov #endif 63a7757f6cSEvgenii Stepanov } 64