public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] scox/globalstate: Support multiple clients that use upstream syscall support.
@ 2016-02-08 15:40 scox
0 siblings, 0 replies; only message in thread
From: scox @ 2016-02-08 15:40 UTC (permalink / raw)
To: archer-commits
The branch, scox/globalstate has been updated
via c94dca1a4db81df5753f2ec7c42b416920908897 (commit)
from 8cb7f5b73460dd9ed08cc78a382d60e52c8f2781 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email.
- Log -----------------------------------------------------------------
commit c94dca1a4db81df5753f2ec7c42b416920908897
Author: Stan Cox <scox@redhat.com>
Date: Mon Feb 8 10:38:17 2016 -0500
Support multiple clients that use upstream syscall support.
* server.c (waitkind_str): New
(set_client_state): Copy client state for multiple client case.
(attached_to_same_proc): New
(resolve_waiter): Handle exited case.
(setup_multiplexing): Refactor.
(do_multiplexing): Refactor. Handle syscall case.
* server.h (catch_syscalls, last_cont_ptid, last_cont_waitstatus): New.
-----------------------------------------------------------------------
Summary of changes:
gdb/gdbserver/ChangeLog | 10 +
gdb/gdbserver/nto-low.c | 1 +
gdb/gdbserver/server.c | 466 +++++++++++++++++++----------
gdb/gdbserver/server.h | 3 +
gdb/gdbserver/spu-low.c | 1 +
gdb/gdbserver/win32-low.c | 1 +
gdb/remote.c | 2 +-
gdb/testsuite/ChangeLog | 4 +
gdb/testsuite/gdb.server/multi-client.exp | 117 +++++++-
9 files changed, 425 insertions(+), 180 deletions(-)
First 500 lines of diff:
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 5eb6384..88d55fd 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,13 @@
+2016-02-06 Stan Cox <scox@redhat.com>
+
+ * server.c (waitkind_str): New
+ (set_client_state): Copy client state for multiple client case.
+ (attached_to_same_proc): New
+ (resolve_waiter): Handle exited case.
+ (setup_multiplexing): Refactor.
+ (do_multiplexing): Refactor. Handle syscall case.
+ * server.h (catch_syscalls, last_cont_ptid, last_cont_waitstatus): New.
+
2016-01-14 Yao Qi <yao.qi@linaro.org>
* linux-aarch32-low.c (thumb2_breakpoint): Make it static.
diff --git a/gdb/gdbserver/nto-low.c b/gdb/gdbserver/nto-low.c
index ce3b8e4..3e945a5 100644
--- a/gdb/gdbserver/nto-low.c
+++ b/gdb/gdbserver/nto-low.c
@@ -979,6 +979,7 @@ static struct target_ops nto_target_ops = {
NULL, /* core_of_thread */
NULL, /* read_loadmap */
NULL, /* process_qsupported */
+ NULL, /* supports_catch_syscall */
NULL, /* supports_tracepoints */
NULL, /* read_pc */
NULL, /* write_pc */
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index dc9977c..378b174 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -86,8 +86,9 @@ static struct client_states client_states;
static void handle_status (char *);
enum pending_types {none_pending, pending_waitee, pending_cont_waiter,pending_step_waiter,pending_stop};
-char *pending_types_str[] = {"not waiting","waitee","waiter","step waiter","stop"};
+char *pending_types_str[] = {"not-waiting","waitee","waiter","step-waiter","stop"};
char *packet_types_str[] = {"other", "vContc", "vConts","vContt","vStopped","vRun", "vAttach"};
+char *waitkind_str[] = {"exited", "stopped", "signalled", "loaded", "forked", "vforked", "execed", "vfork-done", "syscall-entry", "syscall-exit", "spurious", "ignore", "no-history", "not-resumed", "thread-created", "thread-exited", ""};
/* Return the current client state */
@@ -142,33 +143,32 @@ set_client_state (gdb_fildes_t fd)
}
/* add client state S for fd F */
- client_states.current_cs = XCNEW (client_state);
- *client_states.current_cs = *csidx;
- client_states.current_cs->ss = XCNEW (server_state);
- *client_states.current_cs->ss = *csidx->ss;
- cs = client_states.current_cs;
+ cs = XCNEW (client_state);
+ *(cs) = *(csidx);
+ cs->ss = XCNEW (server_state);
+ *(cs->ss) = *(csidx->ss);
+ cs->file_desc = fd;
cs->packet_type = other_packet;
cs->last_packet_type = other_packet;
cs->pending = none_pending;
+ cs->in_buffer_ = NULL;
+ cs->own_buffer_ = xmalloc (PBUFSIZ + 1);
cs->client_breakpoints = NULL;
- in_buffer = NULL;
- wrapper_argv = NULL;
- get_client_state()->ss->attach_count_ = 0;
- cont_thread = null_ptid;
- general_thread = null_ptid;
- signal_pid = 0;
- last_ptid = null_ptid;
- last_status.kind = TARGET_WAITKIND_IGNORE;
- current_thread = NULL;
- all_processes.head = NULL;
- all_processes.tail = NULL;
- all_threads.head = NULL;
- all_threads.tail = NULL;
- client_states.current_cs->file_desc = fd;
- own_buffer = xmalloc (PBUFSIZ + 1);
+ client_states.current_cs = cs;
+ cs->ss->attach_count_ = 0;
+ cs->ss->cont_thread_ = null_ptid;
+ cs->ss->general_thread_ = null_ptid;
+ cs->ss->signal_pid_ = 0;
+ cs->ss->last_ptid_ = null_ptid;
+ cs->ss->last_status_.kind = TARGET_WAITKIND_IGNORE;
+ cs->ss->current_thread_ = NULL;
+ cs->ss->all_processes_.head = NULL;
+ cs->ss->all_processes_.tail = NULL;
+ cs->ss->all_threads_.head = NULL;
+ cs->ss->all_threads_.tail = NULL;
client_states.current_fd = fd;
csidx->next = client_states.current_cs;
- return client_states.current_cs;
+ return cs;
}
/* Add breakpoint ADDR to the per client breakpoint list */
@@ -236,6 +236,14 @@ delete_client_breakpoint (CORE_ADDR addr)
}
+static int attached_to_same_proc (client_state *cs1, client_state *cs2)
+{
+ return cs1->file_desc != -1 && cs2->file_desc != -1
+ && cs1 != cs2 && cs1->ss == cs2->ss;
+}
+
+
+
/* Free client state CS; considering the corresponding server state */
static void free_client_state (client_state *cs)
@@ -244,7 +252,8 @@ static void free_client_state (client_state *cs)
client_state *csi;
for (csi = client_states.first; csi != NULL; csi = csi->next)
{
- if (ptid_equal (csi->ss->general_thread_, null_ptid) && csi != cs && csi->ss == cs->ss)
+ if (ptid_equal (csi->ss->general_thread_, null_ptid)
+ && attached_to_same_proc (cs, csi))
break;
}
delete_client_breakpoint (0);
@@ -272,10 +281,17 @@ dump_client_state (const char *function, const char *comment)
debug_printf ("***Begin Dumping client state from %s %s\n", function, comment);
for (cs = client_states.first; cs != NULL; cs = cs->next)
{
+ char *last_status_kind;
client_states.current_cs = cs;
+
if (cs->file_desc == -1)
continue;
- debug_printf ("%d %#lx(%d)/%#lx/%#lx #=%d %s %s %s\n",
+
+ if (cs->ss->last_status_.kind < (sizeof (waitkind_str) / sizeof (void*)))
+ last_status_kind = waitkind_str[cs->ss->last_status_.kind];
+ else
+ last_status_kind = "";
+ debug_printf ("%d %#lx(%d)/%#lx/%#lx #=%d %s %s %s %s\n",
cs->file_desc,
(long unsigned)general_thread.pid,
(int)general_thread.pid,
@@ -284,7 +300,8 @@ dump_client_state (const char *function, const char *comment)
cs->ss->attach_count_,
packet_types_str[cs->packet_type],
packet_types_str[cs->last_packet_type],
- pending_types_str[cs->pending]);
+ pending_types_str[cs->pending],
+ last_status_kind);
}
debug_printf ("***End Dumping client state\n");
client_states.current_cs = save_cs;
@@ -419,20 +436,25 @@ get_packet_type (client_state *cs)
static int queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg);
-/* Belatedly reply to last CS previously received and waited on packet */
+/* Belatedly reply to client CS, which is waiting on a packet reply. */
void
-resolve_waiter (client_state *cs)
+resolve_waiter (client_state *cs, client_state *waitee_cs)
{
enum packet_types this_packet_type = (cs->packet_type) ? cs->packet_type : cs->last_packet_type;
- if (debug_threads)
- debug_printf ("%s:%d fd=%d %s\n", __FUNCTION__, __LINE__, cs->file_desc, packet_types_str[this_packet_type]);
-
switch (this_packet_type)
{
case vContc:
{
+ strcpy (own_buffer, "?");
+ if (debug_threads)
+ {
+ prepare_resume_reply (own_buffer, cs->last_cont_ptid, &cs->last_cont_waitstatus);
+ debug_printf ("%s:%d %d %#lx %#lx %s %s prepare_resume_reply=%s\n", __FUNCTION__, __LINE__,
+ cs->file_desc, (unsigned long)cs->last_cont_ptid.pid, (unsigned long)cs->ss->last_ptid_.pid,
+ waitkind_str[cs->last_cont_waitstatus.kind], waitkind_str[cs->ss->last_status_.kind], own_buffer);
+ }
if (non_stop)
{
if (last_status.kind != TARGET_WAITKIND_EXITED
@@ -456,13 +478,26 @@ resolve_waiter (client_state *cs)
notif_write_event (¬if_stop, notif_buf);
}
}
- else if (last_status.kind != TARGET_WAITKIND_EXITED)
+ else if (last_status.kind != TARGET_WAITKIND_EXITED
+ && cs->last_cont_ptid.pid == cs->ss->last_ptid_.pid)
{
/* reply to vContc with a status */
strcpy (own_buffer, "?");
handle_status (own_buffer);
putpkt (own_buffer);
}
+ else if (last_status.kind == TARGET_WAITKIND_EXITED)
+ {
+ /* Is this the same process we are waiting on? */
+ if (cs->last_cont_ptid.pid != last_ptid.pid)
+ {
+ prepare_resume_reply (own_buffer, cs->last_cont_ptid,
+ &cs->last_cont_waitstatus);
+ putpkt (own_buffer);
+ }
+ else
+ putpkt (waitee_cs->own_buffer_);
+ }
break;
}
case vConts:
@@ -514,114 +549,153 @@ resolve_waiter (client_state *cs)
/* Determine the state of client CS with respect to other clients connected to the same server process */
static int
-setup_multiplexing (client_state *cs, char *ch)
+setup_multiplexing (client_state *current_cs)
{
- client_state *csidx = NULL;
+ /***
+ If we have two independent clients 4 and 7 and 4 is the current
+ client with a vConts packet then we change both client's state
+ BEFORE
+ packet_type last_packet_type pending last_status_.kind
+ 4 vConts vConts not-waiting stopped
+ 7 other vAttach not-waiting stopped
+ AFTER
+ 4 vConts vConts step-waiter stopped
+ 7 other vAttach waitee stopped
+
+ If we have two dependent clients 4 and 7 and 4 is the current client with a
+ vContc packet then we change nothing here. process_serial_event will handle
+ the vContc then do_multiplexing will decide to either continue with client 4
+ or wakeup and continue with client 7.
+ 4 vContc vConts waitee stopped
+ 7 vContc vContc waiter stopped
+ ***/
+
+ client_state *same_pid_cs = NULL;
dump_client_state (__FUNCTION__, "");
- cs->attached_to_client = 1;
+ current_cs->attached_to_client = 1;
- for (csidx = client_states.first; csidx != NULL; csidx = csidx->next)
+ for (same_pid_cs = client_states.first;
+ same_pid_cs != NULL;
+ same_pid_cs = same_pid_cs->next)
{
- /* another client is attached to the cs process */
- if (csidx->file_desc != -1 && csidx != cs && cs->ss == csidx->ss)
+ if (! attached_to_same_proc (current_cs, same_pid_cs))
+ continue;
+ switch (same_pid_cs->pending)
{
- /* found a client that has nothing pending */
- if (!csidx->pending)
+ case none_pending:
+ /* found a client that has nothing pending */
+ /* The current_cs vContc will wait; found same_pid_cs will proceed */
+ switch (current_cs->packet_type)
{
- /* The cs vContc will wait; found csidx will proceed */
- if (cs->packet_type == vContc)
+ case vContc:
+ if (current_cs->last_packet_type != vRun)
{
- if (cs->last_packet_type != vRun)
- {
- cs->pending = pending_cont_waiter;
- csidx->pending = pending_waitee;
- }
+ current_cs->pending = pending_cont_waiter;
+ same_pid_cs->pending = pending_waitee;
}
- /* TODO else if (cs->packet_type == vContt) */
- else if (cs->packet_type == vConts)
+ break;
+ /* TODO else if (current_cs->packet_type == vContt) */
+ case vConts:
+ if (same_pid_cs->last_packet_type != vContt)
{
- if (csidx->last_packet_type != vContt)
- {
- cs->pending = pending_step_waiter;
- csidx->pending = pending_waitee;
- }
+ current_cs->pending = pending_step_waiter;
+ same_pid_cs->pending = pending_waitee;
}
}
- /* Current client is continuing and found another waiter client */
- else if (csidx->pending == pending_cont_waiter
- && cs->packet_type == vContc)
+ break;
+ case pending_cont_waiter:
+ switch (current_cs->packet_type)
{
- client_state *csi;
- int waitee_count = 0;
+ /* Current client is continuing and found another waiter client */
+ case vContc:
+ {
+ client_state *csi;
+ int waitee_count = 0;
- /* Does the client group have a waitee? */
- for (csi = client_states.first->next; csi != NULL; csi = csi->next)
- {
- if (csi->ss == cs->ss && csi->pending == pending_waitee
- && csi->file_desc != cs->file_desc)
- waitee_count = 1;
- }
-
- /* Don't want to deadlock on everyone waiting */
- if (cs->pending == pending_waitee && waitee_count > 0)
- cs->pending = pending_cont_waiter;
+ /* Does the client group have a waitee? */
+ for (csi = client_states.first->next; csi != NULL; csi = csi->next)
+ {
+ if (current_cs != csi && csi->pending == pending_waitee
+ && attached_to_same_proc (current_cs, csi))
+ waitee_count = 1;
+ }
+
+ dump_client_state (__FUNCTION__, "waitee/waiter switch");
+ if (debug_threads)
+ debug_printf ("waitee count=%d\n", waitee_count);
+
+ /* Don't want to deadlock on everyone waiting */
+ if (current_cs->pending == pending_waitee && waitee_count > 0)
+ current_cs->pending = pending_cont_waiter;
+ }
}
}
- }
+ } /* for same_pid_cs */
+
- /* Current client is continuing and waiting so just return.
- The packet will be replied to later in do_multiplexing */
- if (cs->pending == pending_cont_waiter
- || cs->pending == pending_step_waiter
- || cs->pending == pending_stop)
+ switch (current_cs->pending)
{
- if (cs->last_packet_type != vRun
- && cs->last_packet_type != vStopped
- && cs->ss->last_status_exited != have_exit)
+ case pending_cont_waiter:
+ case pending_step_waiter:
+ case pending_stop:
+
+ switch (current_cs->last_packet_type)
{
- dump_client_state (__FUNCTION__, "return 0");
- return 0; /* Reply to packet later */
+ case vRun:
+ case vStopped:
+ break;
+ default:
+ /* Current client is continuing and waiting so don't reply to this
+ packet now; it will be replied to later in do_multiplexing */
+ if (current_cs->ss->last_status_exited != have_exit)
+ {
+ dump_client_state (__FUNCTION__, "return 0");
+ current_cs->last_cont_ptid = current_cs->ss->general_thread_;
+ current_cs->last_cont_waitstatus = current_cs->ss->last_status_;
+ return 0; /* Reply to packet later */
+ }
}
+ default:
+ dump_client_state (__FUNCTION__, "return 1");
+ return 1; /* Reply to packet now */
}
- dump_client_state (__FUNCTION__, "return 1");
- return 1; /* Reply to packet now */
}
static void
-notify_clients (client_state *waitee_cs)
+notify_clients (client_state *current_cs)
{
- client_state *csidx = NULL;
+ client_state *same_pid_cs = NULL;
- if (! (waitee_cs->pending == pending_waitee
- && waitee_cs->last_packet_type == vStopped
- && waitee_cs->ss->last_status_exited == have_exit))
+ if (! (current_cs->pending == pending_waitee
+ && current_cs->last_packet_type == vStopped
+ && current_cs->ss->last_status_exited == have_exit))
return;
- for (csidx = client_states.first; csidx != NULL; csidx = csidx->next)
+ for (same_pid_cs = client_states.first;
+ same_pid_cs != NULL;
+ same_pid_cs = same_pid_cs->next)
{
+ char *out_buf = alloca (64);
+
/* Insure another client is attached to the cs process */
- if (csidx->file_desc == -1 ||csidx->file_desc == waitee_cs->file_desc
- || waitee_cs->ss != csidx->ss)
+ if (! attached_to_same_proc (current_cs, same_pid_cs))
continue;
- {
- char *out_buf = alloca (64);
-
- csidx->ss->last_status_exited = sent_exit;
- set_client_state (csidx->file_desc);
- csidx->pending = none_pending;
- strcpy (out_buf, "OK");
- putpkt (out_buf);
- // TODO Use a better method to create this: Stop:W0;process:29e3
- sprintf (out_buf, "Stop:W0;process:%x", (unsigned)ptid_get_pid (general_thread));
- putpkt_notif (out_buf);
- if (debug_threads)
- debug_printf ("%s:%d %s\n", __FUNCTION__, __LINE__, out_buf);
- }
- }
- set_client_state (waitee_cs->file_desc);
+
+ same_pid_cs->ss->last_status_exited = sent_exit;
+ set_client_state (same_pid_cs->file_desc);
+ same_pid_cs->pending = none_pending;
+ strcpy (out_buf, "OK");
+ putpkt (out_buf);
+ // TODO Use a better method to create this: Stop:W0;process:29e3
+ sprintf (out_buf, "Stop:W0;process:%x", (unsigned)ptid_get_pid (general_thread));
+ putpkt_notif (out_buf);
+ if (debug_threads)
+ debug_printf ("%s:%d %s\n", __FUNCTION__, __LINE__, out_buf);
+ }
+ set_client_state (current_cs->file_desc);
return;
}
@@ -629,58 +703,126 @@ notify_clients (client_state *waitee_cs)
/* Resolve the state of client WAITEE_CS with respect to other clients connected to the same server process */
static int
-do_multiplexing (client_state *waitee_cs, char ch)
+do_multiplexing (client_state *current_cs, char ch)
{
- client_state *csidx = NULL;
+ /***
+ If we have two dependent clients 4 and 7 and 4 is the current client with a
+ vContc packet then if the handling of vContc resulted in hitting a client 7
+ breakpoint then we wakeup client 7.
+
+ BEFORE
+ packet_type last_packet_type pending last_status_.kind
+ 4 vContc vConts waitee stopped
+ 7 vContc vContc waiter stopped
+ AFTER
+ 4 vContc vConts waiter stopped
+ 7 vContc vContc waitee stopped
+
+ Otherwise we continue with client 4.
+ 4 vContc vConts waitee stopped
+ 7 vContc vContc waiter stopped
+ ***/
+
+ /*
+ syscall halt 3 current
+ 3 waitee 7 waiter
+ 7 syscall? wake 7 wait 3 else continue 3
+ syscall halt 7 current
+ 3 waiter 7 waitee
+ continue 7
+ stopped halt 3 current
+ 3 waitee 7 waiter
+ continue 3
+ stopped halt 7 current
+ 3 waiter 7 waitee
+ 3 break? wake 3 wait 7 else continue 7
+ current_cs.packet_type == vContc and current_cs.catch_syscalls
+current_cs.kind ==
+ and
+ */
+
+ client_state *same_pid_cs = NULL;
int make_waitee_a_waiter = 0;
- if (waitee_cs->last_packet_type == vAttach && waitee_cs->packet_type == vContt)
+ switch (current_cs->packet_type)
{
- resolve_waiter (waitee_cs);
- dump_client_state (__FUNCTION__, "resolved vContt");
- return 0;
+ case other_packet:
+ break;
+ case vContt:
+ if (current_cs->last_packet_type == vAttach)
+ {
+ resolve_waiter (current_cs, NULL);
hooks/post-receive
--
Repository for Project Archer.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2016-02-08 15:40 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-08 15:40 [SCM] scox/globalstate: Support multiple clients that use upstream syscall support scox
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).