From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 70537 invoked by alias); 30 Mar 2016 14:46:58 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 70513 invoked by uid 440); 30 Mar 2016 14:46:58 -0000 Date: Wed, 30 Mar 2016 14:46:00 -0000 Message-ID: <20160330144658.70485.qmail@sourceware.org> From: scox@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] scox/globalstate: Improve non-stop handling X-Git-Refname: refs/heads/scox/globalstate X-Git-Reftype: branch X-Git-Oldrev: bc4b0dbeec0fb45f9fd169cb9b3a984e9378d055 X-Git-Newrev: 0b038592634fba79da5353187a75028e81b6a718 X-SW-Source: 2016-q1/txt/msg00004.txt.bz2 List-Id: The branch, scox/globalstate has been updated via 0b038592634fba79da5353187a75028e81b6a718 (commit) from bc4b0dbeec0fb45f9fd169cb9b3a984e9378d055 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 0b038592634fba79da5353187a75028e81b6a718 Author: Stan Cox Date: Wed Mar 30 10:18:39 2016 -0400 Improve non-stop handling * server.c (pending_types): Add pending_notifier (dump_client_state): Dump pc and indicate current client. (delete_client_state): Copy persistent state flags. (resolve_waiter): Send notification for vConts (notify_clients): New. Send notification to waiter client. (do_multiplexing): Also consider notification state. (process_serial_event): Remove the client breakpoint. * notif.c (notif_push): Also notify the waiting client. ----------------------------------------------------------------------- Summary of changes: gdb/gdbserver/ChangeLog | 12 ++ gdb/gdbserver/notif.c | 1 + gdb/gdbserver/server.c | 174 +++++++++++++++++++++++------ gdb/gdbserver/server.h | 1 + gdb/testsuite/ChangeLog | 5 + gdb/testsuite/gdb.server/multi-client.exp | 70 +++++------- 6 files changed, 187 insertions(+), 76 deletions(-) First 500 lines of diff: diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 49c0407..f1589f9 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,15 @@ +2016-03-30 Stan Cox + + * server.c (pending_types): Add pending_notifier + (dump_client_state): Dump pc and indicate current client. + (delete_client_state): Copy persistent state flags. + (resolve_waiter): Send notification for vConts + (notify_clients): New. Send notification to waiter client. + (do_multiplexing): Also consider notification state. + (process_serial_event): Remove the client breakpoint. + + * notif.c (notif_push): Also notify the waiting client. + 2016-02-23 Stan Cox * server.c (setup_multiplexing): Add pending_step_waiter, vConts, diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c index 9455167..2ca0a9e 100644 --- a/gdb/gdbserver/notif.c +++ b/gdb/gdbserver/notif.c @@ -150,6 +150,7 @@ notif_push (struct notif_server *np, struct notif_event *new_event) p += strlen (p); np->write (new_event, p); + notify_clients (buf); putpkt_notif (buf); } } diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index df1ea3c..9ae8bda 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -85,8 +85,8 @@ 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"}; +enum pending_types {none_pending, pending_waitee, pending_cont_waiter, pending_step_waiter, pending_stop, pending_notifier}; +char *pending_types_str[] = {"not-waiting","waitee","waiter","step-waiter","stop", "notifier"}; 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", ""}; @@ -282,8 +282,10 @@ dump_client_state (const char *function, const char *comment) for (cs = client_states.first; cs != NULL; cs = cs->next) { char *last_status_kind; - client_states.current_cs = cs; + struct regcache *regcache = NULL; + CORE_ADDR pc = 0; + client_states.current_cs = cs; if (cs->file_desc == -1) continue; @@ -291,12 +293,18 @@ dump_client_state (const char *function, const char *comment) 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", + if (current_thread != NULL) + regcache = client_states.current_cs->ss->current_thread_->regcache_data; + if (regcache != NULL) + pc = (*the_target->read_pc) (regcache); + if (save_cs == cs) + debug_printf ("*"); + else + debug_printf (" "); + debug_printf ("%d %#lx pc=%#lx #=%d %s %s %s %s\n", cs->file_desc, - (long unsigned)general_thread.pid, - (int)general_thread.pid, - (long unsigned)cont_thread.pid, - (long unsigned)last_ptid.pid, + (long unsigned)general_thread.pid, + (long unsigned)pc, cs->ss->attach_count_, packet_types_str[cs->packet_type], packet_types_str[cs->last_packet_type], @@ -376,9 +384,14 @@ delete_client_state (gdb_fildes_t fd) { ss = cs->ss; previous_cs->next = cs->next; - free_client_state (cs); if (client_states.current_fd == fd) - set_client_state (get_first_client_fd ()); + { + set_client_state (get_first_client_fd ()); + extended_protocol = cs->extended_protocol_; + run_once = cs->run_once_; + non_stop = cs->non_stop_; + } + free_client_state (cs); cs = previous_cs; } if (cs->next == NULL) @@ -446,6 +459,13 @@ resolve_waiter (client_state *cs, client_state *waitee_cs) save_client_state = client_states.current_cs; set_client_state (cs->file_desc); + if (debug_threads) + { + debug_printf ("%s:%d fd=%d %s %s", __FUNCTION__, __LINE__, cs->file_desc, packet_types_str[this_packet_type], pending_types_str[cs->pending]); + if (waitee_cs) + debug_printf (" fd=%d %s %s", waitee_cs->file_desc, packet_types_str[waitee_cs->packet_type], pending_types_str[waitee_cs->pending]); + debug_printf ("\n"); + } switch (this_packet_type) { case vContc: @@ -467,12 +487,14 @@ resolve_waiter (client_state *cs, client_state *waitee_cs) new_notif->status = last_status; new_notif->status.kind = TARGET_WAITKIND_STOPPED; notif_push (¬if_stop, - (struct notif_event *) new_notif); + (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); } + else if (last_status.kind != TARGET_WAITKIND_EXITED) + cs->pending = pending_notifier; } else if (last_status.kind != TARGET_WAITKIND_EXITED && cs->last_cont_ptid.pid == cs->ss->last_ptid_.pid) @@ -498,7 +520,34 @@ resolve_waiter (client_state *cs, client_state *waitee_cs) } case vConts: { - if (last_status.kind != TARGET_WAITKIND_EXITED) + if (non_stop) + { + if (last_status.kind != TARGET_WAITKIND_EXITED + && last_status.kind != TARGET_WAITKIND_STOPPED) + { + /* Create a stop notification */ + struct vstop_notif *new_notif; + char *notif_buf; + new_notif = XNEW (struct vstop_notif); + 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); + if (last_status.kind != TARGET_WAITKIND_STOPPED) + cs->pending = pending_notifier; + } + + } + else if (last_status.kind != TARGET_WAITKIND_EXITED) { /* reply to vConts with a status */ strcpy (own_buffer, "?"); @@ -506,9 +555,9 @@ resolve_waiter (client_state *cs, client_state *waitee_cs) putpkt (own_buffer); } else if (last_status.kind == TARGET_WAITKIND_EXITED) - { + { putpkt (waitee_cs->own_buffer_); - } + } break; } case vContt: @@ -618,11 +667,8 @@ setup_multiplexing (client_state *current_cs) break; /* TODO else if (current_cs->packet_type == vContt) */ case /* current_cs->packet_type */ vConts: - if (same_pid_cs->last_packet_type != vContt) - { - current_cs->pending = pending_step_waiter; - same_pid_cs->pending = pending_waitee; - } + current_cs->pending = pending_step_waiter; + same_pid_cs->pending = pending_waitee; } break; case /* same_pid_cs->pending */ pending_step_waiter: @@ -633,9 +679,18 @@ setup_multiplexing (client_state *current_cs) current_cs->pending = pending_cont_waiter; resolve_waiter (same_pid_cs, current_cs); same_pid_cs->pending = pending_waitee; + 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; } } - /* fall through for vConts case */ + break; case /* same_pid_cs->pending */ pending_cont_waiter: switch (current_cs->packet_type) { @@ -686,7 +741,6 @@ setup_multiplexing (client_state *current_cs) switch (current_cs->last_packet_type) { case vRun: - case vStopped: break; default: /* Current client is continuing and waiting so don't reply to this @@ -707,8 +761,39 @@ setup_multiplexing (client_state *current_cs) } +void +notify_clients (char *buffer) +{ + client_state *same_pid_cs = NULL; + int save_client_fd = client_states.current_fd; + client_state *save_client_cs = client_states.current_cs; + char *okay_buf = alloca (4); + + write_ok (okay_buf); + + for (same_pid_cs = client_states.first; + same_pid_cs != NULL; + same_pid_cs = same_pid_cs->next) + { + /* Insure another client is attached to the cs process */ + if (! attached_to_same_proc (client_states.current_cs, same_pid_cs)) + continue; + if (same_pid_cs->pending == pending_notifier) + { + if (debug_threads) + debug_printf ("%s:%d Notifying fd=%d\n", __FUNCTION__, __LINE__, same_pid_cs->file_desc); + set_client_state (same_pid_cs->file_desc); + putpkt (okay_buf); + putpkt_notif (buffer); + set_client_state (save_client_fd); + same_pid_cs->pending = none_pending; + } + } +} + + static void -notify_clients (client_state *current_cs) +stop_clients (client_state *current_cs) { client_state *same_pid_cs = NULL; @@ -746,7 +831,7 @@ notify_clients (client_state *current_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 *current_cs, char ch) +do_multiplexing (client_state *current_cs) { /*** If we have two dependent clients 4 and 7 and 4 is the current client with a @@ -800,7 +885,7 @@ do_multiplexing (client_state *current_cs, char ch) } if (current_cs->ss->last_status_exited == have_exit) - notify_clients (current_cs); + stop_clients (current_cs); for (same_pid_cs = client_states.first; same_pid_cs != NULL; @@ -821,7 +906,6 @@ do_multiplexing (client_state *current_cs, char ch) { 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)) @@ -859,10 +943,15 @@ do_multiplexing (client_state *current_cs, char ch) struct thread_info *thread; CORE_ADDR pc; if (non_stop) - thread = current_thread; + { + thread = current_thread; + regcache = get_thread_regcache (thread, 1); + } else - thread = find_thread_ptid (last_ptid); - regcache = get_thread_regcache (thread, 1); + { + 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); @@ -875,10 +964,11 @@ do_multiplexing (client_state *current_cs, char ch) { /* Belatedly reply to the waiter client */ resolve_waiter (waiter_cs, current_cs); - current_cs->pending = none_pending; + if (current_cs->pending != pending_notifier) + current_cs->pending = none_pending; if (!current_cs_has_bp) waiter_cs->pending = pending_waitee; - else + else if (waiter_cs->pending != pending_notifier) waiter_cs->pending = none_pending; /* If the waitee did not reach the breakpoint then it needs to wait */ if (!current_cs_has_bp) @@ -892,7 +982,6 @@ do_multiplexing (client_state *current_cs, char ch) debug_printf ("%s:%d fd=%d no breakpoint\n", __FUNCTION__, __LINE__, waiter_cs->file_desc); } current_cs = set_client_state (current_cs->file_desc); - done_accessing_memory (); } /* switch same_pid_cs->packet_type */ break; /* case vContc */ @@ -900,20 +989,22 @@ do_multiplexing (client_state *current_cs, char ch) 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) + debug_printf ("%s:%d resolving %d %s %s\n", __FUNCTION__, __LINE__, current_cs->file_desc,pending_types_str[same_pid_cs->pending],packet_types_str[current_cs->packet_type]); + if (current_cs->packet_type == vContc + || (current_cs->packet_type == vConts && !non_stop)) { resolve_waiter (waiter_cs, current_cs); current_cs->pending = same_pid_cs->pending = none_pending; } + else if (current_cs->packet_type == vConts && non_stop) + same_pid_cs->pending = pending_notifier; current_cs = set_client_state (current_cs->file_desc); } /* switch same_pid_cs->pending */ } if (make_waitee_a_waiter && current_cs->packet_type == vContc) { - /* The packet will be replied to later in do_multiplexing */ + /* The packet will be replied to later in do_multiplexing */ current_cs->pending = pending_cont_waiter; dump_client_state (__FUNCTION__, "return 0"); current_cs->last_cont_ptid = current_cs->ss->general_thread_; @@ -5094,7 +5185,12 @@ process_serial_event (void) } } else - res = delete_gdb_breakpoint (type, addr, kind); + { + res = delete_gdb_breakpoint (type, addr, kind); + if (res != 0 && has_client_breakpoint_at (addr)) + res = 0; + delete_client_breakpoint (addr); + } if (res == 0) write_ok (own_buffer); @@ -5202,7 +5298,7 @@ process_serial_event (void) break; } - if (! do_multiplexing (cs, ch)) + if (! do_multiplexing (cs)) return 0; if (new_packet_len != -1) @@ -5262,6 +5358,10 @@ handle_target_event (int err, gdb_client_data client_data) last_ptid = mywait (minus_one_ptid, &last_status, TARGET_WNOHANG, 1); + if (debug_threads) + debug_printf ("%s fd=%d queue=%d %s\n", __FUNCTION__, client_states.current_fd, notif_stop.queue->head == NULL ? 0 : 1, + waitkind_str[last_status.kind]); + if (last_status.kind == TARGET_WAITKIND_NO_RESUMED) { if (gdb_connected () && report_no_resumed) diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h index fdf51a0..675231c 100644 --- a/gdb/gdbserver/server.h +++ b/gdb/gdbserver/server.h @@ -84,6 +84,7 @@ typedef int gdb_fildes_t; /* Functions from server.c. */ extern int handle_serial_event (int err, gdb_client_data client_data); extern int handle_target_event (int err, gdb_client_data client_data); +extern void notify_clients (char *buffer); /* Get rid of the currently pending stop replies that match PTID. */ extern void discard_queued_stop_replies (ptid_t ptid); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index c0b2623..6c898ea 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-03-30 Stan Cox + + * gdb.server/multi-client.exp (start_client) Add testpath parameter. + (cleanup_server_and_clients) New. + 2016-02-23 Stan Cox * gdb.server/multi-client.exp: Add next, strace, and pthreads tests. diff --git a/gdb/testsuite/gdb.server/multi-client.exp b/gdb/testsuite/gdb.server/multi-client.exp index d61c024..5effe48 100644 --- a/gdb/testsuite/gdb.server/multi-client.exp +++ b/gdb/testsuite/gdb.server/multi-client.exp @@ -23,10 +23,6 @@ set srcfile wrapper.c global srcdir subdir set testpath [pwd]/$subdir/$testfile -set testfile2 server-kill -set srcfile2 server-kill.c -set testpath2 [pwd]/$subdir/$testfile2 - set testfile3 catch-syscall set srcfile3 ../gdb.base/catch-syscall.c set testpath3 [pwd]/$subdir/$testfile3 @@ -38,9 +34,6 @@ set testpath4 [pwd]/$subdir/$testfile4 if { [prepare_for_testing $test $testfile $srcfile debug] } { return -1 } -if {[build_executable $test $testfile2 $srcfile2 debug] == -1} { - return -1 -} if {[build_executable $test $testfile3 $srcfile3 debug] == -1} { return -1 } @@ -79,8 +72,9 @@ proc start_gdbserver { } { return $res } -proc start_client { N ATTACH_FLAGS } { +proc start_client { N TESTPATH FLAGS ATTACH_FLAGS } { global test gdb_spawn_id GDB MULTI_GDBFLAGS + set MULTI_GDBFLAGS "$FLAGS -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 res [remote_spawn host "$GDB $MULTI_GDBFLAGS $ATTACH_FLAGS [host_info gdb_opts] -iex \"set prompt (client $N gdb) \""] sleep 1 set ok 0 @@ -101,7 +95,7 @@ proc start_client { N ATTACH_FLAGS } { } proc start_strace { ATTACH_FLAGS } { - global test gdb_spawn_id MULTI_GDBFLAGS + global test gdb_spawn_id set STRACE [auto_execok strace] verbose "strace is $STRACE $ATTACH_FLAGS" set res [remote_spawn host "$STRACE $ATTACH_FLAGS"] @@ -173,12 +167,22 @@ proc gdb_command { CLIENT COMMAND RESPONSE COMMENT } { } } +proc cleanup_server_and_clients { } { + global gdb_server_spawn_id + global gdb_client1_spawn_id + global gdb_client2_spawn_id + global gdb_client3_spawn_id + exec kill -KILL [exp_pid -i $gdb_server_spawn_id] + exec kill -KILL [exp_pid -i $gdb_client1_spawn_id] + exec kill -KILL [exp_pid -i $gdb_client2_spawn_id] + exec kill -KILL [exp_pid -i $gdb_client3_spawn_id] +} + 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 ""] +set gdb_client1_spawn_id [start_client 1 $testpath "" ""] gdb_command 1 "b getenv" "Breakpoint 1 at" "b getenv" @@ -186,9 +190,9 @@ gdb_command 1 "run" "Breakpoint 1," "hit b getenv" set target_pid [get_target_pid wrapper] -set gdb_client2_spawn_id [start_client 2 "-iex \"attach $target_pid\""] +set gdb_client2_spawn_id [start_client 2 $testpath "" "-iex \"attach $target_pid\""] -set gdb_client3_spawn_id [start_client 3 "-iex \"attach $target_pid\""] +set gdb_client3_spawn_id [start_client 3 $testpath "" "-iex \"attach $target_pid\""] gdb_command 2 "b marker" "Breakpoint 1 at" "b marker" @@ -234,13 +238,13 @@ if { $ok == 1 } { fail "$test client exited" } hooks/post-receive -- Repository for Project Archer.