xref: /llvm-project/lldb/test/API/api/multithreaded/test_concurrent_unwind.cpp.template (revision 186fac33d08b34be494caa58fe63972f69c6d6ab)
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