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
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 }