public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  scox/globalstate: Push multiple client non-stop handling into notify_clients
@ 2016-06-08 20:28 scox
  0 siblings, 0 replies; only message in thread
From: scox @ 2016-06-08 20:28 UTC (permalink / raw)
  To: archer-commits

The branch, scox/globalstate has been updated
       via  d7a6805f1d4956568ca5f2fb995bb84d522f97ba (commit)
      from  b9d4c5aefb38b48611ca88feab071a8eacf4be60 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit d7a6805f1d4956568ca5f2fb995bb84d522f97ba
Author: Stan Cox <scox@redhat.com>
Date:   Wed Jun 8 16:27:42 2016 -0400

    Push multiple client non-stop handling into notify_clients
    
    	* mem-break.c (has_client_breakpoint_at): Simplify address check.
    	* notif.c (notif_push): notify_clients can throttle putpkt_notif.
    	* server.c (add_client_by_pid)  Check all/non stop mode equivalence.
    	(get_packet_type):  Remove vStopped.
    	(resolve_waiter):  Handle non-stop in putpkt_notif/notify_clients
    	(setup_multiplexing, notify_clients):  Likewise.
    	(do_multiplexing):  Likewise.  Allow for watchpoints.
    	(handle_v_attach):  Check multiple client all/non stop equivalence.
    
    	* multi-client.exp:  Test various request combinations using towers.c
    	Hanoi, towers.c.

-----------------------------------------------------------------------

Summary of changes:
 gdb/gdbserver/ChangeLog                   |   11 ++
 gdb/gdbserver/mem-break.c                 |    8 +-
 gdb/gdbserver/notif.c                     |    4 +-
 gdb/gdbserver/server.c                    |  192 ++++++++++++++---------------
 gdb/gdbserver/server.h                    |    6 +-
 gdb/testsuite/ChangeLog                   |    4 +
 gdb/testsuite/gdb.server/multi-client.exp |  152 ++++++++++++-----------
 gdb/testsuite/gdb.server/towers.c         |  153 +++++++++++++++++++++++
 8 files changed, 351 insertions(+), 179 deletions(-)
 create mode 100644 gdb/testsuite/gdb.server/towers.c

First 500 lines of diff:
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index d8b72e1..231b91e 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,14 @@
+2016-06-08  Stan Cox  <scox@redhat.com>
+
+	* server.c (add_client_by_pid)  Check all/non stop mode equivalence.
+	(get_packet_type):  Remove vStopped.
+	(resolve_waiter):  Handle non-stop in putpkt_notif/notify_clients
+	(setup_multiplexing, notify_clients):  Likewise.
+	(do_multiplexing):  Likewise.  Allow for watchpoints.
+	(handle_v_attach):  Check multiple client all/non stop equivalence.
+	* mem-break.c (has_client_breakpoint_at): Simplify address check.
+	* notif.c (notif_push): notify_clients can throttle putpkt_notif.
+
 2016-05-25  Stan Cox  <scox@redhat.com>
 
 	* server.c (free_client_state):  Free in_buffer and own_buffer.
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index 6b10c7b..cd5547a 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -317,7 +317,8 @@ find_raw_breakpoint_at (CORE_ADDR addr, enum raw_bkpt_type type, int kind)
   return NULL;
 }
 
-/* Is there a low-level breakpoint at address ADDR? */
+
+/* Does the client have a breakpoint at address ADDR? */
 
 int
 has_client_breakpoint_at (CORE_ADDR addr)
@@ -328,11 +329,10 @@ has_client_breakpoint_at (CORE_ADDR addr)
 
   for (cb = cs->client_breakpoints; cb != NULL; cb = cb->next)
     {
-      // TODO improve this; pc might be one insn ahead of break. 
-      if (addr >= cb->addr && addr <= cb->addr + 8)
+      if (addr == cb->addr)
 	{
 	  if (debug_threads)
-	    debug_printf ("%s:%d fd=%d return true at %#lx\n", 
+	    debug_printf ("%s:%d fd=%d return true at %#lx\n",
 			  __FUNCTION__, __LINE__, cs->file_desc, (long unsigned)cb->addr);
 	  return 1;
 	}
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 2ca0a9e..98e1b4d 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -150,8 +150,8 @@ 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);
+      if (notify_clients (buf))
+	putpkt_notif (buf);
     }
 }
 
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 6639b3f..b0206c6 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -85,9 +85,11 @@ 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, pending_notifier};
+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", "notifier"};
-char *packet_types_str[] = {"other", "vContc", "vConts","vContt","vStopped","vRun", "vAttach"};
+enum nonstop_pending_types {no_notifier_pending, pending_notifier, pending_notified};
+char *nonstop_pending_types_str[] = {"", "notifier", "notified"};
+char *packet_types_str[] = {"other", "vContc", "vConts","vContt","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", ""};
 
 
@@ -173,7 +175,7 @@ set_client_state (gdb_fildes_t fd)
 
 /* Add breakpoint ADDR to the per client breakpoint list */
 
-void
+static void
 add_client_breakpoint (CORE_ADDR addr)
 {
   struct client_breakpoint *cb;
@@ -201,7 +203,7 @@ add_client_breakpoint (CORE_ADDR addr)
 
 /* Remove ADDR from the per client breakpoint list */
 
-void
+static void
 delete_client_breakpoint (CORE_ADDR addr)
 {
   /* TODO gdb_remove_breakpoint removes breakpoints when we expect them
@@ -243,7 +245,6 @@ static int attached_to_same_proc (client_state *cs1, client_state *cs2)
 }
 
   
-
 /* Free client state CS; considering the corresponding server state */
 
 static void free_client_state (client_state *cs)
@@ -269,7 +270,7 @@ static void free_client_state (client_state *cs)
 /* Dump the client state list for debugging purposes */
 
 static void dump_stop_queue(const char*,const char*);
-void
+static void
 dump_client_state (const char *function, const char *comment)
 {
   client_state *save_cs = get_client_state();
@@ -302,7 +303,7 @@ dump_client_state (const char *function, const char *comment)
 	debug_printf ("  *");
       else
 	debug_printf ("   ");
-      debug_printf ("%d %lu pc=%#lx #=%d %s %s %s %s\n",
+      debug_printf ("%d %lu pc=%#lx #=%d %s %s %s %s %s\n",
 		    cs->file_desc, 
 		    (long unsigned)general_thread.pid,
 		    (long unsigned)pc,
@@ -310,6 +311,7 @@ dump_client_state (const char *function, const char *comment)
 		    packet_types_str[cs->packet_type], 
 		    packet_types_str[cs->last_packet_type], 
 		    pending_types_str[cs->pending],
+		    nonstop_pending_types_str[cs->nonstop_pending],
 		    last_status_kind);
     }
   client_states.current_cs = save_cs;
@@ -318,7 +320,7 @@ dump_client_state (const char *function, const char *comment)
 
 /* Add another client for PID to the 1 server -> N client list. */
 
-client_state *
+static int
 add_client_by_pid (int pid)
 {
   client_state *cs = get_client_state();
@@ -327,22 +329,24 @@ add_client_by_pid (int pid)
     {
       if (cs != matched_cs && matched_cs->ss->general_thread_.pid == pid)
 	{
+	  // Do clients all/non stop modes match?
+	  if (cs->non_stop_ ^ matched_cs->non_stop_)
+	    return -1;
 	  /* 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;
+	  return 1;
 	}
     }
-  return NULL;
+  return 0;
 }
 
 
 /* Return the first active client state */
 
-client_state*
+static client_state*
 get_first_client (void)
 {
   client_state *cs;
@@ -354,7 +358,7 @@ get_first_client (void)
   return client_states.first;
 }
 
-gdb_fildes_t
+static gdb_fildes_t
 get_first_client_fd (void)
 {
   client_state *cs = get_first_client ();
@@ -418,9 +422,9 @@ delete_client_state (gdb_fildes_t fd)
 }
 
 
-/* Return the packet type for last CS packets */
+/* Return the packet type for client packet CS */
 
-packet_types
+static packet_types
 get_packet_type (client_state *cs)
 {
   char own_packet;
@@ -444,8 +448,6 @@ get_packet_type (client_state *cs)
 	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;
       else if (strncmp (in_buffer, "vAttach", 4) == 0)
@@ -459,7 +461,7 @@ static int queue_stop_reply_callback (struct inferior_list_entry *entry, void *a
 
 /* Belatedly reply to client CS, which is waiting on a packet reply. */
 
-void
+static 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;
@@ -481,33 +483,10 @@ resolve_waiter (client_state *cs, client_state *waitee_cs)
 	strcpy (own_buffer, "?");
 	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 = 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;
-		/* TODO this may incorrectly precede check_stopped_by_breakpoint adjustment of the pc */
-		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_);
-
-		debug_printf ("%s:%d Notifying fd=%d\n", __FUNCTION__, __LINE__, cs->file_desc);
-		notif_write_event (&notif_stop, notif_buf);
-	      }
-	    else if (last_status.kind != TARGET_WAITKIND_EXITED)
-	      cs->pending = pending_notifier;
+	    if (last_status.kind != TARGET_WAITKIND_EXITED)
+	      cs->nonstop_pending = pending_notifier;
 	  }
-	else if (last_status.kind != TARGET_WAITKIND_EXITED
-	         && cs->last_cont_ptid.pid == cs->ss->last_ptid_.pid)
+	else if (last_status.kind != TARGET_WAITKIND_EXITED)
 	  {
 	    /* reply to vContc with a status */
 	    strcpy (own_buffer, "?");
@@ -532,39 +511,12 @@ resolve_waiter (client_state *cs, client_state *waitee_cs)
     {
       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_);
-
-	      if (debug_threads)
-		debug_printf ("%s:%d Notifying fd=%d\n", __FUNCTION__, __LINE__, cs->file_desc);
-	      notif_write_event (&notif_stop, notif_buf);
-	      if (last_status.kind != TARGET_WAITKIND_STOPPED)
-		cs->pending = pending_notifier;
-	    }
-
+	  if (last_status.kind != TARGET_WAITKIND_EXITED)
+	    cs->nonstop_pending = pending_notifier;
 	}
       else if (last_status.kind != TARGET_WAITKIND_EXITED)
 	{
-	  /* reply to vConts with a status */
-	  strcpy (own_buffer, "?");
-	  handle_status (own_buffer);
-	  putpkt (own_buffer);
+	  putpkt (waitee_cs->own_buffer_);
 	}
       else if (last_status.kind == TARGET_WAITKIND_EXITED)
 	{
@@ -611,7 +563,7 @@ resolve_waiter (client_state *cs, client_state *waitee_cs)
 }
 
 
-void
+static void
 analyze_group (client_state *current_cs, int *have_nonwaiter)
 {
   client_state *csi;
@@ -658,6 +610,8 @@ setup_multiplexing (client_state *current_cs)
   dump_client_state (__FUNCTION__, "");
 
   current_cs->attached_to_client = 1;
+  if (current_cs->packet_type == vContc || current_cs->packet_type == vConts)
+    current_cs->nonstop_pending = none_pending;
 
   for (same_pid_cs = client_states.first; 
        same_pid_cs != NULL; 
@@ -697,6 +651,8 @@ 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;
+		set_client_state (same_pid_cs->file_desc);
+		current_cs = same_pid_cs;
 		break;
 	      }
 	    case /* current_cs->packet_type */ vConts:
@@ -769,7 +725,7 @@ setup_multiplexing (client_state *current_cs)
 	     packet now; it will be replied to later in do_multiplexing */
 
 	  if (current_cs->ss->last_status_exited != have_exit
-	      && !(current_cs->catch_syscalls && current_cs->packet_type != vContc))
+	      && (!current_cs->catch_syscalls || current_cs->packet_type == vContc))
 	    {
 	      dump_client_state (__FUNCTION__, "* waiting");
 	      current_cs->last_cont_ptid = current_cs->ss->general_thread_;
@@ -784,13 +740,14 @@ setup_multiplexing (client_state *current_cs)
 }
 
 
-void
+int
 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);
+  int have_syscall = 0;
 
   debug_printf ("%s DBG %s %s\n", __FUNCTION__, target_waitstatus_to_string (&last_status), own_buffer);
   dump_client_state (__FUNCTION__, "");
@@ -809,21 +766,39 @@ notify_clients (char *buffer)
       {
 	case TARGET_WAITKIND_SYSCALL_ENTRY:
 	case TARGET_WAITKIND_SYSCALL_RETURN:
+	  have_syscall = 1;
 	  break;
 	case TARGET_WAITKIND_EXITED:
 	  set_client_state (same_pid_cs->file_desc);
 	  putpkt (okay_buf);
 	  putpkt_notif (buffer);
 	  set_client_state (save_client_fd);
-	  return;
+	  return 1;
+        case TARGET_WAITKIND_STOPPED:
+	  if (same_pid_cs->pending == pending_cont_waiter && same_pid_cs->packet_type == vContc)
+	    {
+	      CORE_ADDR point_addr;
+	      struct regcache *regcache = same_pid_cs->ss->current_thread_->regcache_data;
+	      point_addr = (*the_target->read_pc) (regcache);
+	      if (has_client_breakpoint_at (point_addr))
+		same_pid_cs->nonstop_pending = pending_notifier;
+	    }
+	  
 	default:
 	  /* A syscall client only gets a syscall packet */
 	  if (save_client_cs->catch_syscalls)
-	    set_client_state (same_pid_cs->file_desc);
-	  return;
+	    {
+	      set_client_state (same_pid_cs->file_desc);
+	      return 1;
+	    }
       }
 
-      if (same_pid_cs->pending == pending_notifier)
+      // syscall continue was erroneously caught by by a non syscall client
+      if (save_client_cs->packet_type == other_packet
+	       && same_pid_cs->catch_syscalls)
+	return 0;
+
+      if (same_pid_cs->nonstop_pending == pending_notifier)
 	{
 	  /* Also send the notification to the attached client */
 	  set_client_state (same_pid_cs->file_desc);
@@ -833,8 +808,15 @@ notify_clients (char *buffer)
 	  putpkt_notif (buffer);
 	  set_client_state (save_client_fd);
 	  same_pid_cs->pending = none_pending;
+	  same_pid_cs->nonstop_pending = pending_notified;
 	}
     }
+  if (have_syscall && !save_client_cs->catch_syscalls)
+    return 0;
+  else if (save_client_cs->nonstop_pending == pending_notified)
+    return 0;
+  else
+    return 1;
 }
 
 
@@ -876,6 +858,7 @@ do_multiplexing (client_state *current_cs)
 	{
 	  resolve_waiter (current_cs, NULL);
 	  dump_client_state (__FUNCTION__, "resolved vContt");
+	  current_cs->last_packet_type = other_packet;
 	  return 0;
 	}
     default: /* fall through */
@@ -952,24 +935,29 @@ do_multiplexing (client_state *current_cs)
 		  if (get_first_thread () != NULL)
 		    {
 		      struct regcache *regcache;
-		      struct thread_info *thread;
-		      CORE_ADDR pc;
+		      CORE_ADDR point_addr = 0;
 
-		      if (non_stop)
+		      if ((*the_target->stopped_by_watchpoint)())
+			point_addr = (*the_target->stopped_data_address) ();
+		      else
 			{
-			  thread = current_thread;
 			  regcache = client_states.current_cs->ss->current_thread_->regcache_data;
+			  point_addr = (*the_target->read_pc) (regcache);
 			}
-		      else
+		      if (point_addr)
 			{
-			  thread = find_thread_ptid (last_ptid);
-			  regcache = client_states.current_cs->ss->current_thread_->regcache_data;
+			  current_cs_has_bp = has_client_breakpoint_at (point_addr);
+			  waiter_cs = set_client_state (same_pid_cs->file_desc);
+			  /* Does found client have a breakpoint at PC? */
+			  same_pid_cs_has_bp = has_client_breakpoint_at (point_addr);
+			}
+		      else if (current_cs->packet_type == vConts
+			       && last_status.kind == TARGET_WAITKIND_STOPPED)
+			{
+			  /* there is no target->stopped_by_single_step so just assume that */
+			  waiter_cs = set_client_state (same_pid_cs->file_desc);
+			  same_pid_cs_has_bp = 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? */
-		      same_pid_cs_has_bp = has_client_breakpoint_at (pc);
 		    }
 		}
 
@@ -977,11 +965,10 @@ do_multiplexing (client_state *current_cs)
 		{
 		  /* Belatedly reply to the waiter client */
 		  resolve_waiter (waiter_cs, current_cs);
-		  if (current_cs->pending != pending_notifier)
-		    current_cs->pending = none_pending;
+		  current_cs->pending = none_pending;
 		  if (!current_cs_has_bp)
 		    waiter_cs->pending = pending_waitee;
-		  else if (waiter_cs->pending != pending_notifier)
+		  else 
 		    waiter_cs->pending = none_pending;
 		  /* If the waitee did not reach the breakpoint then it needs to wait */
 		  if (!current_cs_has_bp)
@@ -1002,7 +989,7 @@ do_multiplexing (client_state *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;
+	    same_pid_cs->nonstop_pending = pending_notifier;
 	  current_cs = set_client_state (current_cs->file_desc);
 	} /* switch same_pid_cs->pending */
     }
@@ -3704,9 +3691,16 @@ static int
 handle_v_attach (char *own_buf)
 {
   int pid;
+  int status;
 
   pid = strtol (own_buf + 8, NULL, 16);
-  if (add_client_by_pid (pid))
+  status = add_client_by_pid(pid);
+  if (status < 0)
+    {
+      sprintf (own_buf, "E.Attached client non-stop/all-stop mode does not match the running client.");
+      return 0;
+    }
+  else if (status == 1)
     {
       if (! non_stop)
 	{
@@ -5407,7 +5401,7 @@ handle_target_event (int err, gdb_client_data client_data)
 	      if (attached_to_same_proc (save_csi, csi))
 		{
 		  save_csi = client_states.current_cs;
-		  csi->pending = pending_notifier;
+		  csi->nonstop_pending = pending_notifier;
 		  break;
 		}


hooks/post-receive
--
Repository for Project Archer.


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

only message in thread, other threads:[~2016-06-08 20:28 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-08 20:28 [SCM] scox/globalstate: Push multiple client non-stop handling into notify_clients 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).