Fix FIXME: xstrdup should not be here
[deliverable/binutils-gdb.git] / gdb / remote-notif.c
CommitLineData
722247f1
YQ
1/* Remote notification in GDB protocol
2
28e7fd62 3 Copyright (C) 1988-2013 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"
37#include "observer.h"
38#include "event-loop.h"
39#include "target.h"
40#include "inferior.h"
c9b6281a 41#include "gdbcmd.h"
722247f1
YQ
42
43#include <string.h>
44
99f0a309 45int notif_debug = 0;
722247f1
YQ
46
47/* Supported clients of notifications. */
48
49static struct notif_client *notifs[] =
50{
51 &notif_client_stop,
52};
53
54static void do_notif_event_xfree (void *arg);
55
56/* Parse the BUF for the expected notification NC, and send packet to
57 acknowledge. */
58
59void
60remote_notif_ack (struct notif_client *nc, char *buf)
61{
62 struct notif_event *event = nc->alloc_event ();
63 struct cleanup *old_chain
64 = make_cleanup (do_notif_event_xfree, event);
65
66 if (notif_debug)
67 fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
68 nc->ack_command);
69
70 nc->parse (nc, buf, event);
71 nc->ack (nc, buf, event);
72
73 discard_cleanups (old_chain);
74}
75
76/* Parse the BUF for the expected notification NC. */
77
78struct notif_event *
79remote_notif_parse (struct notif_client *nc, char *buf)
80{
81 struct notif_event *event = nc->alloc_event ();
82 struct cleanup *old_chain
83 = make_cleanup (do_notif_event_xfree, event);
84
85 if (notif_debug)
86 fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
87
88 nc->parse (nc, buf, event);
89
90 discard_cleanups (old_chain);
91 return event;
92}
93
94DECLARE_QUEUE_P (notif_client_p);
95DEFINE_QUEUE_P (notif_client_p);
96
97static QUEUE(notif_client_p) *notif_queue;
98
99/* Process notifications one by one. EXCEPT is not expected in
100 the queue. */
101
102void
103remote_notif_process (struct notif_client *except)
104{
105 while (!QUEUE_is_empty (notif_client_p, notif_queue))
106 {
107 struct notif_client *nc = QUEUE_deque (notif_client_p,
108 notif_queue);
109
110 gdb_assert (nc != except);
111
112 if (nc->can_get_pending_events (nc))
113 remote_notif_get_pending_events (nc);
114 }
115}
116
117static void
118remote_async_get_pending_events_handler (gdb_client_data data)
119{
120 gdb_assert (non_stop);
121 remote_notif_process (NULL);
122}
123
124/* Asynchronous signal handle registered as event loop source for when
125 the remote sent us a notification. The registered callback
126 will do a ACK sequence to pull the rest of the events out of
127 the remote side into our event queue. */
128
129static struct async_event_handler *remote_async_get_pending_events_token;
130
131/* Register async_event_handler for notification. */
132
133void
134remote_notif_register_async_event_handler (void)
135{
136 remote_async_get_pending_events_token
137 = create_async_event_handler (remote_async_get_pending_events_handler,
138 NULL);
139}
140
141/* Unregister async_event_handler for notification. */
142
143void
144remote_notif_unregister_async_event_handler (void)
145{
146 if (remote_async_get_pending_events_token)
147 delete_async_event_handler (&remote_async_get_pending_events_token);
148}
149
150/* Remote notification handler. */
151
152void
153handle_notification (char *buf)
154{
155 struct notif_client *nc = NULL;
156 int i;
157
158 for (i = 0; i < ARRAY_SIZE (notifs); i++)
159 {
160 nc = notifs[i];
161 if (strncmp (buf, nc->name, strlen (nc->name)) == 0
162 && buf[strlen (nc->name)] == ':')
163 break;
164 }
165
166 /* We ignore notifications we don't recognize, for compatibility
167 with newer stubs. */
168 if (nc == NULL)
169 return;
170
171 if (nc->pending_event)
172 {
173 /* We've already parsed the in-flight reply, but the stub for some
174 reason thought we didn't, possibly due to timeout on its side.
175 Just ignore it. */
176 if (notif_debug)
177 fprintf_unfiltered (gdb_stdlog,
178 "notif: ignoring resent notification\n");
179 }
180 else
181 {
182 struct notif_event *event
183 = remote_notif_parse (nc, buf + strlen (nc->name) + 1);
184
185 /* Be careful to only set it after parsing, since an error
186 may be thrown then. */
187 nc->pending_event = event;
188
189 /* Notify the event loop there's a stop reply to acknowledge
190 and that there may be more events to fetch. */
191 QUEUE_enque (notif_client_p, notif_queue, nc);
192 if (non_stop)
193 {
194 /* In non-stop, We mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
195 in order to go on what we were doing and postpone
196 querying notification events to some point safe to do so.
197 See details in the function comment of
198 remote.c:remote_notif_get_pending_events.
199
200 In all-stop, GDB may be blocked to wait for the reply, we
201 shouldn't return to event loop until the expected reply
202 arrives. For example:
203
204 1.1) --> vCont;c
205 GDB expects getting stop reply 'T05 thread:2'.
206 1.2) <-- %Notif
207 <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
208
209 After step #1.2, we return to the event loop, which
210 notices there is a new event on the
211 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and calls the
212 handler, which will send 'vNotif' packet.
213 1.3) --> vNotif
214 It is not safe to start a new sequence, because target
215 is still running and GDB is expecting the stop reply
216 from stub.
217
218 To solve this, whenever we parse a notification
219 successfully, we don't mark the
220 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and let GDB blocked
221 there as before to get the sequence done.
222
223 2.1) --> vCont;c
224 GDB expects getting stop reply 'T05 thread:2'
225 2.2) <-- %Notif
226 <Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
227 2.3) <-- T05 thread:2
228
229 These pending notifications can be processed later. */
230 mark_async_event_handler (remote_async_get_pending_events_token);
231 }
232
233 if (notif_debug)
234 fprintf_unfiltered (gdb_stdlog,
235 "notif: Notification '%s' captured\n",
236 nc->name);
237 }
238}
239
240/* Cleanup wrapper. */
241
242static void
243do_notif_event_xfree (void *arg)
244{
245 struct notif_event *event = arg;
246
247 if (event && event->dtr)
248 event->dtr (event);
249
250 xfree (event);
251}
252
253static void
254notif_xfree (struct notif_client *notif)
255{
256 if (notif->pending_event != NULL
257 && notif->pending_event->dtr != NULL)
258 notif->pending_event->dtr (notif->pending_event);
259
260 xfree (notif->pending_event);
261 xfree (notif);
262}
263
264/* -Wmissing-prototypes */
265extern initialize_file_ftype _initialize_notif;
266
267void
268_initialize_notif (void)
269{
270 notif_queue = QUEUE_alloc (notif_client_p, notif_xfree);
c9b6281a
YQ
271
272 add_setshow_boolean_cmd ("notification", no_class, &notif_debug,
273 _("\
274Set debugging of async remote notification."), _("\
275Show debugging of async remote notification."), _("\
276When non-zero, debugging output about async remote notifications"
277" is enabled."),
278 NULL,
279 NULL,
280 &setdebuglist, &showdebuglist);
722247f1 281}
This page took 0.121387 seconds and 4 git commands to generate.