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