xref: /llvm-project/compiler-rt/test/hwasan/TestCases/Linux/create-thread-stress.cpp (revision fab079275aac895d5f48b96006f62390a5e24664)
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 Stepanov void 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 Stepanov void 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 Stepanov int 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