xref: /llvm-project/lldb/test/API/functionalities/thread/exit_during_break/main.cpp (revision fdea9a4ec9b0d9585b8fe8a612686d9f44f40ddc)
1*99451b44SJordan Rupprecht // This test is intended to create a situation in which one thread will exit
2*99451b44SJordan Rupprecht // while a breakpoint is being handled in another thread.  This may not always
3*99451b44SJordan Rupprecht // happen because it's possible that the exiting thread will exit before the
4*99451b44SJordan Rupprecht // breakpoint is hit.  The test case should be flexible enough to treat that
5*99451b44SJordan Rupprecht // as success.
6*99451b44SJordan Rupprecht 
7*99451b44SJordan Rupprecht #include "pseudo_barrier.h"
8*99451b44SJordan Rupprecht #include <chrono>
9*99451b44SJordan Rupprecht #include <thread>
10*99451b44SJordan Rupprecht 
11*99451b44SJordan Rupprecht volatile int g_test = 0;
12*99451b44SJordan Rupprecht 
13*99451b44SJordan Rupprecht // A barrier to synchronize all the threads except the one that will exit.
14*99451b44SJordan Rupprecht pseudo_barrier_t g_barrier1;
15*99451b44SJordan Rupprecht 
16*99451b44SJordan Rupprecht // A barrier to synchronize all the threads including the one that will exit.
17*99451b44SJordan Rupprecht pseudo_barrier_t g_barrier2;
18*99451b44SJordan Rupprecht 
19*99451b44SJordan Rupprecht // A barrier to keep the first group of threads from exiting until after the
20*99451b44SJordan Rupprecht // breakpoint has been passed.
21*99451b44SJordan Rupprecht pseudo_barrier_t g_barrier3;
22*99451b44SJordan Rupprecht 
23*99451b44SJordan Rupprecht void *
break_thread_func()24*99451b44SJordan Rupprecht break_thread_func ()
25*99451b44SJordan Rupprecht {
26*99451b44SJordan Rupprecht     // Wait until the entire first group of threads is running
27*99451b44SJordan Rupprecht     pseudo_barrier_wait(g_barrier1);
28*99451b44SJordan Rupprecht 
29*99451b44SJordan Rupprecht     // Wait for the exiting thread to start
30*99451b44SJordan Rupprecht     pseudo_barrier_wait(g_barrier2);
31*99451b44SJordan Rupprecht 
32*99451b44SJordan Rupprecht     // Do something
33*99451b44SJordan Rupprecht     g_test++;       // Set breakpoint here
34*99451b44SJordan Rupprecht 
35*99451b44SJordan Rupprecht     // Synchronize after the breakpoint
36*99451b44SJordan Rupprecht     pseudo_barrier_wait(g_barrier3);
37*99451b44SJordan Rupprecht 
38*99451b44SJordan Rupprecht     // Return
39*99451b44SJordan Rupprecht     return NULL;
40*99451b44SJordan Rupprecht }
41*99451b44SJordan Rupprecht 
42*99451b44SJordan Rupprecht void *
wait_thread_func()43*99451b44SJordan Rupprecht wait_thread_func ()
44*99451b44SJordan Rupprecht {
45*99451b44SJordan Rupprecht     // Wait until the entire first group of threads is running
46*99451b44SJordan Rupprecht     pseudo_barrier_wait(g_barrier1);
47*99451b44SJordan Rupprecht 
48*99451b44SJordan Rupprecht     // Wait for the exiting thread to start
49*99451b44SJordan Rupprecht     pseudo_barrier_wait(g_barrier2);
50*99451b44SJordan Rupprecht 
51*99451b44SJordan Rupprecht     // Wait until the breakpoint has been passed
52*99451b44SJordan Rupprecht     pseudo_barrier_wait(g_barrier3);
53*99451b44SJordan Rupprecht 
54*99451b44SJordan Rupprecht     // Return
55*99451b44SJordan Rupprecht     return NULL;
56*99451b44SJordan Rupprecht }
57*99451b44SJordan Rupprecht 
58*99451b44SJordan Rupprecht void *
exit_thread_func()59*99451b44SJordan Rupprecht exit_thread_func ()
60*99451b44SJordan Rupprecht {
61*99451b44SJordan Rupprecht     // Sync up with the rest of the threads.
62*99451b44SJordan Rupprecht     pseudo_barrier_wait(g_barrier2);
63*99451b44SJordan Rupprecht 
64*99451b44SJordan Rupprecht     // Try to make sure this thread doesn't exit until the breakpoint is hit.
65*99451b44SJordan Rupprecht     std::this_thread::sleep_for(std::chrono::microseconds(1));
66*99451b44SJordan Rupprecht 
67*99451b44SJordan Rupprecht     // Return
68*99451b44SJordan Rupprecht     return NULL;
69*99451b44SJordan Rupprecht }
70*99451b44SJordan Rupprecht 
main()71*99451b44SJordan Rupprecht int main ()
72*99451b44SJordan Rupprecht {
73*99451b44SJordan Rupprecht 
74*99451b44SJordan Rupprecht     // The first barrier waits for the non-exiting threads to start.
75*99451b44SJordan Rupprecht     // This thread will also participate in that barrier.
76*99451b44SJordan Rupprecht     // The idea here is to guarantee that the exiting thread will be
77*99451b44SJordan Rupprecht     // last in the internal list maintained by the debugger.
78*99451b44SJordan Rupprecht     pseudo_barrier_init(g_barrier1, 5);
79*99451b44SJordan Rupprecht 
80*99451b44SJordan Rupprecht     // The second break synchronizes thread execution with the breakpoint.
81*99451b44SJordan Rupprecht     pseudo_barrier_init(g_barrier2, 5);
82*99451b44SJordan Rupprecht 
83*99451b44SJordan Rupprecht     // The third barrier keeps the waiting threads around until the breakpoint
84*99451b44SJordan Rupprecht     // has been passed.
85*99451b44SJordan Rupprecht     pseudo_barrier_init(g_barrier3, 4);
86*99451b44SJordan Rupprecht 
87*99451b44SJordan Rupprecht     // Create a thread to hit the breakpoint
88*99451b44SJordan Rupprecht     std::thread thread_1(break_thread_func);
89*99451b44SJordan Rupprecht 
90*99451b44SJordan Rupprecht     // Create more threads to slow the debugger down during processing.
91*99451b44SJordan Rupprecht     std::thread thread_2(wait_thread_func);
92*99451b44SJordan Rupprecht     std::thread thread_3(wait_thread_func);
93*99451b44SJordan Rupprecht     std::thread thread_4(wait_thread_func);
94*99451b44SJordan Rupprecht 
95*99451b44SJordan Rupprecht     // Wait for all these threads to get started.
96*99451b44SJordan Rupprecht     pseudo_barrier_wait(g_barrier1);
97*99451b44SJordan Rupprecht 
98*99451b44SJordan Rupprecht     // Create a thread to exit during the breakpoint
99*99451b44SJordan Rupprecht     std::thread thread_5(exit_thread_func);
100*99451b44SJordan Rupprecht 
101*99451b44SJordan Rupprecht     // Wait for the threads to finish
102*99451b44SJordan Rupprecht     thread_5.join();
103*99451b44SJordan Rupprecht     thread_4.join();
104*99451b44SJordan Rupprecht     thread_3.join();
105*99451b44SJordan Rupprecht     thread_2.join();
106*99451b44SJordan Rupprecht     thread_1.join();
107*99451b44SJordan Rupprecht 
108*99451b44SJordan Rupprecht     return 0;
109*99451b44SJordan Rupprecht }
110