Move pending_event to remote_notif_state.
authorYao Qi <yao@codesourcery.com>
Fri, 4 Oct 2013 07:42:06 +0000 (07:42 +0000)
committerYao Qi <yao@codesourcery.com>
Fri, 4 Oct 2013 07:42:06 +0000 (07:42 +0000)
This patch moves pending_event to remote_notif_state.  All pending
events are destroyed in remote_notif_state_xfree.  However,
discard_pending_stop_replies release pending event too, so the pending
event of stop notification is released twice, we need some refactor
here.  We add a new function discard_pending_stop_replies_in_queue
which only discard events in stop_reply_queue, and let
remote_notif_state_xfree release pending event for all notif_client.

After this change, discard_pending_stop_replies is only attached to
ifnerior_exit observer, so the INF can't be NULL any more.  The
NULL checking is removed too.

gdb:

2013-10-04  Yao Qi  <yao@codesourcery.com>

* remote-notif.h (REMOTE_NOTIF_ID): New enum.
(struct notif_client) <pending_event>: Moved
to struct remote_notif_state.
<id>: New field.
(struct remote_notif_state) <pending_event>: New field.
(notif_event_xfree): Declare.
* remote-notif.c (handle_notification): Adjust.
(notif_event_xfree): New function.
(do_notif_event_xfree): Call notif_event_xfree.
(remote_notif_state_xfree): Call notif_event_xfree to free
each element in field pending_event.
* remote.c (discard_pending_stop_replies): Remove declaration.
(discard_pending_stop_replies_in_queue): Declare.
(remote_close): Call discard_pending_stop_replies_in_queue
instead of discard_pending_stop_replies.
(remote_start_remote): Adjust.
(stop_reply_xfree): Call notif_event_xfree.
(notif_client_stop): Adjust initialization.
(remote_notif_remove_all): Rename it to ...
(remove_stop_reply_for_inferior): ... this.  Update comments.
Don't check INF is NULL.
(discard_pending_stop_replies): Return early if notif_state is
NULL.  Adjust.  Don't check INF is NULL.
(remote_notif_get_pending_events): Adjust.
  (discard_pending_stop_replies_in_queue): New function.
(remote_wait_ns): Likewise.

gdb/ChangeLog
gdb/remote-notif.c
gdb/remote-notif.h
gdb/remote.c

index 4336f37..53359dd 100644 (file)
@@ -1,5 +1,34 @@
 2013-10-04  Yao Qi  <yao@codesourcery.com>
 
+       * remote-notif.h (REMOTE_NOTIF_ID): New enum.
+       (struct notif_client) <pending_event>: Moved
+       to struct remote_notif_state.
+       <id>: New field.
+       (struct remote_notif_state) <pending_event>: New field.
+       (notif_event_xfree): Declare.
+       * remote-notif.c (handle_notification): Adjust.
+       (notif_event_xfree): New function.
+       (do_notif_event_xfree): Call notif_event_xfree.
+       (remote_notif_state_xfree): Call notif_event_xfree to free
+       each element in field pending_event.
+       * remote.c (discard_pending_stop_replies): Remove declaration.
+       (discard_pending_stop_replies_in_queue): Declare.
+       (remote_close): Call discard_pending_stop_replies_in_queue
+       instead of discard_pending_stop_replies.
+       (remote_start_remote): Adjust.
+       (stop_reply_xfree): Call notif_event_xfree.
+       (notif_client_stop): Adjust initialization.
+       (remote_notif_remove_all): Rename it to ...
+       (remove_stop_reply_for_inferior): ... this.  Update comments.
+       Don't check INF is NULL.
+       (discard_pending_stop_replies): Return early if notif_state is
+       NULL.  Adjust.  Don't check INF is NULL.
+       (remote_notif_get_pending_events): Adjust.
+       (discard_pending_stop_replies_in_queue): New function.
+       (remote_wait_ns): Likewise.
+
+2013-10-04  Yao Qi  <yao@codesourcery.com>
+
        * remote-notif.c (DECLARE_QUEUE_P): Remove.
        (notif_queue): Remove.
        (remote_notif_process): Add one parameter 'notif_queue'.
index 905b8a1..0d59279 100644 (file)
@@ -51,6 +51,8 @@ static struct notif_client *notifs[] =
   &notif_client_stop,
 };
 
+gdb_static_assert (ARRAY_SIZE (notifs) == REMOTE_NOTIF_LAST);
+
 static void do_notif_event_xfree (void *arg);
 
 /* Parse the BUF for the expected notification NC, and send packet to
@@ -141,7 +143,7 @@ handle_notification (struct remote_notif_state *state, char *buf)
   if (nc == NULL)
     return;
 
-  if (nc->pending_event)
+  if (state->pending_event[nc->id] != NULL)
     {
       /* We've already parsed the in-flight reply, but the stub for some
         reason thought we didn't, possibly due to timeout on its side.
@@ -157,7 +159,7 @@ handle_notification (struct remote_notif_state *state, char *buf)
 
       /* Be careful to only set it after parsing, since an error
         may be thrown then.  */
-      nc->pending_event = event;
+      state->pending_event[nc->id] = event;
 
       /* Notify the event loop there's a stop reply to acknowledge
         and that there may be more events to fetch.  */
@@ -210,19 +212,25 @@ handle_notification (struct remote_notif_state *state, char *buf)
     }
 }
 
-/* Cleanup wrapper.  */
+/* Invoke destructor of EVENT and xfree it.  */
 
-static void
-do_notif_event_xfree (void *arg)
+void
+notif_event_xfree (struct notif_event *event)
 {
-  struct notif_event *event = arg;
-
-  if (event && event->dtr)
+  if (event != NULL && event->dtr != NULL)
     event->dtr (event);
 
   xfree (event);
 }
 
+/* Cleanup wrapper.  */
+
+static void
+do_notif_event_xfree (void *arg)
+{
+  notif_event_xfree (arg);
+}
+
 /* Return an allocated remote_notif_state.  */
 
 struct remote_notif_state *
@@ -246,12 +254,17 @@ remote_notif_state_allocate (void)
 void
 remote_notif_state_xfree (struct remote_notif_state *state)
 {
+  int i;
+
   QUEUE_free (notif_client_p, state->notif_queue);
 
   /* Unregister async_event_handler for notification.  */
   if (state->get_pending_events_token != NULL)
     delete_async_event_handler (&state->get_pending_events_token);
 
+  for (i = 0; i < REMOTE_NOTIF_LAST; i++)
+    notif_event_xfree (state->pending_event[i]);
+
   xfree (state);
 }
 
index 4c3617e..e5ebbc7 100644 (file)
@@ -31,6 +31,14 @@ struct notif_event
   void (*dtr) (struct notif_event *self);
 };
 
+/* ID of the notif_client.  */
+
+enum REMOTE_NOTIF_ID
+{
+  REMOTE_NOTIF_STOP = 0,
+  REMOTE_NOTIF_LAST,
+};
+
 /* A client to a sort of async remote notification.  */
 
 typedef struct notif_client
@@ -59,13 +67,8 @@ typedef struct notif_client
   /* Allocate an event.  */
   struct notif_event *(*alloc_event) (void);
 
-  /* One pending event.  This is where we keep it until it is
-     acknowledged.  When there is a notification packet, parse it,
-     and create an object of 'struct notif_event' to assign to
-     it.  This field is unchanged until GDB starts to ack this
-     notification (which is done by
-     remote.c:remote_notif_pending_replies).  */
-  struct notif_event *pending_event;
+  /* Id of this notif_client.  */
+  const enum REMOTE_NOTIF_ID id;
 } *notif_client_p;
 
 DECLARE_QUEUE_P (notif_client_p);
@@ -84,12 +87,23 @@ struct remote_notif_state
      the remote side into our event queue.  */
 
   struct async_event_handler *get_pending_events_token;
+
+/* One pending event for each notification client.  This is where we
+   keep it until it is acknowledged.  When there is a notification
+   packet, parse it, and create an object of 'struct notif_event' to
+   assign to it.  This field is unchanged until GDB starts to ack
+   this notification (which is done by
+   remote.c:remote_notif_pending_replies).  */
+
+  struct notif_event *pending_event[REMOTE_NOTIF_LAST];
 };
 
 void remote_notif_ack (struct notif_client *nc, char *buf);
 struct notif_event *remote_notif_parse (struct notif_client *nc,
                                        char *buf);
 
+void notif_event_xfree (struct notif_event *event);
+
 void handle_notification (struct remote_notif_state *notif_state,
                          char *buf);
 
index 6ac3f51..60086d2 100644 (file)
@@ -220,7 +220,7 @@ struct stop_reply;
 static void stop_reply_xfree (struct stop_reply *);
 static void remote_parse_stop_reply (char *, struct stop_reply *);
 static void push_stop_reply (struct stop_reply *);
-static void discard_pending_stop_replies (struct inferior *);
+static void discard_pending_stop_replies_in_queue (void);
 static int peek_stop_reply (ptid_t ptid);
 
 static void remote_async_inferior_event_handler (gdb_client_data);
@@ -3067,11 +3067,9 @@ remote_close (void)
   inferior_ptid = null_ptid;
   discard_all_inferiors ();
 
-  /* Stop replies may from inferiors which are still unknown to GDB.
-     We are closing the remote target, so we should discard
-     everything, including the stop replies from GDB-unknown
-     inferiors.  */
-  discard_pending_stop_replies (NULL);
+  /* We are closing the remote target, so we should discard
+     everything of this target.  */
+  discard_pending_stop_replies_in_queue ();
 
   if (remote_async_inferior_event_token)
     delete_async_event_handler (&remote_async_inferior_event_token);
@@ -3572,7 +3570,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
 
          /* remote_notif_get_pending_replies acks this one, and gets
             the rest out.  */
-         notif_client_stop.pending_event
+         rs->notif_state->pending_event[notif_client_stop.id]
            = remote_notif_parse (notif, rs->buf);
          remote_notif_get_pending_events (notif);
 
@@ -5304,11 +5302,7 @@ static QUEUE (stop_reply_p) *stop_reply_queue;
 static void
 stop_reply_xfree (struct stop_reply *r)
 {
-  if (r != NULL)
-    {
-      VEC_free (cached_reg_t, r->regcache);
-      xfree (r);
-    }
+  notif_event_xfree ((struct notif_event *) r);
 }
 
 static void
@@ -5375,7 +5369,7 @@ struct notif_client notif_client_stop =
   remote_notif_stop_ack,
   remote_notif_stop_can_get_pending_events,
   remote_notif_stop_alloc_reply,
-  NULL,
+  REMOTE_NOTIF_STOP,
 };
 
 /* A parameter to pass data in and out.  */
@@ -5386,18 +5380,19 @@ struct queue_iter_param
   struct stop_reply *output;
 };
 
-/* Remove all queue elements meet the condition it checks.  */
+/* Remove stop replies in the queue if its pid is equal to the given
+   inferior's pid.  */
 
 static int
-remote_notif_remove_all (QUEUE (stop_reply_p) *q,
-                        QUEUE_ITER (stop_reply_p) *iter,
-                        stop_reply_p event,
-                        void *data)
+remove_stop_reply_for_inferior (QUEUE (stop_reply_p) *q,
+                               QUEUE_ITER (stop_reply_p) *iter,
+                               stop_reply_p event,
+                               void *data)
 {
   struct queue_iter_param *param = data;
   struct inferior *inf = param->input;
 
-  if (inf == NULL || ptid_get_pid (event->ptid) == inf->pid)
+  if (ptid_get_pid (event->ptid) == inf->pid)
     {
       stop_reply_xfree (event);
       QUEUE_remove_elem (stop_reply_p, q, iter);
@@ -5406,24 +5401,29 @@ remote_notif_remove_all (QUEUE (stop_reply_p) *q,
   return 1;
 }
 
-/* Discard all pending stop replies of inferior INF.  If INF is NULL,
-   discard everything.  */
+/* Discard all pending stop replies of inferior INF.  */
 
 static void
 discard_pending_stop_replies (struct inferior *inf)
 {
   int i;
   struct queue_iter_param param;
-  struct stop_reply *reply
-    = (struct stop_reply *) notif_client_stop.pending_event;
+  struct stop_reply *reply;
+  struct remote_state *rs = get_remote_state ();
+  struct remote_notif_state *rns = rs->notif_state;
+
+  /* This function can be notified when an inferior exists.  When the
+     target is not remote, the notification state is NULL.  */
+  if (rs->remote_desc == NULL)
+    return;
+
+  reply = (struct stop_reply *) rns->pending_event[notif_client_stop.id];
 
   /* Discard the in-flight notification.  */
-  if (reply != NULL
-      && (inf == NULL
-         || ptid_get_pid (reply->ptid) == inf->pid))
+  if (reply != NULL && ptid_get_pid (reply->ptid) == inf->pid)
     {
       stop_reply_xfree (reply);
-      notif_client_stop.pending_event = NULL;
+      rns->pending_event[notif_client_stop.id] = NULL;
     }
 
   param.input = inf;
@@ -5431,7 +5431,22 @@ discard_pending_stop_replies (struct inferior *inf)
   /* Discard the stop replies we have already pulled with
      vStopped.  */
   QUEUE_iterate (stop_reply_p, stop_reply_queue,
-                remote_notif_remove_all, &param);
+                remove_stop_reply_for_inferior, &param);
+}
+
+/* Discard the stop replies in stop_reply_queue.  */
+
+static void
+discard_pending_stop_replies_in_queue (void)
+{
+  struct queue_iter_param param;
+
+  param.input = NULL;
+  param.output = NULL;
+  /* Discard the stop replies we have already pulled with
+     vStopped.  */
+  QUEUE_iterate (stop_reply_p, stop_reply_queue,
+                remove_stop_reply_for_inferior, &param);
 }
 
 /* A parameter to pass data in and out.  */
@@ -5787,7 +5802,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
 {
   struct remote_state *rs = get_remote_state ();
 
-  if (nc->pending_event)
+  if (rs->notif_state->pending_event[nc->id] != NULL)
     {
       if (notif_debug)
        fprintf_unfiltered (gdb_stdlog,
@@ -5795,8 +5810,8 @@ remote_notif_get_pending_events (struct notif_client *nc)
                            nc->name);
 
       /* acknowledge */
-      nc->ack (nc, rs->buf, nc->pending_event);
-      nc->pending_event = NULL;
+      nc->ack (nc, rs->buf, rs->notif_state->pending_event[nc->id]);
+      rs->notif_state->pending_event[nc->id] = NULL;
 
       while (1)
        {
@@ -5901,7 +5916,7 @@ remote_wait_ns (ptid_t ptid, struct target_waitstatus *status, int options)
 
       /* Acknowledge a pending stop reply that may have arrived in the
         mean time.  */
-      if (notif_client_stop.pending_event != NULL)
+      if (rs->notif_state->pending_event[notif_client_stop.id] != NULL)
        remote_notif_get_pending_events (&notif_client_stop);
 
       /* If indeed we noticed a stop reply, we're done.  */