blob: a3bcc865ac66152c763d26b6ed646d76eaf3b909 [file] [log] [blame]
Pavel Labath8c1b6bd2016-08-09 12:04:46 +00001//===-- GDBRemoteClientBase.h -----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef liblldb_GDBRemoteClientBase_h_
11#define liblldb_GDBRemoteClientBase_h_
12
13#include "GDBRemoteCommunication.h"
14
15#include <condition_variable>
16
17namespace lldb_private
18{
19namespace process_gdb_remote
20{
21
22class GDBRemoteClientBase : public GDBRemoteCommunication
23{
24public:
25 struct ContinueDelegate
26 {
27 virtual ~ContinueDelegate();
28 virtual void
29 HandleAsyncStdout(llvm::StringRef out) = 0;
30 virtual void
31 HandleAsyncMisc(llvm::StringRef data) = 0;
32 virtual void
33 HandleStopReply() = 0;
Todd Fiala75930012016-08-19 04:21:48 +000034
35 //
36 /// Processes async structured data.
37 ///
38 /// @return
39 /// true if the data was handled; otherwise, false.
40 //
41 virtual bool
42 HandleAsyncStructuredData(const StructuredData::ObjectSP
43 &object_sp) = 0;
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000044 };
45
46 GDBRemoteClientBase(const char *comm_name, const char *listener_name);
47
48 bool
49 SendAsyncSignal(int signo);
50
51 bool
52 Interrupt();
53
54 lldb::StateType
55 SendContinuePacketAndWaitForResponse(ContinueDelegate &delegate, const UnixSignals &signals,
56 llvm::StringRef payload, StringExtractorGDBRemote &response);
57
58 PacketResult
59 SendPacketAndWaitForResponse(const char *payload, size_t len, StringExtractorGDBRemote &response, bool send_async)
60 {
61 return SendPacketAndWaitForResponse(llvm::StringRef(payload, len), response, send_async);
62 }
63
64 PacketResult
65 SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response, bool send_async);
66
67 bool
68 SendvContPacket(llvm::StringRef payload, StringExtractorGDBRemote &response);
69
70 class Lock
71 {
72 public:
73 Lock(GDBRemoteClientBase &comm, bool interrupt);
74 ~Lock();
75
Pavel Labath0faf3732016-08-25 08:34:57 +000076 explicit operator bool() const { return m_acquired; }
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000077
78 // Whether we had to interrupt the continue thread to acquire the connection.
79 bool
80 DidInterrupt() const
81 {
82 return m_did_interrupt;
83 }
84
85 private:
Pavel Labath0faf3732016-08-25 08:34:57 +000086 std::unique_lock<std::mutex> m_async_lock;
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000087 GDBRemoteClientBase &m_comm;
88 bool m_acquired;
89 bool m_did_interrupt;
90
91 void
92 SyncWithContinueThread(bool interrupt);
93 };
94
95protected:
96 PacketResult
Pavel Labath0faf3732016-08-25 08:34:57 +000097 SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response, const Lock &lock);
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000098
99 virtual void
100 OnRunPacketSent(bool first);
101
102private:
103 // Variables handling synchronization between the Continue thread and any other threads
104 // wishing to send packets over the connection. Either the continue thread has control over
105 // the connection (m_is_running == true) or the connection is free for an arbitrary number of
106 // other senders to take which indicate their interest by incrementing m_async_count.
107 // Semantics of individual states:
108 // - m_continue_packet == false, m_async_count == 0: connection is free
109 // - m_continue_packet == true, m_async_count == 0: only continue thread is present
110 // - m_continue_packet == true, m_async_count > 0: continue thread has control, async threads
111 // should interrupt it and wait for it to set m_continue_packet to false
112 // - m_continue_packet == false, m_async_count > 0: async threads have control, continue
113 // thread needs to wait for them to finish (m_async_count goes down to 0).
114 std::mutex m_mutex;
115 std::condition_variable m_cv;
116 // Packet with which to resume after an async interrupt. Can be changed by an async thread
117 // e.g. to inject a signal.
118 std::string m_continue_packet;
119 // When was the interrupt packet sent. Used to make sure we time out if the stub does not
120 // respond to interrupt requests.
121 std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time;
122 uint32_t m_async_count;
123 bool m_is_running;
124 bool m_should_stop; // Whether we should resume after a stop.
125 // end of continue thread synchronization block
126
127 // This handles the synchronization between individual async threads. For now they just use a
128 // simple mutex.
Pavel Labath0faf3732016-08-25 08:34:57 +0000129 std::mutex m_async_mutex;
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000130
131 bool
132 ShouldStop(const UnixSignals &signals, StringExtractorGDBRemote &response);
133
134 class ContinueLock
135 {
136 public:
137 enum class LockResult
138 {
139 Success,
140 Cancelled,
141 Failed
142 };
143
144 explicit ContinueLock(GDBRemoteClientBase &comm);
145 ~ContinueLock();
146 explicit operator bool() { return m_acquired; }
147
148 LockResult
149 lock();
150
151 void
152 unlock();
153
154 private:
155 GDBRemoteClientBase &m_comm;
156 bool m_acquired;
157 };
158};
159
160} // namespace process_gdb_remote
161} // namespace lldb_private
162
163#endif // liblldb_GDBRemoteCommunicationClient_h_