1*186fac33Sjimingham#include "pseudo_barrier.h" 2*186fac33Sjimingham 3*186fac33Sjimingham#include <atomic> 4*186fac33Sjimingham#include <thread> 5*186fac33Sjimingham 6*186fac33Sjimingham%include_SB_APIs% 7*186fac33Sjimingham 8*186fac33Sjimingham#include "common.h" 9*186fac33Sjimingham 10*186fac33Sjiminghamusing namespace lldb; 11*186fac33Sjimingham 12*186fac33Sjiminghamvoid test (SBDebugger &dbg, std::vector<std::string> args) { 13*186fac33Sjimingham 14*186fac33SjiminghamSBError error; 15*186fac33Sjimingham dbg.SetAsync(false); 16*186fac33Sjimingham SBTarget target = dbg.CreateTarget(args.at(0).c_str()); 17*186fac33Sjimingham if (!target.IsValid()) 18*186fac33Sjimingham throw Exception("Invalid target"); 19*186fac33Sjimingham 20*186fac33Sjimingham // Now set our breakpoint and launch: 21*186fac33Sjimingham SBFileSpec main_sourcefile("deep_stack.cpp"); 22*186fac33Sjimingham SBBreakpoint bkpt = target.BreakpointCreateBySourceRegex("Set a breakpoint here", 23*186fac33Sjimingham main_sourcefile); 24*186fac33Sjimingham if (bkpt.GetNumLocations() == 0) 25*186fac33Sjimingham throw Exception("Main breakpoint got no locations"); 26*186fac33Sjimingham 27*186fac33Sjimingham SBLaunchInfo launch_info = target.GetLaunchInfo(); 28*186fac33Sjimingham SBProcess process = target.Launch(launch_info, error); 29*186fac33Sjimingham if (error.Fail()) 30*186fac33Sjimingham throw Exception("Failed to launch process"); 31*186fac33Sjimingham if (!process.IsValid()) 32*186fac33Sjimingham throw Exception("Process is not valid"); 33*186fac33Sjimingham if (process.GetState() != lldb::eStateStopped) 34*186fac33Sjimingham throw Exception("Process was not stopped"); 35*186fac33Sjimingham 36*186fac33Sjimingham size_t num_threads = process.GetNumThreads(); 37*186fac33Sjimingham if (num_threads != 1) 38*186fac33Sjimingham throw Exception("Unexpected number of threads."); 39*186fac33Sjimingham SBThread cur_thread = process.GetThreadAtIndex(0); 40*186fac33Sjimingham if (!cur_thread.IsValid()) 41*186fac33Sjimingham throw Exception("Didn't get a valid thread"); 42*186fac33Sjimingham 43*186fac33Sjimingham // Record the number of frames at the point where we stopped: 44*186fac33Sjimingham const size_t num_frames = cur_thread.GetNumFrames(); 45*186fac33Sjimingham // Now step once to clear the frame cache: 46*186fac33Sjimingham cur_thread.StepOver(); 47*186fac33Sjimingham 48*186fac33Sjimingham // Create three threads and set them to getting frames simultaneously, 49*186fac33Sjimingham // and make sure we don't deadlock. 50*186fac33Sjimingham pseudo_barrier_t rendevous; 51*186fac33Sjimingham pseudo_barrier_init(rendevous, 5); 52*186fac33Sjimingham std::atomic_size_t success(true); 53*186fac33Sjimingham std::atomic_size_t largest(0); 54*186fac33Sjimingham 55*186fac33Sjimingham auto lambda = [&](size_t stride){ 56*186fac33Sjimingham pseudo_barrier_wait(rendevous); 57*186fac33Sjimingham bool younger = true; 58*186fac33Sjimingham while (1) { 59*186fac33Sjimingham size_t cursor = largest; 60*186fac33Sjimingham if (cursor > stride && !younger) { 61*186fac33Sjimingham cursor -= stride; 62*186fac33Sjimingham younger = true; 63*186fac33Sjimingham } else { 64*186fac33Sjimingham cursor += stride; 65*186fac33Sjimingham largest += stride; 66*186fac33Sjimingham younger = false; 67*186fac33Sjimingham } 68*186fac33Sjimingham SBFrame frame = cur_thread.GetFrameAtIndex(cursor); 69*186fac33Sjimingham if (!frame.IsValid()) { 70*186fac33Sjimingham if (cursor < num_frames) 71*186fac33Sjimingham success = false; 72*186fac33Sjimingham break; 73*186fac33Sjimingham } 74*186fac33Sjimingham } 75*186fac33Sjimingham 76*186fac33Sjimingham }; 77*186fac33Sjimingham 78*186fac33Sjimingham std::thread thread1(lambda, 1); 79*186fac33Sjimingham std::thread thread2(lambda, 3); 80*186fac33Sjimingham std::thread thread3(lambda, 5); 81*186fac33Sjimingham std::thread thread4(lambda, 7); 82*186fac33Sjimingham std::thread thread5(lambda, 11); 83*186fac33Sjimingham thread1.join(); 84*186fac33Sjimingham thread2.join(); 85*186fac33Sjimingham thread3.join(); 86*186fac33Sjimingham thread4.join(); 87*186fac33Sjimingham thread5.join(); 88*186fac33Sjimingham 89*186fac33Sjimingham if (!success) 90*186fac33Sjimingham throw Exception("One thread stopped before 1000"); 91*186fac33Sjimingham} 92