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 ¬if_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, ¬if_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