Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / remote-notif.c
CommitLineData
722247f1
YQ
1/* Remote notification in GDB protocol
2
42a4f53d 3 Copyright (C) 1988-2019 Free Software Foundation, Inc.
722247f1
YQ
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20/* Remote async notification is sent from remote target over RSP.
21 Each type of notification is represented by an object of
22 'struct notif', which has a field 'pending_reply'. It is not
23 NULL when GDB receives a notification from GDBserver, but hasn't
24 acknowledge yet. Before GDB acknowledges the notification,
25 GDBserver shouldn't send notification again (see the header comments
26 in gdbserver/notif.c).
27
28 Notifications are processed in an almost-unified approach for both
29 all-stop mode and non-stop mode, except the timing to process them.
30 In non-stop mode, notifications are processed in
31 remote_async_get_pending_events_handler, while in all-stop mode,
32 they are processed in remote_resume. */
33
34#include "defs.h"
35#include "remote.h"
36#include "remote-notif.h"
76727919 37#include "observable.h"
722247f1
YQ
38#include "event-loop.h"
39#include "target.h"
40#include "inferior.h"
45741a9c 41#include "infrun.h"
c9b6281a 42#include "gdbcmd.h"
722247f1 43
99f0a309 44int notif_debug = 0;
722247f1
YQ
45
46/* Supported clients of notifications. */
47
48static struct notif_client *notifs[] =
49{
50 &notif_client_stop,
51};
52
f48ff2a7
YQ
53gdb_static_assert (ARRAY_SIZE (notifs) == REMOTE_NOTIF_LAST);
54
722247f1
YQ
55/* Parse the BUF for the expected notification NC, and send packet to
56 acknowledge. */
57
58void
6b8edb51 59remote_notif_ack (remote_target *remote,
bb277751 60 struct notif_client *nc, const char *buf)
722247f1 61{
32603266 62 notif_event_up event = nc->alloc_event ();
722247f1
YQ
63
64 if (notif_debug)
65 fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
66 nc->ack_command);
67
32603266
TT
68 nc->parse (remote, nc, buf, event.get ());
69 nc->ack (remote, nc, buf, event.release ());
722247f1
YQ
70}
71
72/* Parse the BUF for the expected notification NC. */
73
74struct notif_event *
6b8edb51 75remote_notif_parse (remote_target *remote,
bb277751 76 struct notif_client *nc, const char *buf)
722247f1 77{
32603266 78 notif_event_up event = nc->alloc_event ();
722247f1
YQ
79
80 if (notif_debug)
81 fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
82
32603266 83 nc->parse (remote, nc, buf, event.get ());
722247f1 84
32603266 85 return event.release ();
722247f1
YQ
86}
87
722247f1
YQ
88DEFINE_QUEUE_P (notif_client_p);
89
5965e028
YQ
90/* Process notifications in STATE's notification queue one by one.
91 EXCEPT is not expected in the queue. */
722247f1
YQ
92
93void
5965e028
YQ
94remote_notif_process (struct remote_notif_state *state,
95 struct notif_client *except)
722247f1 96{
5965e028 97 while (!QUEUE_is_empty (notif_client_p, state->notif_queue))
722247f1
YQ
98 {
99 struct notif_client *nc = QUEUE_deque (notif_client_p,
5965e028 100 state->notif_queue);
722247f1
YQ
101
102 gdb_assert (nc != except);
103
6b8edb51
PA
104 if (nc->can_get_pending_events (state->remote, nc))
105 remote_notif_get_pending_events (state->remote, nc);
722247f1
YQ
106 }
107}
108
109static void
110remote_async_get_pending_events_handler (gdb_client_data data)
111{
6efcd9a8 112 gdb_assert (target_is_non_stop_p ());
19ba03f4 113 remote_notif_process ((struct remote_notif_state *) data, NULL);
722247f1
YQ
114}
115
5965e028
YQ
116/* Remote notification handler. Parse BUF, queue notification and
117 update STATE. */
722247f1
YQ
118
119void
bb277751 120handle_notification (struct remote_notif_state *state, const char *buf)
722247f1 121{
62972e0b
YQ
122 struct notif_client *nc;
123 size_t i;
722247f1
YQ
124
125 for (i = 0; i < ARRAY_SIZE (notifs); i++)
126 {
62972e0b
YQ
127 const char *name = notifs[i]->name;
128
61012eef 129 if (startswith (buf, name)
62972e0b 130 && buf[strlen (name)] == ':')
722247f1
YQ
131 break;
132 }
133
134 /* We ignore notifications we don't recognize, for compatibility
135 with newer stubs. */
62972e0b 136 if (i == ARRAY_SIZE (notifs))
722247f1
YQ
137 return;
138
62972e0b
YQ
139 nc = notifs[i];
140
f48ff2a7 141 if (state->pending_event[nc->id] != NULL)
722247f1
YQ
142 {
143 /* We've already parsed the in-flight reply, but the stub for some
144 reason thought we didn't, possibly due to timeout on its side.
145 Just ignore it. */
146 if (notif_debug)
147 fprintf_unfiltered (gdb_stdlog,
148 "notif: ignoring resent notification\n");
149 }
150 else
151 {
152 struct notif_event *event
6b8edb51 153 = remote_notif_parse (state->remote, nc, buf + strlen (nc->name) + 1);
722247f1
YQ
154
155 /* Be careful to only set it after parsing, since an error
156 may be thrown then. */
f48ff2a7 157 state->pending_event[nc->id] = event;
722247f1
YQ
158
159 /* Notify the event loop there's a stop reply to acknowledge
160 and that there may be more events to fetch. */
5965e028 161 QUEUE_enque (notif_client_p, state->notif_queue, nc);
6efcd9a8 162 if (target_is_non_stop_p ())
722247f1
YQ
163 {
164 /* In non-stop, We mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
165 in order to go on what we were doing and postpone
166 querying notification events to some point safe to do so.
167 See details in the function comment of
168 remote.c:remote_notif_get_pending_events.
169
170 In all-stop, GDB may be blocked to wait for the reply, we
171 shouldn't return to event loop until the expected reply
172 arrives. For example:
173
174 1.1) --> vCont;c
175 GDB expects getting stop reply 'T05 thread:2'.
176 1.2) <-- %Notif
177 <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
178
179 After step #1.2, we return to the event loop, which
180 notices there is a new event on the
181 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and calls the
182 handler, which will send 'vNotif' packet.
183 1.3) --> vNotif
184 It is not safe to start a new sequence, because target
185 is still running and GDB is expecting the stop reply
186 from stub.
187
188 To solve this, whenever we parse a notification
189 successfully, we don't mark the
190 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and let GDB blocked
191 there as before to get the sequence done.
192
193 2.1) --> vCont;c
194 GDB expects getting stop reply 'T05 thread:2'
195 2.2) <-- %Notif
196 <Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
197 2.3) <-- T05 thread:2
198
199 These pending notifications can be processed later. */
5965e028 200 mark_async_event_handler (state->get_pending_events_token);
722247f1
YQ
201 }
202
203 if (notif_debug)
204 fprintf_unfiltered (gdb_stdlog,
205 "notif: Notification '%s' captured\n",
206 nc->name);
207 }
208}
209
5965e028
YQ
210/* Return an allocated remote_notif_state. */
211
212struct remote_notif_state *
6b8edb51 213remote_notif_state_allocate (remote_target *remote)
5965e028 214{
8d749320 215 struct remote_notif_state *notif_state = XCNEW (struct remote_notif_state);
5965e028 216
6b8edb51
PA
217 notif_state->remote = remote;
218
5965e028
YQ
219 notif_state->notif_queue = QUEUE_alloc (notif_client_p, NULL);
220
221 /* Register async_event_handler for notification. */
222
223 notif_state->get_pending_events_token
224 = create_async_event_handler (remote_async_get_pending_events_handler,
225 notif_state);
226
227 return notif_state;
228}
229
230/* Free STATE and its fields. */
231
232void
233remote_notif_state_xfree (struct remote_notif_state *state)
722247f1 234{
f48ff2a7
YQ
235 int i;
236
5965e028
YQ
237 QUEUE_free (notif_client_p, state->notif_queue);
238
239 /* Unregister async_event_handler for notification. */
240 if (state->get_pending_events_token != NULL)
241 delete_async_event_handler (&state->get_pending_events_token);
722247f1 242
f48ff2a7 243 for (i = 0; i < REMOTE_NOTIF_LAST; i++)
32603266 244 delete state->pending_event[i];
f48ff2a7 245
5965e028 246 xfree (state);
722247f1
YQ
247}
248
722247f1
YQ
249void
250_initialize_notif (void)
251{
c9b6281a
YQ
252 add_setshow_boolean_cmd ("notification", no_class, &notif_debug,
253 _("\
254Set debugging of async remote notification."), _("\
255Show debugging of async remote notification."), _("\
256When non-zero, debugging output about async remote notifications"
257" is enabled."),
258 NULL,
259 NULL,
260 &setdebuglist, &showdebuglist);
722247f1 261}
This page took 0.635051 seconds and 4 git commands to generate.