gdb/
[deliverable/binutils-gdb.git] / gdb / remote-notif.c
1 /* Remote notification in GDB protocol
2
3 Copyright (C) 1988-2012 Free Software Foundation, Inc.
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"
41
42 #include <string.h>
43
44 unsigned int notif_debug = 0;
45
46 /* Supported clients of notifications. */
47
48 static struct notif_client *notifs[] =
49 {
50 &notif_client_stop,
51 };
52
53 static void do_notif_event_xfree (void *arg);
54
55 /* Parse the BUF for the expected notification NC, and send packet to
56 acknowledge. */
57
58 void
59 remote_notif_ack (struct notif_client *nc, char *buf)
60 {
61 struct notif_event *event = nc->alloc_event ();
62 struct cleanup *old_chain
63 = make_cleanup (do_notif_event_xfree, event);
64
65 if (notif_debug)
66 fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
67 nc->ack_command);
68
69 nc->parse (nc, buf, event);
70 nc->ack (nc, buf, event);
71
72 discard_cleanups (old_chain);
73 }
74
75 /* Parse the BUF for the expected notification NC. */
76
77 struct notif_event *
78 remote_notif_parse (struct notif_client *nc, char *buf)
79 {
80 struct notif_event *event = nc->alloc_event ();
81 struct cleanup *old_chain
82 = make_cleanup (do_notif_event_xfree, event);
83
84 if (notif_debug)
85 fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
86
87 nc->parse (nc, buf, event);
88
89 discard_cleanups (old_chain);
90 return event;
91 }
92
93 DECLARE_QUEUE_P (notif_client_p);
94 DEFINE_QUEUE_P (notif_client_p);
95
96 static QUEUE(notif_client_p) *notif_queue;
97
98 /* Process notifications one by one. EXCEPT is not expected in
99 the queue. */
100
101 void
102 remote_notif_process (struct notif_client *except)
103 {
104 while (!QUEUE_is_empty (notif_client_p, notif_queue))
105 {
106 struct notif_client *nc = QUEUE_deque (notif_client_p,
107 notif_queue);
108
109 gdb_assert (nc != except);
110
111 if (nc->can_get_pending_events (nc))
112 remote_notif_get_pending_events (nc);
113 }
114 }
115
116 static void
117 remote_async_get_pending_events_handler (gdb_client_data data)
118 {
119 gdb_assert (non_stop);
120 remote_notif_process (NULL);
121 }
122
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. */
127
128 static struct async_event_handler *remote_async_get_pending_events_token;
129
130 /* Register async_event_handler for notification. */
131
132 void
133 remote_notif_register_async_event_handler (void)
134 {
135 remote_async_get_pending_events_token
136 = create_async_event_handler (remote_async_get_pending_events_handler,
137 NULL);
138 }
139
140 /* Unregister async_event_handler for notification. */
141
142 void
143 remote_notif_unregister_async_event_handler (void)
144 {
145 if (remote_async_get_pending_events_token)
146 delete_async_event_handler (&remote_async_get_pending_events_token);
147 }
148
149 /* Remote notification handler. */
150
151 void
152 handle_notification (char *buf)
153 {
154 struct notif_client *nc = NULL;
155 int i;
156
157 for (i = 0; i < ARRAY_SIZE (notifs); i++)
158 {
159 nc = notifs[i];
160 if (strncmp (buf, nc->name, strlen (nc->name)) == 0
161 && buf[strlen (nc->name)] == ':')
162 break;
163 }
164
165 /* We ignore notifications we don't recognize, for compatibility
166 with newer stubs. */
167 if (nc == NULL)
168 return;
169
170 if (nc->pending_event)
171 {
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.
174 Just ignore it. */
175 if (notif_debug)
176 fprintf_unfiltered (gdb_stdlog,
177 "notif: ignoring resent notification\n");
178 }
179 else
180 {
181 struct notif_event *event
182 = remote_notif_parse (nc, buf + strlen (nc->name) + 1);
183
184 /* Be careful to only set it after parsing, since an error
185 may be thrown then. */
186 nc->pending_event = event;
187
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);
191 if (non_stop)
192 {
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.
198
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:
202
203 1.1) --> vCont;c
204 GDB expects getting stop reply 'T05 thread:2'.
205 1.2) <-- %Notif
206 <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
207
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.
212 1.3) --> vNotif
213 It is not safe to start a new sequence, because target
214 is still running and GDB is expecting the stop reply
215 from stub.
216
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.
221
222 2.1) --> vCont;c
223 GDB expects getting stop reply 'T05 thread:2'
224 2.2) <-- %Notif
225 <Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
226 2.3) <-- T05 thread:2
227
228 These pending notifications can be processed later. */
229 mark_async_event_handler (remote_async_get_pending_events_token);
230 }
231
232 if (notif_debug)
233 fprintf_unfiltered (gdb_stdlog,
234 "notif: Notification '%s' captured\n",
235 nc->name);
236 }
237 }
238
239 /* Cleanup wrapper. */
240
241 static void
242 do_notif_event_xfree (void *arg)
243 {
244 struct notif_event *event = arg;
245
246 if (event && event->dtr)
247 event->dtr (event);
248
249 xfree (event);
250 }
251
252 static void
253 notif_xfree (struct notif_client *notif)
254 {
255 if (notif->pending_event != NULL
256 && notif->pending_event->dtr != NULL)
257 notif->pending_event->dtr (notif->pending_event);
258
259 xfree (notif->pending_event);
260 xfree (notif);
261 }
262
263 /* -Wmissing-prototypes */
264 extern initialize_file_ftype _initialize_notif;
265
266 void
267 _initialize_notif (void)
268 {
269 notif_queue = QUEUE_alloc (notif_client_p, notif_xfree);
270 }
This page took 0.036248 seconds and 5 git commands to generate.