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