summaryrefslogtreecommitdiff
path: root/include/lldb/Target/ThreadList.h
blob: de680f32850433bed7ae3b33f33150089001fc17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//===-- ThreadList.h --------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_ThreadList_h_
#define liblldb_ThreadList_h_

#include <mutex>
#include <vector>

#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadCollection.h"
#include "lldb/Utility/Iterable.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"

namespace lldb_private {

// This is a thread list with lots of functionality for use only by the process
// for which this is the thread list.  A generic container class with iterator
// functionality is ThreadCollection.
class ThreadList : public ThreadCollection {
  friend class Process;

public:
  ThreadList(Process *process);

  ThreadList(const ThreadList &rhs);

  ~ThreadList() override;

  const ThreadList &operator=(const ThreadList &rhs);

  uint32_t GetSize(bool can_update = true);

  // Return the selected thread if there is one.  Otherwise, return the thread
  // selected at index 0.
  lldb::ThreadSP GetSelectedThread();

  // Manage the thread to use for running expressions.  This is usually the
  // Selected thread, but sometimes (e.g. when evaluating breakpoint conditions
  // & stop hooks) it isn't.
  class ExpressionExecutionThreadPusher {
  public:
    ExpressionExecutionThreadPusher(ThreadList &thread_list, lldb::tid_t tid)
        : m_thread_list(&thread_list), m_tid(tid) {
      m_thread_list->PushExpressionExecutionThread(m_tid);
    }

    ExpressionExecutionThreadPusher(lldb::ThreadSP thread_sp);

    ~ExpressionExecutionThreadPusher() {
      if (m_thread_list && m_tid != LLDB_INVALID_THREAD_ID)
        m_thread_list->PopExpressionExecutionThread(m_tid);
    }

  private:
    ThreadList *m_thread_list;
    lldb::tid_t m_tid;
  };

  lldb::ThreadSP GetExpressionExecutionThread();

protected:
  void PushExpressionExecutionThread(lldb::tid_t tid);

  void PopExpressionExecutionThread(lldb::tid_t tid);

public:
  bool SetSelectedThreadByID(lldb::tid_t tid, bool notify = false);

  bool SetSelectedThreadByIndexID(uint32_t index_id, bool notify = false);

  void Clear();

  void Flush();

  void Destroy();

  // Note that "idx" is not the same as the "thread_index". It is a zero based
  // index to accessing the current threads, whereas "thread_index" is a unique
  // index assigned
  lldb::ThreadSP GetThreadAtIndex(uint32_t idx, bool can_update = true);

  lldb::ThreadSP FindThreadByID(lldb::tid_t tid, bool can_update = true);

  lldb::ThreadSP FindThreadByProtocolID(lldb::tid_t tid,
                                        bool can_update = true);

  lldb::ThreadSP RemoveThreadByID(lldb::tid_t tid, bool can_update = true);

  lldb::ThreadSP RemoveThreadByProtocolID(lldb::tid_t tid,
                                          bool can_update = true);

  lldb::ThreadSP FindThreadByIndexID(uint32_t index_id, bool can_update = true);

  lldb::ThreadSP GetThreadSPForThreadPtr(Thread *thread_ptr);

  lldb::ThreadSP GetBackingThread(const lldb::ThreadSP &real_thread);

  bool ShouldStop(Event *event_ptr);

  Vote ShouldReportStop(Event *event_ptr);

  Vote ShouldReportRun(Event *event_ptr);

  void RefreshStateAfterStop();

  //------------------------------------------------------------------
  /// The thread list asks tells all the threads it is about to resume.
  /// If a thread can "resume" without having to resume the target, it
  /// will return false for WillResume, and then the process will not be
  /// restarted.
  ///
  /// @return
  ///    \b true instructs the process to resume normally,
  ///    \b false means start & stopped events will be generated, but
  ///    the process will not actually run.  The thread must then return
  ///    the correct StopInfo when asked.
  ///
  //------------------------------------------------------------------
  bool WillResume();

  void DidResume();

  void DidStop();

  void DiscardThreadPlans();

  uint32_t GetStopID() const;

  void SetStopID(uint32_t stop_id);

  std::recursive_mutex &GetMutex() const override;

  void Update(ThreadList &rhs);

protected:
  void SetShouldReportStop(Vote vote);

  void NotifySelectedThreadChanged(lldb::tid_t tid);

  //------------------------------------------------------------------
  // Classes that inherit from Process can see and modify these
  //------------------------------------------------------------------
  Process *m_process; ///< The process that manages this thread list.
  uint32_t
      m_stop_id; ///< The process stop ID that this thread list is valid for.
  lldb::tid_t
      m_selected_tid; ///< For targets that need the notion of a current thread.
  std::vector<lldb::tid_t> m_expression_tid_stack;

private:
  ThreadList();
};

} // namespace lldb_private

#endif // liblldb_ThreadList_h_