public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] scox/globalstate: Improve multiple client thread support.
@ 2016-02-23 20:09 scox
0 siblings, 0 replies; only message in thread
From: scox @ 2016-02-23 20:09 UTC (permalink / raw)
To: archer-commits
The branch, scox/globalstate has been updated
via bc4b0dbeec0fb45f9fd169cb9b3a984e9378d055 (commit)
from c94dca1a4db81df5753f2ec7c42b416920908897 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email.
- Log -----------------------------------------------------------------
commit bc4b0dbeec0fb45f9fd169cb9b3a984e9378d055
Author: Stan Cox <scox@redhat.com>
Date: Tue Feb 23 15:07:29 2016 -0500
Improve multiple client thread support.
* server.c (setup_multiplexing): Add pending_step_waiter, vConts,
and pending_waitee cases.
(do_multiplexing): Add vConts case. Grab pc from the current
thread's cache.
* multi-client.exp: Add next, strace, and pthreads tests.
-----------------------------------------------------------------------
Summary of changes:
gdb/gdbserver/ChangeLog | 7 +
gdb/gdbserver/server.c | 181 ++++++++++++---------
gdb/testsuite/ChangeLog | 4 +
gdb/testsuite/gdb.server/multi-client.exp | 251 ++++++++++++++++++++--------
4 files changed, 298 insertions(+), 145 deletions(-)
First 500 lines of diff:
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 88d55fd..49c0407 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,10 @@
+2016-02-23 Stan Cox <scox@redhat.com>
+
+ * server.c (setup_multiplexing): Add pending_step_waiter, vConts,
+ and pending_waitee cases.
+ (do_multiplexing): Add vConts case. Grab pc from the current
+ thread's cache.
+
2016-02-06 Stan Cox <scox@redhat.com>
* server.c (waitkind_str): New
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 378b174..df1ea3c 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -85,7 +85,7 @@ 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};
+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"};
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", ""};
@@ -442,19 +442,15 @@ void
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;
+ client_state *save_client_state;
+ save_client_state = client_states.current_cs;
+ set_client_state (cs->file_desc);
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
@@ -504,11 +500,15 @@ resolve_waiter (client_state *cs, client_state *waitee_cs)
{
if (last_status.kind != TARGET_WAITKIND_EXITED)
{
- /* reply to vContc with a status */
+ /* reply to vConts with a status */
strcpy (own_buffer, "?");
handle_status (own_buffer);
putpkt (own_buffer);
}
+ else if (last_status.kind == TARGET_WAITKIND_EXITED)
+ {
+ putpkt (waitee_cs->own_buffer_);
+ }
break;
}
case vContt:
@@ -543,6 +543,25 @@ resolve_waiter (client_state *cs, client_state *waitee_cs)
default:
break;
};
+
+ set_client_state (save_client_state->file_desc);
+}
+
+
+void
+analyze_group (client_state *current_cs, int *have_nonwaiter)
+{
+ client_state *csi;
+ *have_nonwaiter = 0;
+
+ for (csi = client_states.first->next; csi != NULL; csi = csi->next)
+ {
+ if (attached_to_same_proc (current_cs, csi))
+ {
+ if (csi->pending == pending_waitee || csi->pending == none_pending)
+ *have_nonwaiter += 1;
+ }
+ }
}
@@ -582,14 +601,15 @@ setup_multiplexing (client_state *current_cs)
{
if (! attached_to_same_proc (current_cs, same_pid_cs))
continue;
+
switch (same_pid_cs->pending)
{
- case none_pending:
+ case /* same_pid_cs->pending */ 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)
{
- case vContc:
+ case /* current_cs->packet_type */ vContc:
if (current_cs->last_packet_type != vRun)
{
current_cs->pending = pending_cont_waiter;
@@ -597,7 +617,7 @@ setup_multiplexing (client_state *current_cs)
}
break;
/* TODO else if (current_cs->packet_type == vContt) */
- case vConts:
+ case /* current_cs->packet_type */ vConts:
if (same_pid_cs->last_packet_type != vContt)
{
current_cs->pending = pending_step_waiter;
@@ -605,33 +625,56 @@ setup_multiplexing (client_state *current_cs)
}
}
break;
- case pending_cont_waiter:
+ case /* same_pid_cs->pending */ pending_step_waiter:
switch (current_cs->packet_type)
{
- /* Current client is continuing and found another waiter client */
- case vContc:
+ case /* current_cs->packet_type */ 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 (current_cs != csi && csi->pending == pending_waitee
- && attached_to_same_proc (current_cs, csi))
- waitee_count = 1;
- }
-
+ current_cs->pending = pending_cont_waiter;
+ resolve_waiter (same_pid_cs, current_cs);
+ same_pid_cs->pending = pending_waitee;
+ }
+ }
+ /* fall through for vConts case */
+ case /* same_pid_cs->pending */ pending_cont_waiter:
+ switch (current_cs->packet_type)
+ {
+ /* Current client is continuing and found another waiter client */
+ case /* current_cs->packet_type */ vContc:
+ {
+ int have_nonwaiter;
+ analyze_group (current_cs, &have_nonwaiter);
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)
+ if (current_cs->pending == pending_waitee && have_nonwaiter)
current_cs->pending = pending_cont_waiter;
}
+ break;
+ case /* current_cs->packet_type */ vConts:
+ {
+ int have_waitee;
+ analyze_group (current_cs, &have_waitee);
+ /* Don't want to deadlock on everyone waiting */
+ if (current_cs->pending == pending_waitee && have_waitee)
+ current_cs->pending = pending_step_waiter;
+ }
}
- }
+ break;
+ case /* same_pid_cs->pending */ pending_waitee:
+ switch (current_cs->packet_type)
+ {
+ /* Current client is continuing and found another waitee client */
+ case /* current_cs->packet_type */ vContc:
+ {
+ current_cs->pending = pending_cont_waiter;
+ }
+ break;
+ case /* current_cs->packet_type */ vConts:
+ {
+ current_cs->pending = pending_step_waiter;
+ }
+ }
+ } /* switch same_pid_cs->pending */
} /* for same_pid_cs */
@@ -640,15 +683,15 @@ setup_multiplexing (client_state *current_cs)
case pending_cont_waiter:
case pending_step_waiter:
case pending_stop:
-
switch (current_cs->last_packet_type)
- {
+ {
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");
@@ -656,11 +699,11 @@ setup_multiplexing (client_state *current_cs)
current_cs->last_cont_waitstatus = current_cs->ss->last_status_;
return 0; /* Reply to packet later */
}
- }
- default:
+ } /* switch current_cs->last_packet_type */
+ default: /* fall through */
dump_client_state (__FUNCTION__, "return 1");
return 1; /* Reply to packet now */
- }
+ } /* switch current_cs->pending */
}
@@ -723,24 +766,6 @@ do_multiplexing (client_state *current_cs, char ch)
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;
@@ -755,7 +780,7 @@ current_cs.kind ==
dump_client_state (__FUNCTION__, "resolved vContt");
return 0;
}
- default:
+ default: /* fall through */
current_cs->last_packet_type = current_cs->packet_type;
}
@@ -766,9 +791,10 @@ current_cs.kind ==
{
case vContt:
case vContc:
- if ((current_cs->pending == pending_waitee))
+ case vConts:
+ if (current_cs->pending == pending_waitee)
break;
- default:
+ default: /* fall through */
dump_client_state (__FUNCTION__, "no action taken");
return 1;
}
@@ -789,26 +815,22 @@ current_cs.kind ==
continue;
switch (same_pid_cs->pending)
{
- case pending_cont_waiter:
+ case /* same_pid_cs->pending */ pending_cont_waiter:
/* Found a vContc packet that is waiting */
switch (same_pid_cs->packet_type)
{
- case vContc:
+ case /* same_pid_cs->packet_type */ vContc:
prepare_to_access_memory ();
- /**/
if (current_cs->packet_type == vContc
&& (current_cs->ss->last_status_.kind == TARGET_WAITKIND_SYSCALL_ENTRY
|| current_cs->ss->last_status_.kind == TARGET_WAITKIND_SYSCALL_RETURN))
{
if (same_pid_cs->catch_syscalls)
{
- waiter_cs = set_client_state (same_pid_cs->file_desc);
resolve_waiter (same_pid_cs, current_cs);
dump_client_state (__FUNCTION__, "resolved syscall");
- current_cs = set_client_state (current_cs->file_desc);
- waiter_cs->pending = pending_waitee;
- make_waitee_a_waiter = 1;
+ same_pid_cs->pending = pending_waitee;
}
else if (current_cs->catch_syscalls)
{
@@ -816,7 +838,11 @@ current_cs.kind ==
same_pid_cs_has_bp = 1;
}
}
- /**/
+ else if (current_cs->packet_type == vConts)
+ {
+ current_cs->last_cont_ptid = current_cs->ss->general_thread_;
+ current_cs->last_cont_waitstatus = current_cs->ss->last_status_;
+ }
if (current_cs->ss->last_status_.kind == TARGET_WAITKIND_EXITED)
{
@@ -827,10 +853,17 @@ current_cs.kind ==
else /* not exited */
{
/* Does current client have a breakpoint at PC? */
- if (get_first_thread () != NULL && set_desired_thread (1))
+ if (get_first_thread () != NULL)
{
- struct regcache *regcache = get_thread_regcache (current_thread, 1);
- CORE_ADDR pc = (*the_target->read_pc) (regcache);
+ struct regcache *regcache;
+ struct thread_info *thread;
+ CORE_ADDR pc;
+ if (non_stop)
+ thread = current_thread;
+ else
+ thread = find_thread_ptid (last_ptid);
+ regcache = get_thread_regcache (thread, 1);
+ pc = (*the_target->read_pc) (regcache);
current_cs_has_bp = has_client_breakpoint_at (pc);
waiter_cs = set_client_state (same_pid_cs->file_desc);
/* Does found client have a breakpoint at PC? */
@@ -861,11 +894,13 @@ current_cs.kind ==
current_cs = set_client_state (current_cs->file_desc);
done_accessing_memory ();
- }
-
- break;
- case pending_step_waiter:
+ } /* switch same_pid_cs->packet_type */
+ break; /* case vContc */
+
+ case /* same_pid_cs->pending */ pending_step_waiter:
waiter_cs = set_client_state (same_pid_cs->file_desc);
+ if (debug_threads)
+ debug_printf ("%s:%d resolving %d/%d %s", __FUNCTION__, __LINE__, current_cs->file_desc,same_pid_cs->pending,packet_types_str[current_cs->packet_type]);
if (current_cs->packet_type == vConts
|| current_cs->packet_type == vContc)
{
@@ -873,7 +908,7 @@ current_cs.kind ==
current_cs->pending = same_pid_cs->pending = none_pending;
}
current_cs = set_client_state (current_cs->file_desc);
- }
+ } /* switch same_pid_cs->pending */
}
if (make_waitee_a_waiter && current_cs->packet_type == vContc)
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index e250aee..c0b2623 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2016-02-23 Stan Cox <scox@redhat.com>
+
+ * gdb.server/multi-client.exp: Add next, strace, and pthreads tests.
+
2016-02-06 Stan Cox <scox@redhat.com>
* gdb.server/multi-client.exp: Add syscall test.
diff --git a/gdb/testsuite/gdb.server/multi-client.exp b/gdb/testsuite/gdb.server/multi-client.exp
index ae75ed3..d61c024 100644
--- a/gdb/testsuite/gdb.server/multi-client.exp
+++ b/gdb/testsuite/gdb.server/multi-client.exp
@@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-exp_internal 1
+# exp_internal 1
load_lib gdbserver-support.exp
set test "multi-client"
@@ -31,6 +31,10 @@ set testfile3 catch-syscall
set srcfile3 ../gdb.base/catch-syscall.c
set testpath3 [pwd]/$subdir/$testfile3
+set testfile4 thread_check
+set srcfile4 ../gdb.threads/thread_check.c
+set testpath4 [pwd]/$subdir/$testfile4
+
if { [prepare_for_testing $test $testfile $srcfile debug] } {
return -1
}
@@ -40,6 +44,9 @@ if {[build_executable $test $testfile2 $srcfile2 debug] == -1} {
if {[build_executable $test $testfile3 $srcfile3 debug] == -1} {
return -1
}
+if {[build_executable $test $testfile4 $srcfile4 {debug pthreads}] == -1} {
+ return -1
+}
set use_gdb_stub [target_info exists use_gdb_stub]
@@ -86,9 +93,9 @@ proc start_client { N ATTACH_FLAGS } {
}
set gdb_spawn_id $res
if { $ok == 1 } {
- pass "$test gdbserver attach client $N"
+ pass "$test attach client $N"
} else {
- fail "$test gdbserver attach client $N"
+ fail "$test attach client $N"
}
return $res
}
@@ -109,9 +116,9 @@ proc start_strace { ATTACH_FLAGS } {
}
set gdb_spawn_id $res
if { $ok == 1 } {
- pass "$test gdbserver strace \"$expect_out(buffer)\""
+ pass "$test strace \"$expect_out(buffer)\""
} else {
- unresolved "$test gdbserver strace \"$expect_out(buffer)\""
+ unresolved "$test strace \"$expect_out(buffer)\""
}
return $res
}
@@ -160,44 +167,42 @@ proc gdb_command { CLIENT COMMAND RESPONSE COMMENT } {
} else {
if { $i == 3 } {
fail "$test $COMMENT"
- } else { sleep 1 }
+ } else { sleep 4 }
}
}
}
}
-verbose "##### Run one process and attach to it"
-
+verbose "##### Test coordination of three clients doing break/continue"
set gdb_server_spawn_id [start_gdbserver]
set MULTI_GDBFLAGS "-iex \"file $testpath\" -iex \"set remotetimeout 600\" -iex \"target extended-remote localhost:65432\" -iex \"set remote exec-file $testpath\" --silent --data-directory=[file dirname $GDB]/data-directory"
set gdb_client1_spawn_id [start_client 1 ""]
-gdb_command 1 "b getenv" "Breakpoint 1 at" "gdbserver b getenv"
+gdb_command 1 "b getenv" "Breakpoint 1 at" "b getenv"
-gdb_command 1 "run" "Breakpoint 1," "gdbserver hit b getenv"
+gdb_command 1 "run" "Breakpoint 1," "hit b getenv"
set target_pid [get_target_pid wrapper]
-# Now start a second client that attaches to the first client
set gdb_client2_spawn_id [start_client 2 "-iex \"attach $target_pid\""]
set gdb_client3_spawn_id [start_client 3 "-iex \"attach $target_pid\""]
-gdb_command 2 "b marker" "Breakpoint 1 at" "gdbserver b marker"
+gdb_command 2 "b marker" "Breakpoint 1 at" "b marker"
-gdb_command 2 "continue" "Continuing" "gdbserver continue client2"
+gdb_command 2 "continue" "Continuing" "continue client2"
-gdb_command 3 "b wrapper.c:33" "Breakpoint 1 at" "gdbserver b exit"
+gdb_command 3 "b wrapper.c:33" "Breakpoint 1 at" "b exit"
-gdb_command 3 "continue" "Continuing" "gdbserver continue client3"
+gdb_command 3 "continue" "Continuing" "continue client3"
# Second client waits while we continue first client
-gdb_command 1 "dis 1" "" "gdbserver disable breakpoint"
+gdb_command 1 "dis 1" "" "disable breakpoint"
-gdb_command 1 "continue" "Continuing" "gdbserver continue client1"
+gdb_command 1 "continue" "Continuing" "continue client1"
# The second client is back
@@ -206,42 +211,97 @@ expect {
-i $gdb_client2_spawn_id "Breakpoint 1, marker" { incr ok; }
}
if { $ok == 1 } {
- pass "$test gdbserver hit b marker"
+ pass "$test hit b marker"
} else {
hooks/post-receive
--
Repository for Project Archer.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2016-02-23 20:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-23 20:09 [SCM] scox/globalstate: Improve multiple client thread 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).