1 /* Remote notification in GDB protocol
3 Copyright (C) 1988-2012 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
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).
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. */
36 #include "remote-notif.h"
38 #include "event-loop.h"
44 unsigned int notif_debug = 0;
46 /* Supported clients of notifications. */
48 static struct notif_client *notifs[] =
53 static void do_notif_event_xfree (void *arg);
55 /* Parse the BUF for the expected notification NC, and send packet to
59 remote_notif_ack (struct notif_client *nc, char *buf)
61 struct notif_event *event = nc->alloc_event ();
62 struct cleanup *old_chain
63 = make_cleanup (do_notif_event_xfree, event);
66 fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
69 nc->parse (nc, buf, event);
70 nc->ack (nc, buf, event);
72 discard_cleanups (old_chain);
75 /* Parse the BUF for the expected notification NC. */
78 remote_notif_parse (struct notif_client *nc, char *buf)
80 struct notif_event *event = nc->alloc_event ();
81 struct cleanup *old_chain
82 = make_cleanup (do_notif_event_xfree, event);
85 fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
87 nc->parse (nc, buf, event);
89 discard_cleanups (old_chain);
93 DECLARE_QUEUE_P (notif_client_p);
94 DEFINE_QUEUE_P (notif_client_p);
96 static QUEUE(notif_client_p) *notif_queue;
98 /* Process notifications one by one. EXCEPT is not expected in
102 remote_notif_process (struct notif_client *except)
104 while (!QUEUE_is_empty (notif_client_p, notif_queue))
106 struct notif_client *nc = QUEUE_deque (notif_client_p,
109 gdb_assert (nc != except);
111 if (nc->can_get_pending_events (nc))
112 remote_notif_get_pending_events (nc);
117 remote_async_get_pending_events_handler (gdb_client_data data)
119 gdb_assert (non_stop);
120 remote_notif_process (NULL);
123 /* Asynchronous signal handle registered as event loop source for when
124 the remote sent us a notification. The registered callback
125 will do a ACK sequence to pull the rest of the events out of
126 the remote side into our event queue. */
128 static struct async_event_handler *remote_async_get_pending_events_token;
130 /* Register async_event_handler for notification. */
133 remote_notif_register_async_event_handler (void)
135 remote_async_get_pending_events_token
136 = create_async_event_handler (remote_async_get_pending_events_handler,
140 /* Unregister async_event_handler for notification. */
143 remote_notif_unregister_async_event_handler (void)
145 if (remote_async_get_pending_events_token)
146 delete_async_event_handler (&remote_async_get_pending_events_token);
149 /* Remote notification handler. */
152 handle_notification (char *buf)
154 struct notif_client *nc = NULL;
157 for (i = 0; i < ARRAY_SIZE (notifs); i++)
160 if (strncmp (buf, nc->name, strlen (nc->name)) == 0
161 && buf[strlen (nc->name)] == ':')
165 /* We ignore notifications we don't recognize, for compatibility
170 if (nc->pending_event)
172 /* We've already parsed the in-flight reply, but the stub for some
173 reason thought we didn't, possibly due to timeout on its side.
176 fprintf_unfiltered (gdb_stdlog,
177 "notif: ignoring resent notification\n");
181 struct notif_event *event
182 = remote_notif_parse (nc, buf + strlen (nc->name) + 1);
184 /* Be careful to only set it after parsing, since an error
185 may be thrown then. */
186 nc->pending_event = event;
188 /* Notify the event loop there's a stop reply to acknowledge
189 and that there may be more events to fetch. */
190 QUEUE_enque (notif_client_p, notif_queue, nc);
193 /* In non-stop, We mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
194 in order to go on what we were doing and postpone
195 querying notification events to some point safe to do so.
196 See details in the function comment of
197 remote.c:remote_notif_get_pending_events.
199 In all-stop, GDB may be blocked to wait for the reply, we
200 shouldn't return to event loop until the expected reply
201 arrives. For example:
204 GDB expects getting stop reply 'T05 thread:2'.
206 <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
208 After step #1.2, we return to the event loop, which
209 notices there is a new event on the
210 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and calls the
211 handler, which will send 'vNotif' packet.
213 It is not safe to start a new sequence, because target
214 is still running and GDB is expecting the stop reply
217 To solve this, whenever we parse a notification
218 successfully, we don't mark the
219 REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and let GDB blocked
220 there as before to get the sequence done.
223 GDB expects getting stop reply 'T05 thread:2'
225 <Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
226 2.3) <-- T05 thread:2
228 These pending notifications can be processed later. */
229 mark_async_event_handler (remote_async_get_pending_events_token);
233 fprintf_unfiltered (gdb_stdlog,
234 "notif: Notification '%s' captured\n",
239 /* Cleanup wrapper. */
242 do_notif_event_xfree (void *arg)
244 struct notif_event *event = arg;
246 if (event && event->dtr)
253 notif_xfree (struct notif_client *notif)
255 if (notif->pending_event != NULL
256 && notif->pending_event->dtr != NULL)
257 notif->pending_event->dtr (notif->pending_event);
259 xfree (notif->pending_event);
263 /* -Wmissing-prototypes */
264 extern initialize_file_ftype _initialize_notif;
267 _initialize_notif (void)
269 notif_queue = QUEUE_alloc (notif_client_p, notif_xfree);