gdb/
[external/binutils.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 #include "gdbcmd.h"
42
43 #include <string.h>
44
45 unsigned int notif_debug = 0;
46
47 /* Supported clients of notifications.  */
48
49 static struct notif_client *notifs[] =
50 {
51   &notif_client_stop,
52 };
53
54 static void do_notif_event_xfree (void *arg);
55
56 /* Parse the BUF for the expected notification NC, and send packet to
57    acknowledge.  */
58
59 void
60 remote_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
78 struct notif_event *
79 remote_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
94 DECLARE_QUEUE_P (notif_client_p);
95 DEFINE_QUEUE_P (notif_client_p);
96
97 static QUEUE(notif_client_p) *notif_queue;
98
99 /* Process notifications one by one.  EXCEPT is not expected in
100    the queue.  */
101
102 void
103 remote_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
117 static void
118 remote_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
129 static struct async_event_handler *remote_async_get_pending_events_token;
130
131 /* Register async_event_handler for notification.  */
132
133 void
134 remote_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
143 void
144 remote_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
152 void
153 handle_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
242 static void
243 do_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
253 static void
254 notif_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 */
265 extern initialize_file_ftype _initialize_notif;
266
267 void
268 _initialize_notif (void)
269 {
270   notif_queue = QUEUE_alloc (notif_client_p, notif_xfree);
271
272   add_setshow_boolean_cmd ("notification", no_class, &notif_debug,
273                            _("\
274 Set debugging of async remote notification."), _("\
275 Show debugging of async remote notification."), _("\
276 When non-zero, debugging output about async remote notifications"
277 " is enabled."),
278                            NULL,
279                            NULL,
280                            &setdebuglist, &showdebuglist);
281 }