GDB (API)
/home/stan/gdb/src/gdb/remote-notif.c
Go to the documentation of this file.
00001 /* Remote notification in GDB protocol
00002 
00003    Copyright (C) 1988-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 /* Remote async notification is sent from remote target over RSP.
00021    Each type of notification is represented by an object of
00022    'struct notif', which has a field 'pending_reply'.  It is not
00023    NULL when GDB receives a notification from GDBserver, but hasn't
00024    acknowledge yet.  Before GDB acknowledges the notification,
00025    GDBserver shouldn't send notification again (see the header comments
00026    in gdbserver/notif.c).
00027 
00028    Notifications are processed in an almost-unified approach for both
00029    all-stop mode and non-stop mode, except the timing to process them.
00030    In non-stop mode, notifications are processed in
00031    remote_async_get_pending_events_handler, while in all-stop mode,
00032    they are processed in remote_resume.  */
00033 
00034 #include "defs.h"
00035 #include "remote.h"
00036 #include "remote-notif.h"
00037 #include "observer.h"
00038 #include "event-loop.h"
00039 #include "target.h"
00040 #include "inferior.h"
00041 #include "gdbcmd.h"
00042 
00043 #include <string.h>
00044 
00045 int notif_debug = 0;
00046 
00047 /* Supported clients of notifications.  */
00048 
00049 static struct notif_client *notifs[] =
00050 {
00051   &notif_client_stop,
00052 };
00053 
00054 gdb_static_assert (ARRAY_SIZE (notifs) == REMOTE_NOTIF_LAST);
00055 
00056 static void do_notif_event_xfree (void *arg);
00057 
00058 /* Parse the BUF for the expected notification NC, and send packet to
00059    acknowledge.  */
00060 
00061 void
00062 remote_notif_ack (struct notif_client *nc, char *buf)
00063 {
00064   struct notif_event *event = nc->alloc_event ();
00065   struct cleanup *old_chain
00066     = make_cleanup (do_notif_event_xfree, event);
00067 
00068   if (notif_debug)
00069     fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
00070                         nc->ack_command);
00071 
00072   nc->parse (nc, buf, event);
00073   nc->ack (nc, buf, event);
00074 
00075   discard_cleanups (old_chain);
00076 }
00077 
00078 /* Parse the BUF for the expected notification NC.  */
00079 
00080 struct notif_event *
00081 remote_notif_parse (struct notif_client *nc, char *buf)
00082 {
00083   struct notif_event *event = nc->alloc_event ();
00084   struct cleanup *old_chain
00085     = make_cleanup (do_notif_event_xfree, event);
00086 
00087   if (notif_debug)
00088     fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
00089 
00090   nc->parse (nc, buf, event);
00091 
00092   discard_cleanups (old_chain);
00093   return event;
00094 }
00095 
00096 DEFINE_QUEUE_P (notif_client_p);
00097 
00098 /* Process notifications in STATE's notification queue one by one.
00099    EXCEPT is not expected in the queue.  */
00100 
00101 void
00102 remote_notif_process (struct remote_notif_state *state,
00103                       struct notif_client *except)
00104 {
00105   while (!QUEUE_is_empty (notif_client_p, state->notif_queue))
00106     {
00107       struct notif_client *nc = QUEUE_deque (notif_client_p,
00108                                              state->notif_queue);
00109 
00110       gdb_assert (nc != except);
00111 
00112       if (nc->can_get_pending_events (nc))
00113         remote_notif_get_pending_events (nc);
00114     }
00115 }
00116 
00117 static void
00118 remote_async_get_pending_events_handler (gdb_client_data data)
00119 {
00120   gdb_assert (non_stop);
00121   remote_notif_process (data, NULL);
00122 }
00123 
00124 /* Remote notification handler.  Parse BUF, queue notification and
00125    update STATE.  */
00126 
00127 void
00128 handle_notification (struct remote_notif_state *state, char *buf)
00129 {
00130   struct notif_client *nc = NULL;
00131   int i;
00132 
00133   for (i = 0; i < ARRAY_SIZE (notifs); i++)
00134     {
00135       nc = notifs[i];
00136       if (strncmp (buf, nc->name, strlen (nc->name)) == 0
00137           && buf[strlen (nc->name)] == ':')
00138         break;
00139     }
00140 
00141   /* We ignore notifications we don't recognize, for compatibility
00142      with newer stubs.  */
00143   if (nc == NULL)
00144     return;
00145 
00146   if (state->pending_event[nc->id] != NULL)
00147     {
00148       /* We've already parsed the in-flight reply, but the stub for some
00149          reason thought we didn't, possibly due to timeout on its side.
00150          Just ignore it.  */
00151       if (notif_debug)
00152         fprintf_unfiltered (gdb_stdlog,
00153                             "notif: ignoring resent notification\n");
00154     }
00155   else
00156     {
00157       struct notif_event *event
00158         = remote_notif_parse (nc, buf + strlen (nc->name) + 1);
00159 
00160       /* Be careful to only set it after parsing, since an error
00161          may be thrown then.  */
00162       state->pending_event[nc->id] = event;
00163 
00164       /* Notify the event loop there's a stop reply to acknowledge
00165          and that there may be more events to fetch.  */
00166       QUEUE_enque (notif_client_p, state->notif_queue, nc);
00167       if (non_stop)
00168         {
00169           /* In non-stop, We mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
00170              in order to go on what we were doing and postpone
00171              querying notification events to some point safe to do so.
00172              See details in the function comment of
00173              remote.c:remote_notif_get_pending_events.
00174 
00175              In all-stop, GDB may be blocked to wait for the reply, we
00176              shouldn't return to event loop until the expected reply
00177              arrives.  For example:
00178 
00179              1.1) --> vCont;c
00180                GDB expects getting stop reply 'T05 thread:2'.
00181              1.2) <-- %Notif
00182                <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
00183 
00184              After step #1.2, we return to the event loop, which
00185              notices there is a new event on the
00186              REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and calls the
00187              handler, which will send 'vNotif' packet.
00188              1.3) --> vNotif
00189              It is not safe to start a new sequence, because target
00190              is still running and GDB is expecting the stop reply
00191              from stub.
00192 
00193              To solve this, whenever we parse a notification
00194              successfully, we don't mark the
00195              REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and let GDB blocked
00196              there as before to get the sequence done.
00197 
00198              2.1) --> vCont;c
00199                GDB expects getting stop reply 'T05 thread:2'
00200              2.2) <-- %Notif
00201                <Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
00202              2.3) <-- T05 thread:2
00203 
00204              These pending notifications can be processed later.  */
00205           mark_async_event_handler (state->get_pending_events_token);
00206         }
00207 
00208       if (notif_debug)
00209         fprintf_unfiltered (gdb_stdlog,
00210                             "notif: Notification '%s' captured\n",
00211                             nc->name);
00212     }
00213 }
00214 
00215 /* Invoke destructor of EVENT and xfree it.  */
00216 
00217 void
00218 notif_event_xfree (struct notif_event *event)
00219 {
00220   if (event != NULL && event->dtr != NULL)
00221     event->dtr (event);
00222 
00223   xfree (event);
00224 }
00225 
00226 /* Cleanup wrapper.  */
00227 
00228 static void
00229 do_notif_event_xfree (void *arg)
00230 {
00231   notif_event_xfree (arg);
00232 }
00233 
00234 /* Return an allocated remote_notif_state.  */
00235 
00236 struct remote_notif_state *
00237 remote_notif_state_allocate (void)
00238 {
00239   struct remote_notif_state *notif_state = xzalloc (sizeof (*notif_state));
00240 
00241   notif_state->notif_queue = QUEUE_alloc (notif_client_p, NULL);
00242 
00243   /* Register async_event_handler for notification.  */
00244 
00245   notif_state->get_pending_events_token
00246     = create_async_event_handler (remote_async_get_pending_events_handler,
00247                                   notif_state);
00248 
00249   return notif_state;
00250 }
00251 
00252 /* Free STATE and its fields.  */
00253 
00254 void
00255 remote_notif_state_xfree (struct remote_notif_state *state)
00256 {
00257   int i;
00258 
00259   QUEUE_free (notif_client_p, state->notif_queue);
00260 
00261   /* Unregister async_event_handler for notification.  */
00262   if (state->get_pending_events_token != NULL)
00263     delete_async_event_handler (&state->get_pending_events_token);
00264 
00265   for (i = 0; i < REMOTE_NOTIF_LAST; i++)
00266     notif_event_xfree (state->pending_event[i]);
00267 
00268   xfree (state);
00269 }
00270 
00271 /* -Wmissing-prototypes */
00272 extern initialize_file_ftype _initialize_notif;
00273 
00274 void
00275 _initialize_notif (void)
00276 {
00277   add_setshow_boolean_cmd ("notification", no_class, &notif_debug,
00278                            _("\
00279 Set debugging of async remote notification."), _("\
00280 Show debugging of async remote notification."), _("\
00281 When non-zero, debugging output about async remote notifications"
00282 " is enabled."),
00283                            NULL,
00284                            NULL,
00285                            &setdebuglist, &showdebuglist);
00286 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines