1*99451b44SJordan Rupprecht // This test is intended to create a situation in which one thread will exit 2*99451b44SJordan Rupprecht // while the debugger is stepping in another thread. 3*99451b44SJordan Rupprecht 4*99451b44SJordan Rupprecht #include "pseudo_barrier.h" 5*99451b44SJordan Rupprecht #include <thread> 6*99451b44SJordan Rupprecht 7*99451b44SJordan Rupprecht #define do_nothing() 8*99451b44SJordan Rupprecht 9*99451b44SJordan Rupprecht // A barrier to synchronize thread start. 10*99451b44SJordan Rupprecht pseudo_barrier_t g_barrier; 11*99451b44SJordan Rupprecht 12*99451b44SJordan Rupprecht volatile int g_thread_exited = 0; 13*99451b44SJordan Rupprecht 14*99451b44SJordan Rupprecht volatile int g_test = 0; 15*99451b44SJordan Rupprecht 16*99451b44SJordan Rupprecht void * step_thread_func()17*99451b44SJordan Rupprechtstep_thread_func () 18*99451b44SJordan Rupprecht { 19*99451b44SJordan Rupprecht // Wait until both threads are started. 20*99451b44SJordan Rupprecht pseudo_barrier_wait(g_barrier); 21*99451b44SJordan Rupprecht 22*99451b44SJordan Rupprecht g_test = 0; // Set breakpoint here 23*99451b44SJordan Rupprecht 24*99451b44SJordan Rupprecht while (!g_thread_exited) 25*99451b44SJordan Rupprecht g_test++; 26*99451b44SJordan Rupprecht 27*99451b44SJordan Rupprecht // One more time to provide a continue point 28*99451b44SJordan Rupprecht g_test++; // Continue from here 29*99451b44SJordan Rupprecht 30*99451b44SJordan Rupprecht // Return 31*99451b44SJordan Rupprecht return NULL; 32*99451b44SJordan Rupprecht } 33*99451b44SJordan Rupprecht 34*99451b44SJordan Rupprecht void * exit_thread_func()35*99451b44SJordan Rupprechtexit_thread_func () 36*99451b44SJordan Rupprecht { 37*99451b44SJordan Rupprecht // Wait until both threads are started. 38*99451b44SJordan Rupprecht pseudo_barrier_wait(g_barrier); 39*99451b44SJordan Rupprecht 40*99451b44SJordan Rupprecht // Wait until the other thread is stepping. 41*99451b44SJordan Rupprecht while (g_test == 0) 42*99451b44SJordan Rupprecht do_nothing(); 43*99451b44SJordan Rupprecht 44*99451b44SJordan Rupprecht // Return 45*99451b44SJordan Rupprecht return NULL; 46*99451b44SJordan Rupprecht } 47*99451b44SJordan Rupprecht main()48*99451b44SJordan Rupprechtint main () 49*99451b44SJordan Rupprecht { 50*99451b44SJordan Rupprecht // Synchronize thread start so that doesn't happen during stepping. 51*99451b44SJordan Rupprecht pseudo_barrier_init(g_barrier, 2); 52*99451b44SJordan Rupprecht 53*99451b44SJordan Rupprecht // Create a thread to hit the breakpoint. 54*99451b44SJordan Rupprecht std::thread thread_1(step_thread_func); 55*99451b44SJordan Rupprecht 56*99451b44SJordan Rupprecht // Create a thread to exit while we're stepping. 57*99451b44SJordan Rupprecht std::thread thread_2(exit_thread_func); 58*99451b44SJordan Rupprecht 59*99451b44SJordan Rupprecht // Wait for the exit thread to finish. 60*99451b44SJordan Rupprecht thread_2.join(); 61*99451b44SJordan Rupprecht 62*99451b44SJordan Rupprecht // Let the stepping thread know the other thread is gone. 63*99451b44SJordan Rupprecht g_thread_exited = 1; 64*99451b44SJordan Rupprecht 65*99451b44SJordan Rupprecht // Wait for the stepping thread to finish. 66*99451b44SJordan Rupprecht thread_1.join(); 67*99451b44SJordan Rupprecht 68*99451b44SJordan Rupprecht return 0; 69*99451b44SJordan Rupprecht } 70