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