Coverage Report

Created: 2022-01-25 06:29

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Target/ThreadPlanStack.h
Line
Count
Source (jump to first uncovered line)
1
//===-- ThreadPlanStack.h ---------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLDB_TARGET_THREADPLANSTACK_H
10
#define LLDB_TARGET_THREADPLANSTACK_H
11
12
#include <mutex>
13
#include <string>
14
#include <unordered_map>
15
#include <vector>
16
17
#include "lldb/Target/Target.h"
18
#include "lldb/Target/Thread.h"
19
#include "lldb/lldb-private-forward.h"
20
#include "lldb/lldb-private.h"
21
22
namespace lldb_private {
23
24
// The ThreadPlans have a thread for use when they are asked all the ThreadPlan
25
// state machine questions, but they should never cache any pointers from their
26
// owning lldb_private::Thread.  That's because we want to be able to detach
27
// them from an owning thread, then reattach them by TID.
28
// The ThreadPlanStack holds the ThreadPlans for a given TID.  All its methods
29
// are private, and it should only be accessed through the owning thread.  When
30
// it is detached from a thread, all you can do is reattach it or delete it.
31
class ThreadPlanStack {
32
  friend class lldb_private::Thread;
33
34
public:
35
  ThreadPlanStack(const Thread &thread, bool make_empty = false);
36
3.35k
  ~ThreadPlanStack() = default;
37
38
  using PlanStack = std::vector<lldb::ThreadPlanSP>;
39
40
  void DumpThreadPlans(Stream &s, lldb::DescriptionLevel desc_level,
41
                       bool include_internal) const;
42
43
  size_t CheckpointCompletedPlans();
44
45
  void RestoreCompletedPlanCheckpoint(size_t checkpoint);
46
47
  void DiscardCompletedPlanCheckpoint(size_t checkpoint);
48
49
  void ThreadDestroyed(Thread *thread);
50
51
  void PushPlan(lldb::ThreadPlanSP new_plan_sp);
52
53
  lldb::ThreadPlanSP PopPlan();
54
55
  lldb::ThreadPlanSP DiscardPlan();
56
57
  // If the input plan is nullptr, discard all plans.  Otherwise make sure this
58
  // plan is in the stack, and if so discard up to and including it.
59
  void DiscardPlansUpToPlan(ThreadPlan *up_to_plan_ptr);
60
61
  void DiscardAllPlans();
62
63
  void DiscardConsultingControllingPlans();
64
65
  lldb::ThreadPlanSP GetCurrentPlan() const;
66
67
  lldb::ThreadPlanSP GetCompletedPlan(bool skip_private = true) const;
68
69
  lldb::ThreadPlanSP GetPlanByIndex(uint32_t plan_idx,
70
                                    bool skip_private = true) const;
71
72
  lldb::ValueObjectSP GetReturnValueObject() const;
73
74
  lldb::ExpressionVariableSP GetExpressionVariable() const;
75
76
  bool AnyPlans() const;
77
78
  bool AnyCompletedPlans() const;
79
80
  bool AnyDiscardedPlans() const;
81
82
  bool IsPlanDone(ThreadPlan *plan) const;
83
84
  bool WasPlanDiscarded(ThreadPlan *plan) const;
85
86
  ThreadPlan *GetPreviousPlan(ThreadPlan *current_plan) const;
87
88
  ThreadPlan *GetInnermostExpression() const;
89
90
  void WillResume();
91
92
  /// Clear the Thread* cache that each ThreadPlan contains.
93
  ///
94
  /// This is useful in situations like when a new Thread list is being
95
  /// generated.
96
  void ClearThreadCache();
97
98
private:
99
  void PrintOneStack(Stream &s, llvm::StringRef stack_name,
100
                     const PlanStack &stack, lldb::DescriptionLevel desc_level,
101
                     bool include_internal) const;
102
103
  PlanStack m_plans;           ///< The stack of plans this thread is executing.
104
  PlanStack m_completed_plans; ///< Plans that have been completed by this
105
                               /// stop.  They get deleted when the thread
106
                               /// resumes.
107
  PlanStack m_discarded_plans; ///< Plans that have been discarded by this
108
                               /// stop.  They get deleted when the thread
109
                               /// resumes.
110
  size_t m_completed_plan_checkpoint = 0; // Monotonically increasing token for
111
                                          // completed plan checkpoints.
112
  std::unordered_map<size_t, PlanStack> m_completed_plan_store;
113
  mutable std::recursive_mutex m_stack_mutex;
114
};
115
116
class ThreadPlanStackMap {
117
public:
118
3.02k
  ThreadPlanStackMap(Process &process) : m_process(process) {}
119
2.90k
  ~ThreadPlanStackMap() = default;
120
121
  // Prune the map using the current_threads list.
122
  void Update(ThreadList &current_threads, bool delete_missing,
123
              bool check_for_new = true);
124
125
3.34k
  void AddThread(Thread &thread) {
126
3.34k
    lldb::tid_t tid = thread.GetID();
127
3.34k
    m_plans_list.emplace(tid, thread);
128
3.34k
  }
129
130
144
  bool RemoveTID(lldb::tid_t tid) {
131
144
    auto result = m_plans_list.find(tid);
132
144
    if (result == m_plans_list.end())
133
0
      return false;
134
144
    result->second.ThreadDestroyed(nullptr);
135
144
    m_plans_list.erase(result);
136
144
    return true;
137
144
  }
138
139
463k
  ThreadPlanStack *Find(lldb::tid_t tid) {
140
463k
    auto result = m_plans_list.find(tid);
141
463k
    if (result == m_plans_list.end())
142
3.37k
      return nullptr;
143
460k
    else
144
460k
      return &result->second;
145
463k
  }
146
147
  /// Clear the Thread* cache that each ThreadPlan contains.
148
  ///
149
  /// This is useful in situations like when a new Thread list is being
150
  /// generated.
151
20.3k
  void ClearThreadCache() {
152
20.3k
    for (auto &plan_list : m_plans_list)
153
18.3k
      plan_list.second.ClearThreadCache();
154
20.3k
  }
155
156
3.01k
  void Clear() {
157
3.01k
    for (auto &plan : m_plans_list)
158
3.20k
      plan.second.ThreadDestroyed(nullptr);
159
3.01k
    m_plans_list.clear();
160
3.01k
  }
161
162
  // Implements Process::DumpThreadPlans
163
  void DumpPlans(Stream &strm, lldb::DescriptionLevel desc_level, bool internal,
164
                 bool ignore_boring, bool skip_unreported);
165
166
  // Implements Process::DumpThreadPlansForTID
167
  bool DumpPlansForTID(Stream &strm, lldb::tid_t tid,
168
                       lldb::DescriptionLevel desc_level, bool internal,
169
                       bool ignore_boring, bool skip_unreported);
170
                       
171
  bool PrunePlansForTID(lldb::tid_t tid);
172
173
private:
174
  Process &m_process;
175
  using PlansList = std::unordered_map<lldb::tid_t, ThreadPlanStack>;
176
  PlansList m_plans_list;
177
};
178
179
} // namespace lldb_private
180
181
#endif // LLDB_TARGET_THREADPLANSTACK_H