gdb/
2012-12-15 Yao Qi <yao@codesourcery.com> * Makefile.in (REMOTE_OBS): Add "remote-notif.o". (SFILES): Add "remote-notif.c". (HFILES_NO_SRCDIR): Add "remote-notif.h" and "common/queue.h". * remote-notif.c: New. Factored out from remote.c. * remote-notif.h: New. * remote.c: Include "remote-notif.h". (stop_reply_xmalloc, do_stop_reply_xfree): (remote_parse_stop_reply, remote_get_pending_stop_replies): (remote_async_get_pending_events_handler): Remove declarations. (remote_parse_stop_reply): Declare. (pending_stop_reply): Remove. (remote_async_get_pending_events_token): Move to remote-notif.c. (remote_close): Replace 'delete_async_event_handler' with remote_notif_unregister_async_event_handler. Don't call discard_pending_stop_replies. (remote_start_remote): Replace code with remote_notif_parse and remote_notif_get_pending_replies. (remote_open_1): Replace 'create_async_event_handler' with remote_notif_register_async_event_handler. (extended_remote_attach_1): Call remote_notif_parse and notif_stop_reply_push. (struct stop_reply) <next>: Remove. <base>: New field. Callers update. (stop_reply_queue): Change its type. (stop_reply_xmalloc, do_stop_reply_xfree): Remove. (remote_notif_remove_all): New. (discard_pending_stop_replies): Update. (remote_notif_stop_ack, stop_reply_dtr): New. (remote_notif_stop_alloc_event): New. (notif_client_stop): New variable. (stop_reply_match_ptid, stop_reply_match_ptid_and_ws: New. (queued_stop_reply, peek_stop_reply): Adjust. (remote_get_pending_stop_replies): Rename to remote_notif_get_pending_events. (handle_notification): Move to remote-notif.c. (remote_async_get_pending_events_handler): Likewise. (remote_wait_as): Adjust to call remote_notif_parse. Call 'getpkt_or_notif_sane' instead of 'getpkt_sane'. Return minus_one_ptid early if gets a notification. (remote_wait): Call QUEUE_is_empty (notif_reply_p). (_initialize_remote): Call QUEUE_alloc. Update caller. (remote_resume): Call 'remote_notif_process' in all-stop mode. * remote.h: Include "remote-notif.h". (remote_notif_get_pending_replies): Declare.
This commit is contained in:
parent
5f4cf0bb27
commit
722247f1cb
@ -1,3 +1,52 @@
|
||||
2012-12-15 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* Makefile.in (REMOTE_OBS): Add "remote-notif.o".
|
||||
(SFILES): Add "remote-notif.c".
|
||||
(HFILES_NO_SRCDIR): Add "remote-notif.h" and "common/queue.h".
|
||||
* remote-notif.c: New. Factored out from remote.c.
|
||||
* remote-notif.h: New.
|
||||
* remote.c: Include "remote-notif.h".
|
||||
(stop_reply_xmalloc, do_stop_reply_xfree):
|
||||
(remote_parse_stop_reply, remote_get_pending_stop_replies):
|
||||
(remote_async_get_pending_events_handler): Remove declarations.
|
||||
(remote_parse_stop_reply): Declare.
|
||||
(pending_stop_reply): Remove.
|
||||
(remote_async_get_pending_events_token): Move to
|
||||
remote-notif.c.
|
||||
(remote_close): Replace 'delete_async_event_handler' with
|
||||
remote_notif_unregister_async_event_handler.
|
||||
Don't call discard_pending_stop_replies.
|
||||
(remote_start_remote): Replace code with remote_notif_parse
|
||||
and remote_notif_get_pending_replies.
|
||||
(remote_open_1): Replace 'create_async_event_handler' with
|
||||
remote_notif_register_async_event_handler.
|
||||
(extended_remote_attach_1): Call remote_notif_parse and
|
||||
notif_stop_reply_push.
|
||||
(struct stop_reply) <next>: Remove.
|
||||
<base>: New field.
|
||||
Callers update.
|
||||
(stop_reply_queue): Change its type.
|
||||
(stop_reply_xmalloc, do_stop_reply_xfree): Remove.
|
||||
(remote_notif_remove_all): New.
|
||||
(discard_pending_stop_replies): Update.
|
||||
(remote_notif_stop_ack, stop_reply_dtr): New.
|
||||
(remote_notif_stop_alloc_event): New.
|
||||
(notif_client_stop): New variable.
|
||||
(stop_reply_match_ptid, stop_reply_match_ptid_and_ws: New.
|
||||
(queued_stop_reply, peek_stop_reply): Adjust.
|
||||
(remote_get_pending_stop_replies): Rename to
|
||||
remote_notif_get_pending_events.
|
||||
(handle_notification): Move to remote-notif.c.
|
||||
(remote_async_get_pending_events_handler): Likewise.
|
||||
(remote_wait_as): Adjust to call remote_notif_parse.
|
||||
Call 'getpkt_or_notif_sane' instead of 'getpkt_sane'.
|
||||
Return minus_one_ptid early if gets a notification.
|
||||
(remote_wait): Call QUEUE_is_empty (notif_reply_p).
|
||||
(_initialize_remote): Call QUEUE_alloc. Update caller.
|
||||
(remote_resume): Call 'remote_notif_process' in all-stop mode.
|
||||
* remote.h: Include "remote-notif.h".
|
||||
(remote_notif_get_pending_replies): Declare.
|
||||
|
||||
2012-12-15 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* remote.c (discard_pending_stop_replies): Update declaration.
|
||||
|
@ -507,7 +507,8 @@ SER_HARDWIRE = @SER_HARDWIRE@
|
||||
|
||||
# The `remote' debugging target is supported for most architectures,
|
||||
# but not all (e.g. 960)
|
||||
REMOTE_OBS = remote.o dcache.o tracepoint.o ax-general.o ax-gdb.o remote-fileio.o
|
||||
REMOTE_OBS = remote.o dcache.o tracepoint.o ax-general.o ax-gdb.o remote-fileio.o \
|
||||
remote-notif.o
|
||||
|
||||
# This is remote-sim.o if a simulator is to be linked in.
|
||||
SIM_OBS = @SIM_OBS@
|
||||
@ -729,7 +730,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
|
||||
p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \
|
||||
proc-service.list progspace.c \
|
||||
prologue-value.c psymtab.c \
|
||||
regcache.c reggroups.c remote.c remote-fileio.c reverse.c \
|
||||
regcache.c reggroups.c remote.c remote-fileio.c remote-notif.c reverse.c \
|
||||
sentinel-frame.c \
|
||||
serial.c ser-base.c ser-unix.c skip.c \
|
||||
solib.c solib-target.c source.c \
|
||||
@ -774,7 +775,7 @@ c-lang.h d-lang.h go-lang.h frame.h event-loop.h block.h cli/cli-setshow.h \
|
||||
cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h cli/cli-utils.h \
|
||||
cli/cli-script.h macrotab.h symtab.h version.h \
|
||||
gnulib/import/string.in.h gnulib/import/str-two-way.h \
|
||||
gnulib/import/stdint.in.h remote.h gdb.h sparc-nat.h \
|
||||
gnulib/import/stdint.in.h remote.h remote-notif.h gdb.h sparc-nat.h \
|
||||
gdbthread.h dwarf2-frame.h dwarf2-frame-tailcall.h nbsd-nat.h dcache.h \
|
||||
amd64-nat.h s390-tdep.h arm-linux-tdep.h exceptions.h macroscope.h \
|
||||
gdbarch.h bsd-uthread.h common/gdb_stat.h memory-map.h memrange.h \
|
||||
@ -826,7 +827,7 @@ gnulib/import/extra/snippet/arg-nonnull.h gnulib/import/extra/snippet/c++defs.h
|
||||
gnulib/import/extra/snippet/warn-on-use.h \
|
||||
gnulib/import/stddef.in.h gnulib/import/inttypes.in.h inline-frame.h skip.h \
|
||||
common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
|
||||
common/format.h common/host-defs.h utils.h \
|
||||
common/format.h common/host-defs.h utils.h common/queue.h \
|
||||
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h gdb_bfd.h
|
||||
|
||||
# Header files that already have srcdir in them, or which are in objdir.
|
||||
|
270
gdb/remote-notif.c
Normal file
270
gdb/remote-notif.c
Normal file
@ -0,0 +1,270 @@
|
||||
/* Remote notification in GDB protocol
|
||||
|
||||
Copyright (C) 1988-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Remote async notification is sent from remote target over RSP.
|
||||
Each type of notification is represented by an object of
|
||||
'struct notif', which has a field 'pending_reply'. It is not
|
||||
NULL when GDB receives a notification from GDBserver, but hasn't
|
||||
acknowledge yet. Before GDB acknowledges the notification,
|
||||
GDBserver shouldn't send notification again (see the header comments
|
||||
in gdbserver/notif.c).
|
||||
|
||||
Notifications are processed in an almost-unified approach for both
|
||||
all-stop mode and non-stop mode, except the timing to process them.
|
||||
In non-stop mode, notifications are processed in
|
||||
remote_async_get_pending_events_handler, while in all-stop mode,
|
||||
they are processed in remote_resume. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "remote.h"
|
||||
#include "remote-notif.h"
|
||||
#include "observer.h"
|
||||
#include "event-loop.h"
|
||||
#include "target.h"
|
||||
#include "inferior.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
unsigned int notif_debug = 0;
|
||||
|
||||
/* Supported clients of notifications. */
|
||||
|
||||
static struct notif_client *notifs[] =
|
||||
{
|
||||
¬if_client_stop,
|
||||
};
|
||||
|
||||
static void do_notif_event_xfree (void *arg);
|
||||
|
||||
/* Parse the BUF for the expected notification NC, and send packet to
|
||||
acknowledge. */
|
||||
|
||||
void
|
||||
remote_notif_ack (struct notif_client *nc, char *buf)
|
||||
{
|
||||
struct notif_event *event = nc->alloc_event ();
|
||||
struct cleanup *old_chain
|
||||
= make_cleanup (do_notif_event_xfree, event);
|
||||
|
||||
if (notif_debug)
|
||||
fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
|
||||
nc->ack_command);
|
||||
|
||||
nc->parse (nc, buf, event);
|
||||
nc->ack (nc, buf, event);
|
||||
|
||||
discard_cleanups (old_chain);
|
||||
}
|
||||
|
||||
/* Parse the BUF for the expected notification NC. */
|
||||
|
||||
struct notif_event *
|
||||
remote_notif_parse (struct notif_client *nc, char *buf)
|
||||
{
|
||||
struct notif_event *event = nc->alloc_event ();
|
||||
struct cleanup *old_chain
|
||||
= make_cleanup (do_notif_event_xfree, event);
|
||||
|
||||
if (notif_debug)
|
||||
fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
|
||||
|
||||
nc->parse (nc, buf, event);
|
||||
|
||||
discard_cleanups (old_chain);
|
||||
return event;
|
||||
}
|
||||
|
||||
DECLARE_QUEUE_P (notif_client_p);
|
||||
DEFINE_QUEUE_P (notif_client_p);
|
||||
|
||||
static QUEUE(notif_client_p) *notif_queue;
|
||||
|
||||
/* Process notifications one by one. EXCEPT is not expected in
|
||||
the queue. */
|
||||
|
||||
void
|
||||
remote_notif_process (struct notif_client *except)
|
||||
{
|
||||
while (!QUEUE_is_empty (notif_client_p, notif_queue))
|
||||
{
|
||||
struct notif_client *nc = QUEUE_deque (notif_client_p,
|
||||
notif_queue);
|
||||
|
||||
gdb_assert (nc != except);
|
||||
|
||||
if (nc->can_get_pending_events (nc))
|
||||
remote_notif_get_pending_events (nc);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remote_async_get_pending_events_handler (gdb_client_data data)
|
||||
{
|
||||
gdb_assert (non_stop);
|
||||
remote_notif_process (NULL);
|
||||
}
|
||||
|
||||
/* Asynchronous signal handle registered as event loop source for when
|
||||
the remote sent us a notification. The registered callback
|
||||
will do a ACK sequence to pull the rest of the events out of
|
||||
the remote side into our event queue. */
|
||||
|
||||
static struct async_event_handler *remote_async_get_pending_events_token;
|
||||
|
||||
/* Register async_event_handler for notification. */
|
||||
|
||||
void
|
||||
remote_notif_register_async_event_handler (void)
|
||||
{
|
||||
remote_async_get_pending_events_token
|
||||
= create_async_event_handler (remote_async_get_pending_events_handler,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Unregister async_event_handler for notification. */
|
||||
|
||||
void
|
||||
remote_notif_unregister_async_event_handler (void)
|
||||
{
|
||||
if (remote_async_get_pending_events_token)
|
||||
delete_async_event_handler (&remote_async_get_pending_events_token);
|
||||
}
|
||||
|
||||
/* Remote notification handler. */
|
||||
|
||||
void
|
||||
handle_notification (char *buf)
|
||||
{
|
||||
struct notif_client *nc = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (notifs); i++)
|
||||
{
|
||||
nc = notifs[i];
|
||||
if (strncmp (buf, nc->name, strlen (nc->name)) == 0
|
||||
&& buf[strlen (nc->name)] == ':')
|
||||
break;
|
||||
}
|
||||
|
||||
/* We ignore notifications we don't recognize, for compatibility
|
||||
with newer stubs. */
|
||||
if (nc == NULL)
|
||||
return;
|
||||
|
||||
if (nc->pending_event)
|
||||
{
|
||||
/* 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.
|
||||
Just ignore it. */
|
||||
if (notif_debug)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"notif: ignoring resent notification\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
struct notif_event *event
|
||||
= remote_notif_parse (nc, buf + strlen (nc->name) + 1);
|
||||
|
||||
/* Be careful to only set it after parsing, since an error
|
||||
may be thrown then. */
|
||||
nc->pending_event = event;
|
||||
|
||||
/* Notify the event loop there's a stop reply to acknowledge
|
||||
and that there may be more events to fetch. */
|
||||
QUEUE_enque (notif_client_p, notif_queue, nc);
|
||||
if (non_stop)
|
||||
{
|
||||
/* In non-stop, We mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
|
||||
in order to go on what we were doing and postpone
|
||||
querying notification events to some point safe to do so.
|
||||
See details in the function comment of
|
||||
remote.c:remote_notif_get_pending_events.
|
||||
|
||||
In all-stop, GDB may be blocked to wait for the reply, we
|
||||
shouldn't return to event loop until the expected reply
|
||||
arrives. For example:
|
||||
|
||||
1.1) --> vCont;c
|
||||
GDB expects getting stop reply 'T05 thread:2'.
|
||||
1.2) <-- %Notif
|
||||
<GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
|
||||
|
||||
After step #1.2, we return to the event loop, which
|
||||
notices there is a new event on the
|
||||
REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and calls the
|
||||
handler, which will send 'vNotif' packet.
|
||||
1.3) --> vNotif
|
||||
It is not safe to start a new sequence, because target
|
||||
is still running and GDB is expecting the stop reply
|
||||
from stub.
|
||||
|
||||
To solve this, whenever we parse a notification
|
||||
successfully, we don't mark the
|
||||
REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN and let GDB blocked
|
||||
there as before to get the sequence done.
|
||||
|
||||
2.1) --> vCont;c
|
||||
GDB expects getting stop reply 'T05 thread:2'
|
||||
2.2) <-- %Notif
|
||||
<Don't mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
|
||||
2.3) <-- T05 thread:2
|
||||
|
||||
These pending notifications can be processed later. */
|
||||
mark_async_event_handler (remote_async_get_pending_events_token);
|
||||
}
|
||||
|
||||
if (notif_debug)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"notif: Notification '%s' captured\n",
|
||||
nc->name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup wrapper. */
|
||||
|
||||
static void
|
||||
do_notif_event_xfree (void *arg)
|
||||
{
|
||||
struct notif_event *event = arg;
|
||||
|
||||
if (event && event->dtr)
|
||||
event->dtr (event);
|
||||
|
||||
xfree (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notif_xfree (struct notif_client *notif)
|
||||
{
|
||||
if (notif->pending_event != NULL
|
||||
&& notif->pending_event->dtr != NULL)
|
||||
notif->pending_event->dtr (notif->pending_event);
|
||||
|
||||
xfree (notif->pending_event);
|
||||
xfree (notif);
|
||||
}
|
||||
|
||||
/* -Wmissing-prototypes */
|
||||
extern initialize_file_ftype _initialize_notif;
|
||||
|
||||
void
|
||||
_initialize_notif (void)
|
||||
{
|
||||
notif_queue = QUEUE_alloc (notif_client_p, notif_xfree);
|
||||
}
|
85
gdb/remote-notif.h
Normal file
85
gdb/remote-notif.h
Normal file
@ -0,0 +1,85 @@
|
||||
/* Remote notification in GDB protocol
|
||||
|
||||
Copyright (C) 1988-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef REMOTE_NOTIF_H
|
||||
#define REMOTE_NOTIF_H
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
/* An event of a type of async remote notification. */
|
||||
|
||||
struct notif_event
|
||||
{
|
||||
/* Destructor. Release everything from SELF, but not SELF
|
||||
itself. */
|
||||
void (*dtr) (struct notif_event *self);
|
||||
};
|
||||
|
||||
/* A client to a sort of async remote notification. */
|
||||
|
||||
typedef struct notif_client
|
||||
{
|
||||
/* The name of notification packet. */
|
||||
const char *name;
|
||||
|
||||
/* The packet to acknowledge a previous reply. */
|
||||
const char *ack_command;
|
||||
|
||||
/* Parse BUF to get the expected event and update EVENT. This
|
||||
function may throw exception if contents in BUF is not the
|
||||
expected event. */
|
||||
void (*parse) (struct notif_client *self, char *buf,
|
||||
struct notif_event *event);
|
||||
|
||||
/* Send field <ack_command> to remote, and do some checking. If
|
||||
something wrong, throw an exception. */
|
||||
void (*ack) (struct notif_client *self, char *buf,
|
||||
struct notif_event *event);
|
||||
|
||||
/* Check this notification client can get pending events in
|
||||
'remote_notif_process'. */
|
||||
int (*can_get_pending_events) (struct notif_client *self);
|
||||
|
||||
/* 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;
|
||||
} *notif_client_p;
|
||||
|
||||
void remote_notif_ack (struct notif_client *nc, char *buf);
|
||||
struct notif_event *remote_notif_parse (struct notif_client *nc,
|
||||
char *buf);
|
||||
|
||||
void handle_notification (char *buf);
|
||||
|
||||
void remote_notif_register_async_event_handler (void);
|
||||
void remote_notif_unregister_async_event_handler (void);
|
||||
|
||||
void remote_notif_process (struct notif_client *except);
|
||||
extern struct notif_client notif_client_stop;
|
||||
|
||||
extern unsigned int notif_debug;
|
||||
|
||||
#endif /* REMOTE_NOTIF_H */
|
466
gdb/remote.c
466
gdb/remote.c
@ -34,6 +34,7 @@
|
||||
#include "gdb-stabs.h"
|
||||
#include "gdbthread.h"
|
||||
#include "remote.h"
|
||||
#include "remote-notif.h"
|
||||
#include "regcache.h"
|
||||
#include "value.h"
|
||||
#include "gdb_assert.h"
|
||||
@ -223,17 +224,13 @@ static void remote_check_symbols (struct objfile *objfile);
|
||||
void _initialize_remote (void);
|
||||
|
||||
struct stop_reply;
|
||||
static struct stop_reply *stop_reply_xmalloc (void);
|
||||
static void stop_reply_xfree (struct stop_reply *);
|
||||
static void do_stop_reply_xfree (void *arg);
|
||||
static void remote_parse_stop_reply (char *buf, struct stop_reply *);
|
||||
static void remote_parse_stop_reply (char *, struct stop_reply *);
|
||||
static void push_stop_reply (struct stop_reply *);
|
||||
static void remote_get_pending_stop_replies (void);
|
||||
static void discard_pending_stop_replies (struct inferior *);
|
||||
static int peek_stop_reply (ptid_t ptid);
|
||||
|
||||
static void remote_async_inferior_event_handler (gdb_client_data);
|
||||
static void remote_async_get_pending_events_handler (gdb_client_data);
|
||||
|
||||
static void remote_terminal_ours (void);
|
||||
|
||||
@ -245,11 +242,6 @@ static int remote_supports_cond_breakpoints (void);
|
||||
|
||||
static int remote_can_run_breakpoint_commands (void);
|
||||
|
||||
/* The non-stop remote protocol provisions for one pending stop reply.
|
||||
This is where we keep it until it is acknowledged. */
|
||||
|
||||
static struct stop_reply *pending_stop_reply = NULL;
|
||||
|
||||
/* For "remote". */
|
||||
|
||||
static struct cmd_list_element *remote_cmdlist;
|
||||
@ -1402,12 +1394,6 @@ static struct async_signal_handler *sigint_remote_token;
|
||||
|
||||
static struct async_event_handler *remote_async_inferior_event_token;
|
||||
|
||||
/* Asynchronous signal handle registered as event loop source for when
|
||||
the remote sent us a %Stop notification. The registered callback
|
||||
will do a vStopped sequence to pull the rest of the events out of
|
||||
the remote side into our event queue. */
|
||||
|
||||
static struct async_event_handler *remote_async_get_pending_events_token;
|
||||
|
||||
|
||||
static ptid_t magic_null_ptid;
|
||||
@ -3030,8 +3016,8 @@ remote_close (int quitting)
|
||||
|
||||
if (remote_async_inferior_event_token)
|
||||
delete_async_event_handler (&remote_async_inferior_event_token);
|
||||
if (remote_async_get_pending_events_token)
|
||||
delete_async_event_handler (&remote_async_get_pending_events_token);
|
||||
|
||||
remote_notif_unregister_async_event_handler ();
|
||||
}
|
||||
|
||||
/* Query the remote side for the text, data and bss offsets. */
|
||||
@ -3453,19 +3439,13 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
|
||||
mechanism. */
|
||||
if (strcmp (rs->buf, "OK") != 0)
|
||||
{
|
||||
struct stop_reply *stop_reply;
|
||||
struct cleanup *old_chain;
|
||||
struct notif_client *notif = ¬if_client_stop;
|
||||
|
||||
stop_reply = stop_reply_xmalloc ();
|
||||
old_chain = make_cleanup (do_stop_reply_xfree, stop_reply);
|
||||
|
||||
remote_parse_stop_reply (rs->buf, stop_reply);
|
||||
discard_cleanups (old_chain);
|
||||
|
||||
/* get_pending_stop_replies acks this one, and gets the rest
|
||||
out. */
|
||||
pending_stop_reply = stop_reply;
|
||||
remote_get_pending_stop_replies ();
|
||||
/* remote_notif_get_pending_replies acks this one, and gets
|
||||
the rest out. */
|
||||
notif_client_stop.pending_event
|
||||
= remote_notif_parse (notif, rs->buf);
|
||||
remote_notif_get_pending_events (notif);
|
||||
|
||||
/* Make sure that threads that were stopped remain
|
||||
stopped. */
|
||||
@ -4225,9 +4205,7 @@ remote_open_1 (char *name, int from_tty,
|
||||
remote_async_inferior_event_token
|
||||
= create_async_event_handler (remote_async_inferior_event_handler,
|
||||
NULL);
|
||||
remote_async_get_pending_events_token
|
||||
= create_async_event_handler (remote_async_get_pending_events_handler,
|
||||
NULL);
|
||||
remote_notif_register_async_event_handler ();
|
||||
|
||||
/* Reset the target state; these things will be queried either by
|
||||
remote_query_supported or as they are needed. */
|
||||
@ -4482,14 +4460,10 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty)
|
||||
|
||||
if (target_can_async_p ())
|
||||
{
|
||||
struct stop_reply *stop_reply;
|
||||
struct cleanup *old_chain;
|
||||
struct notif_event *reply
|
||||
= remote_notif_parse (¬if_client_stop, wait_status);
|
||||
|
||||
stop_reply = stop_reply_xmalloc ();
|
||||
old_chain = make_cleanup (do_stop_reply_xfree, stop_reply);
|
||||
remote_parse_stop_reply (wait_status, stop_reply);
|
||||
discard_cleanups (old_chain);
|
||||
push_stop_reply (stop_reply);
|
||||
push_stop_reply ((struct stop_reply *) reply);
|
||||
|
||||
target_async (inferior_event_handler, 0);
|
||||
}
|
||||
@ -4783,6 +4757,15 @@ remote_resume (struct target_ops *ops,
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
char *buf;
|
||||
|
||||
/* In all-stop, we can't mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
|
||||
(explained in remote-notif.c:handle_notification) so
|
||||
remote_notif_process is not called. We need find a place where
|
||||
it is safe to start a 'vNotif' sequence. It is good to do it
|
||||
before resuming inferior, because inferior was stopped and no RSP
|
||||
traffic at that moment. */
|
||||
if (!non_stop)
|
||||
remote_notif_process (¬if_client_stop);
|
||||
|
||||
last_sent_signal = siggnal;
|
||||
last_sent_step = step;
|
||||
|
||||
@ -5116,10 +5099,11 @@ typedef struct cached_reg
|
||||
|
||||
DEF_VEC_O(cached_reg_t);
|
||||
|
||||
struct stop_reply
|
||||
typedef struct stop_reply
|
||||
{
|
||||
struct stop_reply *next;
|
||||
struct notif_event base;
|
||||
|
||||
/* The identifier of the thread about this event */
|
||||
ptid_t ptid;
|
||||
|
||||
struct target_waitstatus ws;
|
||||
@ -5137,19 +5121,18 @@ struct stop_reply
|
||||
int replay_event;
|
||||
|
||||
int core;
|
||||
};
|
||||
} *stop_reply_p;
|
||||
|
||||
/* The list of already fetched and acknowledged stop events. */
|
||||
static struct stop_reply *stop_reply_queue;
|
||||
|
||||
static struct stop_reply *
|
||||
stop_reply_xmalloc (void)
|
||||
{
|
||||
struct stop_reply *r = XMALLOC (struct stop_reply);
|
||||
|
||||
r->next = NULL;
|
||||
return r;
|
||||
}
|
||||
DECLARE_QUEUE_P (stop_reply_p);
|
||||
DEFINE_QUEUE_P (stop_reply_p);
|
||||
/* The list of already fetched and acknowledged stop events. This
|
||||
queue is used for notification Stop, and other notifications
|
||||
don't need queue for their events, because the notification events
|
||||
of Stop can't be consumed immediately, so that events should be
|
||||
queued first, and be consumed by remote_wait_{ns,as} one per
|
||||
time. Other notifications can consume their events immediately,
|
||||
so queue is not needed for them. */
|
||||
static QUEUE (stop_reply_p) *stop_reply_queue;
|
||||
|
||||
static void
|
||||
stop_reply_xfree (struct stop_reply *r)
|
||||
@ -5161,51 +5144,169 @@ stop_reply_xfree (struct stop_reply *r)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remote_notif_stop_parse (struct notif_client *self, char *buf,
|
||||
struct notif_event *event)
|
||||
{
|
||||
remote_parse_stop_reply (buf, (struct stop_reply *) event);
|
||||
}
|
||||
|
||||
static void
|
||||
remote_notif_stop_ack (struct notif_client *self, char *buf,
|
||||
struct notif_event *event)
|
||||
{
|
||||
struct stop_reply *stop_reply = (struct stop_reply *) event;
|
||||
|
||||
/* acknowledge */
|
||||
putpkt ((char *) self->ack_command);
|
||||
|
||||
if (stop_reply->ws.kind == TARGET_WAITKIND_IGNORE)
|
||||
/* We got an unknown stop reply. */
|
||||
error (_("Unknown stop reply"));
|
||||
|
||||
push_stop_reply (stop_reply);
|
||||
}
|
||||
|
||||
static int
|
||||
remote_notif_stop_can_get_pending_events (struct notif_client *self)
|
||||
{
|
||||
/* We can't get pending events in remote_notif_process for
|
||||
notification stop, and we have to do this in remote_wait_ns
|
||||
instead. If we fetch all queued events from stub, remote stub
|
||||
may exit and we have no chance to process them back in
|
||||
remote_wait_ns. */
|
||||
mark_async_event_handler (remote_async_inferior_event_token);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
stop_reply_dtr (struct notif_event *event)
|
||||
{
|
||||
struct stop_reply *r = (struct stop_reply *) event;
|
||||
|
||||
VEC_free (cached_reg_t, r->regcache);
|
||||
}
|
||||
|
||||
static struct notif_event *
|
||||
remote_notif_stop_alloc_reply (void)
|
||||
{
|
||||
struct notif_event *r
|
||||
= (struct notif_event *) XMALLOC (struct stop_reply);
|
||||
|
||||
r->dtr = stop_reply_dtr;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* A client of notification Stop. */
|
||||
|
||||
struct notif_client notif_client_stop =
|
||||
{
|
||||
"Stop",
|
||||
"vStopped",
|
||||
remote_notif_stop_parse,
|
||||
remote_notif_stop_ack,
|
||||
remote_notif_stop_can_get_pending_events,
|
||||
remote_notif_stop_alloc_reply,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* A parameter to pass data in and out. */
|
||||
|
||||
struct queue_iter_param
|
||||
{
|
||||
void *input;
|
||||
struct stop_reply *output;
|
||||
};
|
||||
|
||||
/* Remove all queue elements meet the condition it checks. */
|
||||
|
||||
static int
|
||||
remote_notif_remove_all (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)
|
||||
{
|
||||
stop_reply_xfree (event);
|
||||
QUEUE_remove_elem (stop_reply_p, q, iter);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Discard all pending stop replies of inferior INF. If INF is NULL,
|
||||
discard everything. */
|
||||
|
||||
static void
|
||||
discard_pending_stop_replies (struct inferior *inf)
|
||||
{
|
||||
struct stop_reply *prev = NULL, *reply, *next;
|
||||
int i;
|
||||
struct queue_iter_param param;
|
||||
struct stop_reply *reply
|
||||
= (struct stop_reply *) notif_client_stop.pending_event;
|
||||
|
||||
/* Discard the in-flight notification. */
|
||||
if (pending_stop_reply != NULL
|
||||
if (reply != NULL
|
||||
&& (inf == NULL
|
||||
|| ptid_get_pid (pending_stop_reply->ptid) == inf->pid))
|
||||
|| ptid_get_pid (reply->ptid) == inf->pid))
|
||||
{
|
||||
stop_reply_xfree (pending_stop_reply);
|
||||
pending_stop_reply = NULL;
|
||||
stop_reply_xfree (reply);
|
||||
notif_client_stop.pending_event = NULL;
|
||||
}
|
||||
|
||||
param.input = inf;
|
||||
param.output = NULL;
|
||||
/* Discard the stop replies we have already pulled with
|
||||
vStopped. */
|
||||
for (reply = stop_reply_queue; reply; reply = next)
|
||||
{
|
||||
next = reply->next;
|
||||
if (inf == NULL
|
||||
|| ptid_get_pid (reply->ptid) == inf->pid)
|
||||
{
|
||||
if (reply == stop_reply_queue)
|
||||
stop_reply_queue = reply->next;
|
||||
else
|
||||
prev->next = reply->next;
|
||||
|
||||
stop_reply_xfree (reply);
|
||||
}
|
||||
else
|
||||
prev = reply;
|
||||
}
|
||||
QUEUE_iterate (stop_reply_p, stop_reply_queue,
|
||||
remote_notif_remove_all, ¶m);
|
||||
}
|
||||
|
||||
/* Cleanup wrapper. */
|
||||
/* A parameter to pass data in and out. */
|
||||
|
||||
static void
|
||||
do_stop_reply_xfree (void *arg)
|
||||
static int
|
||||
remote_notif_remove_once_on_match (QUEUE (stop_reply_p) *q,
|
||||
QUEUE_ITER (stop_reply_p) *iter,
|
||||
stop_reply_p event,
|
||||
void *data)
|
||||
{
|
||||
struct stop_reply *r = arg;
|
||||
struct queue_iter_param *param = data;
|
||||
ptid_t *ptid = param->input;
|
||||
|
||||
stop_reply_xfree (r);
|
||||
if (ptid_match (event->ptid, *ptid))
|
||||
{
|
||||
param->output = event;
|
||||
QUEUE_remove_elem (stop_reply_p, q, iter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Remove the first reply in 'stop_reply_queue' which matches
|
||||
PTID. */
|
||||
|
||||
static struct stop_reply *
|
||||
remote_notif_remove_queued_reply (ptid_t ptid)
|
||||
{
|
||||
struct queue_iter_param param;
|
||||
|
||||
param.input = &ptid;
|
||||
param.output = NULL;
|
||||
|
||||
QUEUE_iterate (stop_reply_p, stop_reply_queue,
|
||||
remote_notif_remove_once_on_match, ¶m);
|
||||
if (notif_debug)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"notif: discard queued event: 'Stop' in %s\n",
|
||||
target_pid_to_str (ptid));
|
||||
|
||||
return param.output;
|
||||
}
|
||||
|
||||
/* Look for a queued stop reply belonging to PTID. If one is found,
|
||||
@ -5216,29 +5317,13 @@ do_stop_reply_xfree (void *arg)
|
||||
static struct stop_reply *
|
||||
queued_stop_reply (ptid_t ptid)
|
||||
{
|
||||
struct stop_reply *it;
|
||||
struct stop_reply **it_link;
|
||||
struct stop_reply *r = remote_notif_remove_queued_reply (ptid);
|
||||
|
||||
it = stop_reply_queue;
|
||||
it_link = &stop_reply_queue;
|
||||
while (it)
|
||||
{
|
||||
if (ptid_match (it->ptid, ptid))
|
||||
{
|
||||
*it_link = it->next;
|
||||
it->next = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
it_link = &it->next;
|
||||
it = *it_link;
|
||||
}
|
||||
|
||||
if (stop_reply_queue)
|
||||
if (!QUEUE_is_empty (stop_reply_p, stop_reply_queue))
|
||||
/* There's still at least an event left. */
|
||||
mark_async_event_handler (remote_async_inferior_event_token);
|
||||
|
||||
return it;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Push a fully parsed stop reply in the stop reply queue. Since we
|
||||
@ -5248,38 +5333,37 @@ queued_stop_reply (ptid_t ptid)
|
||||
static void
|
||||
push_stop_reply (struct stop_reply *new_event)
|
||||
{
|
||||
struct stop_reply *event;
|
||||
QUEUE_enque (stop_reply_p, stop_reply_queue, new_event);
|
||||
|
||||
if (stop_reply_queue)
|
||||
{
|
||||
for (event = stop_reply_queue;
|
||||
event && event->next;
|
||||
event = event->next)
|
||||
;
|
||||
|
||||
event->next = new_event;
|
||||
}
|
||||
else
|
||||
stop_reply_queue = new_event;
|
||||
if (notif_debug)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"notif: push 'Stop' %s to queue %d\n",
|
||||
target_pid_to_str (new_event->ptid),
|
||||
QUEUE_length (stop_reply_p,
|
||||
stop_reply_queue));
|
||||
|
||||
mark_async_event_handler (remote_async_inferior_event_token);
|
||||
}
|
||||
|
||||
static int
|
||||
stop_reply_match_ptid_and_ws (QUEUE (stop_reply_p) *q,
|
||||
QUEUE_ITER (stop_reply_p) *iter,
|
||||
struct stop_reply *event,
|
||||
void *data)
|
||||
{
|
||||
ptid_t *ptid = data;
|
||||
|
||||
return !(ptid_equal (*ptid, event->ptid)
|
||||
&& event->ws.kind == TARGET_WAITKIND_STOPPED);
|
||||
}
|
||||
|
||||
/* Returns true if we have a stop reply for PTID. */
|
||||
|
||||
static int
|
||||
peek_stop_reply (ptid_t ptid)
|
||||
{
|
||||
struct stop_reply *it;
|
||||
|
||||
for (it = stop_reply_queue; it; it = it->next)
|
||||
if (ptid_equal (ptid, it->ptid))
|
||||
{
|
||||
if (it->ws.kind == TARGET_WAITKIND_STOPPED)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return !QUEUE_iterate (stop_reply_p, stop_reply_queue,
|
||||
stop_reply_match_ptid_and_ws, &ptid);
|
||||
}
|
||||
|
||||
/* Parse the stop reply in BUF. Either the function succeeds, and the
|
||||
@ -5495,13 +5579,14 @@ Packet: '%s'\n"),
|
||||
error (_("No process or thread specified in stop reply: %s"), buf);
|
||||
}
|
||||
|
||||
/* When the stub wants to tell GDB about a new stop reply, it sends a
|
||||
stop notification (%Stop). Those can come it at any time, hence,
|
||||
we have to make sure that any pending putpkt/getpkt sequence we're
|
||||
making is finished, before querying the stub for more events with
|
||||
vStopped. E.g., if we started a vStopped sequence immediatelly
|
||||
upon receiving the %Stop notification, something like this could
|
||||
happen:
|
||||
/* When the stub wants to tell GDB about a new notification reply, it
|
||||
sends a notification (%Stop, for example). Those can come it at
|
||||
any time, hence, we have to make sure that any pending
|
||||
putpkt/getpkt sequence we're making is finished, before querying
|
||||
the stub for more events with the corresponding ack command
|
||||
(vStopped, for example). E.g., if we started a vStopped sequence
|
||||
immediately upon receiving the notification, something like this
|
||||
could happen:
|
||||
|
||||
1.1) --> Hg 1
|
||||
1.2) <-- OK
|
||||
@ -5536,19 +5621,21 @@ Packet: '%s'\n"),
|
||||
2.9) --> OK
|
||||
*/
|
||||
|
||||
static void
|
||||
remote_get_pending_stop_replies (void)
|
||||
void
|
||||
remote_notif_get_pending_events (struct notif_client *nc)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
|
||||
if (pending_stop_reply)
|
||||
if (nc->pending_event)
|
||||
{
|
||||
/* acknowledge */
|
||||
putpkt ("vStopped");
|
||||
if (notif_debug)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"notif: process: '%s' ack pending event\n",
|
||||
nc->name);
|
||||
|
||||
/* Now we can rely on it. */
|
||||
push_stop_reply (pending_stop_reply);
|
||||
pending_stop_reply = NULL;
|
||||
/* acknowledge */
|
||||
nc->ack (nc, rs->buf, nc->pending_event);
|
||||
nc->pending_event = NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -5556,31 +5643,18 @@ remote_get_pending_stop_replies (void)
|
||||
if (strcmp (rs->buf, "OK") == 0)
|
||||
break;
|
||||
else
|
||||
{
|
||||
struct cleanup *old_chain;
|
||||
struct stop_reply *stop_reply = stop_reply_xmalloc ();
|
||||
|
||||
old_chain = make_cleanup (do_stop_reply_xfree, stop_reply);
|
||||
remote_parse_stop_reply (rs->buf, stop_reply);
|
||||
|
||||
/* acknowledge */
|
||||
putpkt ("vStopped");
|
||||
|
||||
if (stop_reply->ws.kind != TARGET_WAITKIND_IGNORE)
|
||||
{
|
||||
/* Now we can rely on it. */
|
||||
discard_cleanups (old_chain);
|
||||
push_stop_reply (stop_reply);
|
||||
}
|
||||
else
|
||||
/* We got an unknown stop reply. */
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
remote_notif_ack (nc, rs->buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (notif_debug)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"notif: process: '%s' no pending reply\n",
|
||||
nc->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called when it is decided that STOP_REPLY holds the info of the
|
||||
event that is to be returned to the core. This function always
|
||||
destroys STOP_REPLY. */
|
||||
@ -5664,8 +5738,8 @@ 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 (pending_stop_reply != NULL)
|
||||
remote_get_pending_stop_replies ();
|
||||
if (notif_client_stop.pending_event != NULL)
|
||||
remote_notif_get_pending_events (¬if_client_stop);
|
||||
|
||||
/* If indeed we noticed a stop reply, we're done. */
|
||||
stop_reply = queued_stop_reply (ptid);
|
||||
@ -5712,6 +5786,7 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
|
||||
else
|
||||
{
|
||||
int ret;
|
||||
int is_notif;
|
||||
|
||||
if (!target_is_async_p ())
|
||||
{
|
||||
@ -5729,7 +5804,14 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
|
||||
_never_ wait for ever -> test on target_is_async_p().
|
||||
However, before we do that we need to ensure that the caller
|
||||
knows how to take the target into/out of async mode. */
|
||||
ret = getpkt_sane (&rs->buf, &rs->buf_size, wait_forever_enabled_p);
|
||||
ret = getpkt_or_notif_sane (&rs->buf, &rs->buf_size,
|
||||
wait_forever_enabled_p, &is_notif);
|
||||
|
||||
/* GDB gets a notification. Return to core as this event is
|
||||
not interesting. */
|
||||
if (ret != -1 && is_notif)
|
||||
return minus_one_ptid;
|
||||
|
||||
if (!target_is_async_p ())
|
||||
signal (SIGINT, ofunc);
|
||||
}
|
||||
@ -5761,13 +5843,10 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
|
||||
break;
|
||||
case 'T': case 'S': case 'X': case 'W':
|
||||
{
|
||||
struct stop_reply *stop_reply;
|
||||
struct cleanup *old_chain;
|
||||
struct stop_reply *stop_reply
|
||||
= (struct stop_reply *) remote_notif_parse (¬if_client_stop,
|
||||
rs->buf);
|
||||
|
||||
stop_reply = stop_reply_xmalloc ();
|
||||
old_chain = make_cleanup (do_stop_reply_xfree, stop_reply);
|
||||
remote_parse_stop_reply (buf, stop_reply);
|
||||
discard_cleanups (old_chain);
|
||||
event_ptid = process_stop_reply (stop_reply, status);
|
||||
break;
|
||||
}
|
||||
@ -5848,7 +5927,7 @@ remote_wait (struct target_ops *ops,
|
||||
{
|
||||
/* If there are are events left in the queue tell the event loop
|
||||
to return here. */
|
||||
if (stop_reply_queue)
|
||||
if (!QUEUE_is_empty (stop_reply_p, stop_reply_queue))
|
||||
mark_async_event_handler (remote_async_inferior_event_token);
|
||||
}
|
||||
|
||||
@ -6743,52 +6822,6 @@ remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
|
||||
/* Return what we have. Let higher layers handle partial reads. */
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* Remote notification handler. */
|
||||
|
||||
static void
|
||||
handle_notification (char *buf)
|
||||
{
|
||||
if (strncmp (buf, "Stop:", 5) == 0)
|
||||
{
|
||||
if (pending_stop_reply)
|
||||
{
|
||||
/* We've already parsed the in-flight stop-reply, but the
|
||||
stub for some reason thought we didn't, possibly due to
|
||||
timeout on its side. Just ignore it. */
|
||||
if (remote_debug)
|
||||
fprintf_unfiltered (gdb_stdlog, "ignoring resent notification\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
struct cleanup *old_chain;
|
||||
struct stop_reply *reply = stop_reply_xmalloc ();
|
||||
|
||||
old_chain = make_cleanup (do_stop_reply_xfree, reply);
|
||||
|
||||
remote_parse_stop_reply (buf + 5, reply);
|
||||
|
||||
discard_cleanups (old_chain);
|
||||
|
||||
/* Be careful to only set it after parsing, since an error
|
||||
may be thrown then. */
|
||||
pending_stop_reply = reply;
|
||||
|
||||
/* Notify the event loop there's a stop reply to acknowledge
|
||||
and that there may be more events to fetch. */
|
||||
mark_async_event_handler (remote_async_get_pending_events_token);
|
||||
|
||||
if (remote_debug)
|
||||
fprintf_unfiltered (gdb_stdlog, "stop notification captured\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We ignore notifications we don't recognize, for compatibility
|
||||
with newer stubs. */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read or write LEN bytes from inferior memory at MEMADDR,
|
||||
@ -11196,12 +11229,6 @@ remote_async_inferior_event_handler (gdb_client_data data)
|
||||
inferior_event_handler (INF_REG_EVENT, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
remote_async_get_pending_events_handler (gdb_client_data data)
|
||||
{
|
||||
remote_get_pending_stop_replies ();
|
||||
}
|
||||
|
||||
static void
|
||||
remote_async (void (*callback) (enum inferior_event_type event_type,
|
||||
void *context), void *context)
|
||||
@ -11357,6 +11384,7 @@ _initialize_remote (void)
|
||||
init_remote_threadtests ();
|
||||
#endif
|
||||
|
||||
stop_reply_queue = QUEUE_alloc (stop_reply_p, stop_reply_xfree);
|
||||
/* set/show remote ... */
|
||||
|
||||
add_prefix_cmd ("remote", class_maintenance, set_remote_cmd, _("\
|
||||
|
@ -19,6 +19,8 @@
|
||||
#ifndef REMOTE_H
|
||||
#define REMOTE_H
|
||||
|
||||
#include "remote-notif.h"
|
||||
|
||||
struct target_desc;
|
||||
|
||||
/* Read a packet from the remote machine, with error checking, and
|
||||
@ -59,4 +61,5 @@ extern int remote_register_number_and_offset (struct gdbarch *gdbarch,
|
||||
int regnum, int *pnum,
|
||||
int *poffset);
|
||||
|
||||
extern void remote_notif_get_pending_events (struct notif_client *np);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user