public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  scox/globalstate: Improve non-stop handling
@ 2016-03-30 14:46 scox
  0 siblings, 0 replies; only message in thread
From: scox @ 2016-03-30 14:46 UTC (permalink / raw)
  To: archer-commits

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 <scox@redhat.com>
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  <scox@redhat.com>
+
+	* 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  <scox@redhat.com>
 
 	* 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 (&notif_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 (&notif_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 (&notif_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 (&notif_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  <scox@redhat.com>
+
+	* gdb.server/multi-client.exp (start_client)  Add testpath parameter.
+	(cleanup_server_and_clients)  New.
+
 2016-02-23  Stan Cox  <scox@redhat.com>
 
 	* 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.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2016-03-30 14:46 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-30 14:46 [SCM] scox/globalstate: Improve non-stop 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).