1 //===-- main.cpp ------------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // This test is intended to create a situation in which one thread will exit 10 // while a breakpoint is being handled in another thread. This may not always 11 // happen because it's possible that the exiting thread will exit before the 12 // breakpoint is hit. The test case should be flexible enough to treat that 13 // as success. 14 15 #include "pseudo_barrier.h" 16 #include <chrono> 17 #include <thread> 18 19 volatile int g_test = 0; 20 21 // A barrier to synchronize all the threads. 22 pseudo_barrier_t g_barrier1; 23 24 // A barrier to keep the threads from exiting until after the breakpoint has 25 // been passed. 26 pseudo_barrier_t g_barrier2; 27 28 void * 29 break_thread_func () 30 { 31 // Wait until all the threads are running 32 pseudo_barrier_wait(g_barrier1); 33 34 // Wait for the join thread to join 35 std::this_thread::sleep_for(std::chrono::microseconds(50)); 36 37 // Do something 38 g_test++; // Set breakpoint here 39 40 // Synchronize after the breakpoint 41 pseudo_barrier_wait(g_barrier2); 42 43 // Return 44 return NULL; 45 } 46 47 void * 48 wait_thread_func () 49 { 50 // Wait until the entire first group of threads is running 51 pseudo_barrier_wait(g_barrier1); 52 53 // Wait until the breakpoint has been passed 54 pseudo_barrier_wait(g_barrier2); 55 56 // Return 57 return NULL; 58 } 59 60 void * 61 join_thread_func (void *input) 62 { 63 std::thread *thread_to_join = (std::thread *)input; 64 65 // Sync up with the rest of the threads. 66 pseudo_barrier_wait(g_barrier1); 67 68 // Join the other thread 69 thread_to_join->join(); 70 71 // Return 72 return NULL; 73 } 74 75 int main () 76 { 77 // The first barrier waits for the non-joining threads to start. 78 // This thread will also participate in that barrier. 79 // The idea here is to guarantee that the joining thread will be 80 // last in the internal list maintained by the debugger. 81 pseudo_barrier_init(g_barrier1, 5); 82 83 // The second barrier keeps the waiting threads around until the breakpoint 84 // has been passed. 85 pseudo_barrier_init(g_barrier2, 4); 86 87 // Create a thread to hit the breakpoint 88 std::thread thread_1(break_thread_func); 89 90 // Create more threads to slow the debugger down during processing. 91 std::thread thread_2(wait_thread_func); 92 std::thread thread_3(wait_thread_func); 93 std::thread thread_4(wait_thread_func); 94 95 // Create a thread to join the breakpoint thread 96 std::thread thread_5(join_thread_func, &thread_1); 97 98 // Wait for the threads to finish 99 thread_5.join(); // implies thread_1 is already finished 100 thread_4.join(); 101 thread_3.join(); 102 thread_2.join(); 103 104 return 0; 105 } 106