GDBserver
/home/stan/gdb/src/gdb/gdbserver/notif.c
Go to the documentation of this file.
00001 /* Notification to GDB.
00002    Copyright (C) 1989-2013 Free Software Foundation, Inc.
00003 
00004    This file is part of GDB.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 3 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00018 
00019 /* Async notifications to GDB.  When the state of remote target is
00020    changed or something interesting to GDB happened, async
00021    notifications are used to tell GDB.
00022 
00023    Each type of notification is represented by an object
00024    'struct notif_server', in which there is a queue for events to GDB
00025    represented by 'struct notif_event'.  GDBserver writes (by means of
00026    'write' field) each event in the queue into the buffer and send the
00027    contents in buffer to GDB.  The contents in buffer is specified in
00028    RSP.  See more in the comments to field 'queue' of
00029    'struct notif_server'.
00030 
00031    Here is the workflow of sending events and managing queue:
00032    1.  At any time, when something interesting FOO happens, a object
00033    of 'struct notif_event' or its sub-class EVENT is created for FOO.
00034 
00035    2.  Enque EVENT to the 'queue' field of 'struct notif_server' for
00036    FOO and send corresponding notification packet to GDB if EVENT is
00037    the first one.
00038    #1 and #2 are done by function 'notif_push'.
00039 
00040    3.  EVENT is not deque'ed until the ack of FOO from GDB arrives.
00041    Before ack of FOO arrives, FOO happens again, a new object of
00042    EVENT is created and enque EVENT silently.
00043    Once GDB has a chance to ack to FOO, it sends an ack to GDBserver,
00044    and GDBserver repeatedly sends events to GDB and gets ack of FOO,
00045    until queue is empty.  Then, GDBserver sends 'OK' to GDB that all
00046    queued notification events are done.
00047 
00048    # 3 is done by function 'handle_notif_ack'.  */
00049 
00050 #include "notif.h"
00051 
00052 static struct notif_server *notifs[] =
00053 {
00054   &notif_stop,
00055 };
00056 
00057 /* Write another event or an OK, if there are no more left, to
00058    OWN_BUF.  */
00059 
00060 void
00061 notif_write_event (struct notif_server *notif, char *own_buf)
00062 {
00063   if (!QUEUE_is_empty (notif_event_p, notif->queue))
00064     {
00065       struct notif_event *event
00066         = QUEUE_peek (notif_event_p, notif->queue);
00067 
00068       notif->write (event, own_buf);
00069     }
00070   else
00071     write_ok (own_buf);
00072 }
00073 
00074 /* Handle the ack in buffer OWN_BUF,and packet length is PACKET_LEN.
00075    Return 1 if the ack is handled, and return 0 if the contents
00076    in OWN_BUF is not a ack.  */
00077 
00078 int
00079 handle_notif_ack (char *own_buf, int packet_len)
00080 {
00081   int i = 0;
00082   struct notif_server *np = NULL;
00083 
00084   for (i = 0; i < ARRAY_SIZE (notifs); i++)
00085     {
00086       np = notifs[i];
00087       if (strncmp (own_buf, np->ack_name, strlen (np->ack_name)) == 0
00088           && packet_len == strlen (np->ack_name))
00089         break;
00090     }
00091 
00092   if (np == NULL)
00093     return 0;
00094 
00095   /* If we're waiting for GDB to acknowledge a pending event,
00096      consider that done.  */
00097   if (!QUEUE_is_empty (notif_event_p, np->queue))
00098     {
00099       struct notif_event *head
00100         = QUEUE_deque (notif_event_p, np->queue);
00101 
00102       if (remote_debug)
00103         fprintf (stderr, "%s: acking %d\n", np->ack_name,
00104                  QUEUE_length (notif_event_p, np->queue));
00105 
00106       xfree (head);
00107     }
00108 
00109   notif_write_event (np, own_buf);
00110 
00111   return 1;
00112 }
00113 
00114 /* Put EVENT to the queue of NOTIF.  */
00115 
00116 void
00117 notif_event_enque (struct notif_server *notif,
00118                    struct notif_event *event)
00119 {
00120   QUEUE_enque (notif_event_p, notif->queue, event);
00121 
00122   if (remote_debug)
00123     fprintf (stderr, "pending events: %s %d\n", notif->notif_name,
00124              QUEUE_length (notif_event_p, notif->queue));
00125 
00126 }
00127 
00128 /* Push one event NEW_EVENT of notification NP into NP->queue.  */
00129 
00130 void
00131 notif_push (struct notif_server *np, struct notif_event *new_event)
00132 {
00133   int is_first_event = QUEUE_is_empty (notif_event_p, np->queue);
00134 
00135   /* Something interesting.  Tell GDB about it.  */
00136   notif_event_enque (np, new_event);
00137 
00138   /* If this is the first stop reply in the queue, then inform GDB
00139      about it, by sending a corresponding notification.  */
00140   if (is_first_event)
00141     {
00142       char buf[PBUFSIZ];
00143       char *p = buf;
00144 
00145       xsnprintf (p, PBUFSIZ, "%s:", np->notif_name);
00146       p += strlen (p);
00147 
00148       np->write (new_event, p);
00149       putpkt_notif (buf);
00150     }
00151 }
00152 
00153 static void
00154 notif_event_xfree (struct notif_event *event)
00155 {
00156   xfree (event);
00157 }
00158 
00159 void
00160 initialize_notif (void)
00161 {
00162   int i = 0;
00163 
00164   for (i = 0; i < ARRAY_SIZE (notifs); i++)
00165     notifs[i]->queue
00166       = QUEUE_alloc (notif_event_p, notif_event_xfree);
00167 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines