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