xref: /dragonfly/contrib/gdb-7/gdb/remote-notif.c (revision 67640b13)
1 /* Remote notification in GDB protocol
2 
3    Copyright (C) 1988-2013 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 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 }
282