public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] scox/globalstate: Improve non-stop multi client handling.
@ 2016-01-04 15:32 scox
0 siblings, 0 replies; only message in thread
From: scox @ 2016-01-04 15:32 UTC (permalink / raw)
To: archer-commits
The branch, scox/globalstate has been updated
via 86f94295634f71220c6e6c4ac987406be3014e59 (commit)
from 0bee029c99922ca26020016079c299fe2b01df59 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email.
- Log -----------------------------------------------------------------
commit 86f94295634f71220c6e6c4ac987406be3014e59
Author: Stan Cox <scox@redhat.com>
Date: Sun Jan 3 21:37:56 2016 -0500
Improve non-stop multi client handling.
gdbserver/ChangeLog:
* server.c (add_client_by_pid): Add non_stop, multi_process_, and run_once_.
(have_multiple_clients): Add vCont;t and vStopped and vAttach.
(resolve_waiter): Add vContc, non_stop, and vContt
(setup_multiplexing): Add vContt and pending_stop for non_stop.
(notify_clients): New to send stop notification to multiple clients.
(do_multiplexing): Call notify_clients. Make vContt aware.
(handle_v_attach): Make non_stop aware.
* server.h (last_status_exited, vContt, vStopped, vAttach)
(exit_types): New.
* mem-break.c (has_client_breakpoint_at): Simplify. Improve
debug_threads output.
testsuite/ChangeLog:
* gdb.server/multi-client.exp: Add non-stop test.
-----------------------------------------------------------------------
Summary of changes:
gdb/gdbserver/ChangeLog | 16 ++
gdb/gdbserver/event-loop.c | 2 +-
gdb/gdbserver/mem-break.c | 30 ++--
gdb/gdbserver/server.c | 292 ++++++++++++++++++++---------
gdb/gdbserver/server.h | 9 +-
gdb/testsuite/ChangeLog | 4 +
gdb/testsuite/gdb.server/multi-client.exp | 141 ++++++++-------
7 files changed, 321 insertions(+), 173 deletions(-)
First 500 lines of diff:
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 3ac724f..d9c99e4 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,19 @@
+2016-01-03 Stan Cox <scox@redhat.com>
+
+ * server.c (add_client_by_pid): Add non_stop, multi_process_, and run_once_.
+ (have_multiple_clients): Add vCont;t and vStopped and vAttach.
+ (resolve_waiter): Add vContc, non_stop, and vContt
+ (setup_multiplexing): Add vContt and pending_stop for non_stop.
+ (notify_clients): New to send stop notification to multiple clients.
+ (do_multiplexing): Call notify_clients. Make vContt aware.
+ (handle_v_attach): Make non_stop aware.
+
+ * server.h (last_status_exited, vContt, vStopped, vAttach)
+ (exit_types): New.
+
+ * mem-break.c (has_client_breakpoint_at): Simplify. Improve
+ debug_threads output.
+
2015-11-04 Stan Cox <scox@redhat.com>
* server.h (client_state): Remove executable and all its references.
diff --git a/gdb/gdbserver/event-loop.c b/gdb/gdbserver/event-loop.c
index 1679464..00feb4f 100644
--- a/gdb/gdbserver/event-loop.c
+++ b/gdb/gdbserver/event-loop.c
@@ -428,7 +428,7 @@ handle_file_event (gdb_fildes_t event_file_desc)
if (mask != 0)
{
/* Don't change client states if we have multiple clients */
- if (have_multiple_clients (file_ptr->fd) || ptid_equal (general_thread, null_ptid))
+ if (have_multiple_clients (file_ptr->fd))
set_client_state (file_ptr->fd);
if ((*file_ptr->proc) (file_ptr->error,
file_ptr->client_data) < 0)
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index 138e8e0..898d370 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -301,23 +301,25 @@ has_client_breakpoint_at (CORE_ADDR addr)
client_state *cs = get_client_state ();
struct client_breakpoint *cb;
- if (debug_threads)
- debug_printf ("%s:%d fd=%d addr=%#lx\n", __FUNCTION__, __LINE__, cs->file_desc, (long unsigned)addr);
+
for (cb = cs->client_breakpoints; cb != NULL; cb = cb->next)
- if (debug_threads)
- debug_printf ("%s:%d %d breakpoint at %#lx\n", __FUNCTION__, __LINE__, cs->file_desc, (long unsigned)cb->addr);
+ {
+ // TODO improve this; pc might be one insn ahead of break.
+ if (addr >= cb->addr && addr <= cb->addr + 8)
+ {
+ if (debug_threads)
+ debug_printf ("%s:%d fd=%d return true at %#lx\n",
+ __FUNCTION__, __LINE__, cs->file_desc, (long unsigned)cb->addr);
+ return 1;
+ }
+ }
- // for (bp = proc->raw_breakpoints; bp != NULL; bp = bp->next)
+ if (debug_threads)
{
- // if (addr >= bp->pc && addr <= bp->pc + 8 && cs->ss->last_status.kind == TARGET_WAITKIND_STOPPED
- // && cs->ss->last_status.value.sig == GDB_SIGNAL_TRAP)
- for (cb = cs->client_breakpoints; cb != NULL; cb = cb->next)
- // TODO improve this; pc might be one insn ahead of break.
- {
- debug_printf ("%s:%d addr=%#lx pb->pc %#lx in range? %d\n", __FUNCTION__, __LINE__, (long unsigned) addr, (long unsigned)cb->addr, addr >= cb->addr && addr <= cb->addr + 8);
- if (addr >= cb->addr && addr <= cb->addr + 8)
- return 1;
- }
+ debug_printf ("%s:%d fd=%d addr=%#lx breakpoints at:\n", __FUNCTION__, __LINE__, cs->file_desc, (long unsigned)addr);
+ for (cb = cs->client_breakpoints; cb != NULL; cb = cb->next)
+ debug_printf (" %#lx", (long unsigned)cb->addr);
+ debug_printf ("\n");
}
return 0;
}
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index cb552ec..64bf851 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -85,9 +85,9 @@ static struct client_states client_states;
static void handle_status (char *);
-enum pending_types {none_pending=0, pending_waitee=1, pending_cont_waiter=2,pending_step_waiter=3};
-char *pending_types_str[] = {"not waiting","waitee","waiter","step waiter"};
-char *packet_types_str[] = {"other", "vContc", "vConts","vRun"};
+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 *packet_types_str[] = {"other", "vContc", "vConts","vContt","vStopped","vRun", "vAttach"};
/* Return the current client state */
@@ -148,6 +148,8 @@ set_client_state (gdb_fildes_t fd)
*client_states.current_cs->ss = *csidx->ss;
cs = client_states.current_cs;
cs->packet_type = other_packet;
+ cs->last_packet_type = other_packet;
+ cs->pending = none_pending;
cs->client_breakpoints = NULL;
in_buffer = NULL;
wrapper_argv = NULL;
@@ -259,7 +261,7 @@ static void free_client_state (client_state *cs)
/* Dump the client state list for debugging purposes */
void
-dump_client_state (const char *comment)
+dump_client_state (const char *function, const char *comment)
{
client_state *save_cs = get_client_state();
client_state *cs;
@@ -267,10 +269,12 @@ dump_client_state (const char *comment)
if (! debug_threads)
return;
- debug_printf ("***Begin Dumping client state from %s\n", comment);
+ debug_printf ("***Begin Dumping client state from %s %s\n", function, comment);
for (cs = client_states.first; cs != NULL; cs = cs->next)
{
client_states.current_cs = cs;
+ if (cs->file_desc == -1)
+ continue;
debug_printf ("%d %#lx(%d)/%#lx/%#lx #=%d %s %s %s\n",
cs->file_desc,
(long unsigned)general_thread.pid,
@@ -282,7 +286,7 @@ dump_client_state (const char *comment)
packet_types_str[cs->last_packet_type],
pending_types_str[cs->pending]);
}
- debug_printf ("***End Dumping client state from %s\n", comment);
+ debug_printf ("***End Dumping client state\n");
client_states.current_cs = save_cs;
}
@@ -294,15 +298,16 @@ add_client_by_pid (int pid)
{
client_state *cs = get_client_state();
client_state *matched_cs;
-
for (matched_cs = client_states.first; matched_cs != NULL; matched_cs = matched_cs->next)
{
if (cs != matched_cs && matched_cs->ss->general_thread_.pid == pid)
{
- XDELETE (cs->ss);
/* reuse the matched server state */
cs->ss = matched_cs->ss;
cs->ss->attach_count_ += 1;
+ cs->non_stop_ = matched_cs->non_stop_;
+ cs->multi_process_ = matched_cs->multi_process_;
+ cs->run_once_ = matched_cs->run_once_;
return cs;
}
}
@@ -331,7 +336,7 @@ int
have_multiple_clients (gdb_fildes_t fd)
{
client_state *cs;
- dump_client_state(__FUNCTION__);
+ dump_client_state(__FUNCTION__, "");
for (cs = client_states.first; cs != NULL; cs = cs->next)
if (cs->file_desc == fd)
@@ -387,23 +392,33 @@ get_packet_type (client_state *cs)
else
return other_packet;
/* We have already categorized the packet type */
+
if (cs->pending == pending_cont_waiter || cs->pending == pending_step_waiter)
return other_packet;
switch (own_packet)
- {
+ {
case 'v':
if ((strncmp (in_buffer, "vCont;c", 7) == 0))
return vContc;
- else if ((strncmp (in_buffer, "vCont;r", 7) == 0) || (strncmp (in_buffer, "vCont;s", 7) == 0))
+ else if ((strncmp (in_buffer, "vCont;r", 7) == 0)
+ || (strncmp (in_buffer, "vCont;s", 7) == 0))
return vConts;
+ else if ((strncmp (in_buffer, "vCont;t", 7) == 0))
+ return vContt;
+ else if ((strncmp (in_buffer, "vStopped", 8) == 0))
+ return vStopped;
else if (strncmp (in_buffer, "vRun", 4) == 0)
return vRun;
- break;
- };
- return other_packet;
+ else if (strncmp (in_buffer, "vAttach", 4) == 0)
+ return vAttach;
+ default:
+ return other_packet;
+ };
}
+static int queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg);
+
/* Belatedly reply to last CS previously received and waited on packet */
void
@@ -418,18 +433,30 @@ resolve_waiter (client_state *cs)
{
case vContc:
{
- if (last_status.kind != TARGET_WAITKIND_EXITED)
+ if (non_stop)
{
- /* reply to vContc with a status */
- strcpy (own_buffer, "?");
- handle_status (own_buffer);
- putpkt (own_buffer);
+ if (last_status.kind != TARGET_WAITKIND_EXITED
+ && last_status.kind != TARGET_WAITKIND_STOPPED)
+ {
+ /* Create a stop notification */
+ struct vstop_notif *new_notif = XNEW (struct vstop_notif);
+ char *notif_buf;
+ notif_buf = alloca (PBUFSIZ + 1);
+ write_ok (notif_buf);
+ putpkt (notif_buf);
+
+ new_notif->ptid = general_thread;
+ new_notif->status = last_status;
+ new_notif->status.kind = TARGET_WAITKIND_STOPPED;
+ notif_push (¬if_stop,
+ (struct notif_event *) new_notif);
+ /* Explicit write of notification and remove from queue */
+ discard_queued_stop_replies (cs->ss->general_thread_);
+
+ notif_write_event (¬if_stop, notif_buf);
+ }
}
- break;
- }
- case vConts:
- {
- if (last_status.kind != TARGET_WAITKIND_EXITED)
+ else if (last_status.kind != TARGET_WAITKIND_EXITED)
{
/* reply to vContc with a status */
strcpy (own_buffer, "?");
@@ -438,27 +465,60 @@ resolve_waiter (client_state *cs)
}
break;
}
- case vRun:
- {
- /* reply to vRun with an OK */
- strcpy (own_buffer, "OK");
- putpkt (own_buffer);
- break;
- }
- default:
+ case vConts:
+ {
+ if (last_status.kind != TARGET_WAITKIND_EXITED)
+ {
+ /* reply to vContc with a status */
+ strcpy (own_buffer, "?");
+ handle_status (own_buffer);
+ putpkt (own_buffer);
+ }
break;
+ }
+ case vContt:
+ {
+ if (last_status.kind != TARGET_WAITKIND_EXITED
+ && last_status.kind != TARGET_WAITKIND_STOPPED)
+ {
+ char *notif_buf, *out_buf;
+ notif_buf = alloca (PBUFSIZ + 1);
+ write_ok (notif_buf);
+ putpkt (notif_buf);
+
+ find_inferior (&all_threads, queue_stop_reply_callback, NULL);
+ notif_write_event (¬if_stop, notif_buf);
+ out_buf = alloca (strlen (notif_buf) + 8);
+ // TODO Use Defined notif constant
+ strcpy (out_buf, "Stop:");
+ strcat (out_buf, notif_buf);
+ putpkt_notif (out_buf);
+ if (debug_threads)
+ debug_printf ("%s:%d %s\n", __FUNCTION__, __LINE__, out_buf);
+ }
+ break;
+ }
+ case vRun:
+ {
+ /* reply to vRun with an OK */
+ strcpy (own_buffer, "OK");
+ putpkt (own_buffer);
+ break;
+ }
+ default:
+ break;
};
}
/* Determine the state of client CS with respect to other clients connected to the same server process */
-int
+static int
setup_multiplexing (client_state *cs, char *ch)
{
client_state *csidx = NULL;
- dump_client_state (__FUNCTION__);
+ dump_client_state (__FUNCTION__, "");
cs->attached_to_client = 1;
@@ -467,41 +527,27 @@ setup_multiplexing (client_state *cs, char *ch)
/* another client is attached to the cs process */
if (csidx->file_desc != -1 && csidx != cs && cs->ss == csidx->ss)
{
- if (debug_threads)
- debug_printf ("%s:%d before csidx fd=%d %s %s cs fd=%d %s %s\n", __FUNCTION__, __LINE__, csidx->file_desc, pending_types_str[csidx->pending], packet_types_str[csidx->packet_type], cs->file_desc, pending_types_str[cs->pending], packet_types_str[cs->packet_type]);
/* found a client that has nothing pending */
if (!csidx->pending)
{
- int already_have_waitee = 0;
- client_state *csi;
- /* 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 && csi->file_desc != csidx->file_desc)
- already_have_waitee = 1;
- }
-
/* The cs vContc will wait; found csidx will proceed */
if (cs->packet_type == vContc)
{
if (cs->last_packet_type != vRun)
{
cs->pending = pending_cont_waiter;
- if (1 || already_have_waitee)
csidx->pending = pending_waitee;
}
}
+ /* TODO else if (cs->packet_type == vContt) */
else if (cs->packet_type == vConts)
{
- if (cs->last_packet_type != vRun)
+ if (csidx->last_packet_type != vContt)
{
cs->pending = pending_step_waiter;
csidx->pending = pending_waitee;
}
}
- if (debug_threads)
- debug_printf ("%s:%d after csidx fd=%d %s %s cs fd=%d %s %s\n", __FUNCTION__, __LINE__, csidx->file_desc, pending_types_str[csidx->pending], packet_types_str[csidx->packet_type], cs->file_desc, pending_types_str[cs->pending], packet_types_str[cs->packet_type]);
}
/* Current client is continuing and found another waiter client */
else if (csidx->pending == pending_cont_waiter
@@ -518,67 +564,118 @@ setup_multiplexing (client_state *cs, char *ch)
waitee_count = 1;
}
- debug_printf ("%s:%d waitee_count=%d cs pending %s\n", __FUNCTION__, __LINE__, waitee_count, pending_types_str[cs->pending]);
-
/* Don't want to deadlock on everyone waiting */
if (cs->pending == pending_waitee && waitee_count > 0)
cs->pending = pending_cont_waiter;
}
}
}
- dump_client_state (__FUNCTION__);
/* 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_step_waiter
+ || cs->pending == pending_stop)
{
- if (cs->last_packet_type != vRun)
- return 0;
+ if (cs->last_packet_type != vRun
+ && cs->last_packet_type != vStopped
+ && cs->ss->last_status_exited != have_exit)
+ {
+ dump_client_state (__FUNCTION__, "return 0");
+ return 0; /* Reply to packet later */
+ }
}
- return 1;
+ dump_client_state (__FUNCTION__, "return 1");
+ return 1; /* Reply to packet now */
+}
+
+
+static void
+notify_clients (client_state *waitee_cs)
+{
+ client_state *csidx = NULL;
+
+ if (! (waitee_cs->pending == pending_waitee
+ && waitee_cs->last_packet_type == vStopped
+ && waitee_cs->ss->last_status_exited == have_exit))
+ return;
+
+ for (csidx = client_states.first; csidx != NULL; csidx = csidx->next)
+ {
+ /* 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)
+ 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);
+ return;
}
/* Resolve the state of client WAITEE_CS with respect to other clients connected to the same server process */
-int
+static int
do_multiplexing (client_state *waitee_cs, char ch)
{
client_state *csidx = NULL;
int make_waitee_a_waiter = 0;
+ if (waitee_cs->last_packet_type == vAttach && waitee_cs->packet_type == vContt)
+ {
+ resolve_waiter (waitee_cs);
+ dump_client_state (__FUNCTION__, "resolved vContt");
+ return 0;
+ }
+
if (waitee_cs->packet_type != other_packet)
waitee_cs->last_packet_type = waitee_cs->packet_type;
- dump_client_state (__FUNCTION__);
+ dump_client_state (__FUNCTION__, "");
+
+ if (waitee_cs->ss->last_status_exited == have_exit)
+ notify_clients (waitee_cs);
/* Current client is a waitee that is continuing */
- if (! ((waitee_cs->packet_type == vContc
- || waitee_cs->packet_type == vConts)
- && waitee_cs->pending == pending_waitee))
+ if (! (waitee_cs->pending == pending_waitee
+ && (waitee_cs->packet_type == vContc
+ || waitee_cs->packet_type == vContt)))
{
- if (debug_threads)
- debug_printf ("%s:%d returning for waitee %d\n", __FUNCTION__, __LINE__, waitee_cs->file_desc);
+ dump_client_state (__FUNCTION__, "no action taken");
return 1;
}
-
+
for (csidx = client_states.first; csidx != NULL; csidx = csidx->next)
{
client_state *waiter_cs;
/* Insure another client is attached to the cs process */
if (csidx->file_desc == -1 || waitee_cs->ss != csidx->ss)
continue;
- if (debug_threads)
- debug_printf ("%s:%d before csidx fd=%d %s %s cs fd=%d %s %s\n", __FUNCTION__, __LINE__, csidx->file_desc, pending_types_str[csidx->pending], packet_types_str[csidx->packet_type], waitee_cs->file_desc, pending_types_str[waitee_cs->pending], packet_types_str[waitee_cs->packet_type]);
if (csidx->pending == pending_cont_waiter)
{
/* Found a vContc packet that is waiting */
if (csidx->packet_type == vContc
- || csidx->last_packet_type == vContc)
+ || csidx->last_packet_type == vContc
+ || csidx->last_packet_type == vContt) // TODO
{
char save_ch = ch;
int waitee_has_bp, waiter_has_bp;
+
+ prepare_to_access_memory ();
+
if (waitee_cs->ss->last_status_.kind == TARGET_WAITKIND_EXITED)
{
waiter_cs = set_client_state (csidx->file_desc);
@@ -588,12 +685,15 @@ do_multiplexing (client_state *waitee_cs, char ch)
hooks/post-receive
--
Repository for Project Archer.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2016-01-04 15:32 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-04 15:32 [SCM] scox/globalstate: Improve non-stop multi client handling 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).