aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYao Qi <yao@codesourcery.com>2013-10-04 07:42:06 +0000
committerYao Qi <yao@codesourcery.com>2013-10-04 07:42:06 +0000
commitf48ff2a7d3f69653dbf164e03d3397de8f6ba7c0 (patch)
treec865c15272902c555bae310d136f73eee5db53c7
parent5965e02896b242f2ffe086def9c83a205eef31aa (diff)
downloadgdb-f48ff2a7d3f69653dbf164e03d3397de8f6ba7c0.zip
gdb-f48ff2a7d3f69653dbf164e03d3397de8f6ba7c0.tar.gz
gdb-f48ff2a7d3f69653dbf164e03d3397de8f6ba7c0.tar.bz2
Move pending_event to remote_notif_state.
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.
-rw-r--r--gdb/ChangeLog29
-rw-r--r--gdb/remote-notif.c29
-rw-r--r--gdb/remote-notif.h28
-rw-r--r--gdb/remote.c79
4 files changed, 118 insertions, 47 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4336f37..53359dd 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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'.
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index 905b8a1..0d59279 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -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);
}
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index 4c3617e..e5ebbc7 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -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);
diff --git a/gdb/remote.c b/gdb/remote.c
index 6ac3f51..60086d2 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -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. */