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