LLDB  mainline
GDBRemoteClientBase.h
Go to the documentation of this file.
1 //===-- GDBRemoteClientBase.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_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECLIENTBASE_H
10 #define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECLIENTBASE_H
11 
12 #include "GDBRemoteCommunication.h"
13 
14 #include <condition_variable>
15 
16 namespace lldb_private {
17 namespace process_gdb_remote {
18 
20 public:
22  virtual ~ContinueDelegate();
23  virtual void HandleAsyncStdout(llvm::StringRef out) = 0;
24  virtual void HandleAsyncMisc(llvm::StringRef data) = 0;
25  virtual void HandleStopReply() = 0;
26 
27  /// Process asynchronously-received structured data.
28  ///
29  /// \param[in] data
30  /// The complete data packet, expected to start with JSON-async.
31  virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data) = 0;
32  };
33 
34  GDBRemoteClientBase(const char *comm_name, const char *listener_name);
35 
36  bool SendAsyncSignal(int signo);
37 
38  bool Interrupt();
39 
41  ContinueDelegate &delegate, const UnixSignals &signals,
42  llvm::StringRef payload, StringExtractorGDBRemote &response);
43 
44  PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload,
45  StringExtractorGDBRemote &response,
46  bool send_async);
47 
49  llvm::StringRef payload, StringExtractorGDBRemote &response,
50  bool send_async,
51  llvm::function_ref<void(llvm::StringRef)> output_callback);
52 
53  bool SendvContPacket(llvm::StringRef payload,
54  StringExtractorGDBRemote &response);
55 
56  class Lock {
57  public:
58  Lock(GDBRemoteClientBase &comm, bool interrupt);
59  ~Lock();
60 
61  explicit operator bool() { return m_acquired; }
62 
63  // Whether we had to interrupt the continue thread to acquire the
64  // connection.
65  bool DidInterrupt() const { return m_did_interrupt; }
66 
67  private:
68  std::unique_lock<std::recursive_mutex> m_async_lock;
70  bool m_acquired;
72 
73  void SyncWithContinueThread(bool interrupt);
74  };
75 
76 protected:
78  SendPacketAndWaitForResponseNoLock(llvm::StringRef payload,
79  StringExtractorGDBRemote &response);
80 
81  virtual void OnRunPacketSent(bool first);
82 
83 private:
84  /// Variables handling synchronization between the Continue thread and any
85  /// other threads wishing to send packets over the connection. Either the
86  /// continue thread has control over the connection (m_is_running == true) or
87  /// the connection is free for an arbitrary number of other senders to take
88  /// which indicate their interest by incrementing m_async_count.
89  ///
90  /// Semantics of individual states:
91  ///
92  /// - m_continue_packet == false, m_async_count == 0:
93  /// connection is free
94  /// - m_continue_packet == true, m_async_count == 0:
95  /// only continue thread is present
96  /// - m_continue_packet == true, m_async_count > 0:
97  /// continue thread has control, async threads should interrupt it and wait
98  /// for it to set m_continue_packet to false
99  /// - m_continue_packet == false, m_async_count > 0:
100  /// async threads have control, continue thread needs to wait for them to
101  /// finish (m_async_count goes down to 0).
102  /// @{
103  std::mutex m_mutex;
104  std::condition_variable m_cv;
105 
106  /// Packet with which to resume after an async interrupt. Can be changed by
107  /// an async thread e.g. to inject a signal.
108  std::string m_continue_packet;
109 
110  /// When was the interrupt packet sent. Used to make sure we time out if the
111  /// stub does not respond to interrupt requests.
112  std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time;
113 
114  /// Number of threads interested in sending.
116 
117  /// Whether the continue thread has control.
119 
120  /// Whether we should resume after a stop.
122  /// @}
123 
124  /// This handles the synchronization between individual async threads. For
125  /// now they just use a simple mutex.
126  std::recursive_mutex m_async_mutex;
127 
128  bool ShouldStop(const UnixSignals &signals,
129  StringExtractorGDBRemote &response);
130 
131  class ContinueLock {
132  public:
133  enum class LockResult { Success, Cancelled, Failed };
134 
135  explicit ContinueLock(GDBRemoteClientBase &comm);
136  ~ContinueLock();
137  explicit operator bool() { return m_acquired; }
138 
139  LockResult lock();
140 
141  void unlock();
142 
143  private:
146  };
147 };
148 
149 } // namespace process_gdb_remote
150 } // namespace lldb_private
151 
152 #endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECLIENTBASE_H
PacketResult SendPacketAndWaitForResponseNoLock(llvm::StringRef payload, StringExtractorGDBRemote &response)
A class that represents a running process on the host machine.
bool m_should_stop
Whether we should resume after a stop.
bool SendvContPacket(llvm::StringRef payload, StringExtractorGDBRemote &response)
std::recursive_mutex m_async_mutex
This handles the synchronization between individual async threads.
PacketResult SendPacketAndReceiveResponseWithOutputSupport(llvm::StringRef payload, StringExtractorGDBRemote &response, bool send_async, llvm::function_ref< void(llvm::StringRef)> output_callback)
GDBRemoteClientBase(const char *comm_name, const char *listener_name)
std::chrono::time_point< std::chrono::steady_clock > m_interrupt_time
When was the interrupt packet sent.
bool ShouldStop(const UnixSignals &signals, StringExtractorGDBRemote &response)
std::mutex m_mutex
Variables handling synchronization between the Continue thread and any other threads wishing to send ...
virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data)=0
Process asynchronously-received structured data.
std::string m_continue_packet
Packet with which to resume after an async interrupt.
StateType
Process and Thread States.
lldb::StateType SendContinuePacketAndWaitForResponse(ContinueDelegate &delegate, const UnixSignals &signals, llvm::StringRef payload, StringExtractorGDBRemote &response)
uint32_t m_async_count
Number of threads interested in sending.
bool m_is_running
Whether the continue thread has control.
PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response, bool send_async)
std::unique_lock< std::recursive_mutex > m_async_lock