public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  scox/globalstate: Support multiple clients that use upstream syscall support.
@ 2016-02-08 15:40 scox
  0 siblings, 0 replies; only message in thread
From: scox @ 2016-02-08 15:40 UTC (permalink / raw)
  To: archer-commits

The branch, scox/globalstate has been updated
       via  c94dca1a4db81df5753f2ec7c42b416920908897 (commit)
      from  8cb7f5b73460dd9ed08cc78a382d60e52c8f2781 (commit)

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

- Log -----------------------------------------------------------------
commit c94dca1a4db81df5753f2ec7c42b416920908897
Author: Stan Cox <scox@redhat.com>
Date:   Mon Feb 8 10:38:17 2016 -0500

    Support multiple clients that use upstream syscall support.
    
    	* server.c (waitkind_str):  New
    	(set_client_state): Copy client state for multiple client case.
    	(attached_to_same_proc):  New
    	(resolve_waiter): Handle exited case.
    	(setup_multiplexing): Refactor.
    	(do_multiplexing): Refactor.  Handle syscall case.
    	* server.h (catch_syscalls, last_cont_ptid, last_cont_waitstatus): New.

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

Summary of changes:
 gdb/gdbserver/ChangeLog                   |   10 +
 gdb/gdbserver/nto-low.c                   |    1 +
 gdb/gdbserver/server.c                    |  466 +++++++++++++++++++----------
 gdb/gdbserver/server.h                    |    3 +
 gdb/gdbserver/spu-low.c                   |    1 +
 gdb/gdbserver/win32-low.c                 |    1 +
 gdb/remote.c                              |    2 +-
 gdb/testsuite/ChangeLog                   |    4 +
 gdb/testsuite/gdb.server/multi-client.exp |  117 +++++++-
 9 files changed, 425 insertions(+), 180 deletions(-)

First 500 lines of diff:
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 5eb6384..88d55fd 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,13 @@
+2016-02-06  Stan Cox  <scox@redhat.com>
+
+	* server.c (waitkind_str):  New
+	(set_client_state): Copy client state for multiple client case.
+	(attached_to_same_proc):  New
+	(resolve_waiter): Handle exited case.
+	(setup_multiplexing): Refactor.
+	(do_multiplexing): Refactor.  Handle syscall case.
+	* server.h (catch_syscalls, last_cont_ptid, last_cont_waitstatus): New.
+
 2016-01-14  Yao Qi  <yao.qi@linaro.org>
 
 	* linux-aarch32-low.c (thumb2_breakpoint): Make it static.
diff --git a/gdb/gdbserver/nto-low.c b/gdb/gdbserver/nto-low.c
index ce3b8e4..3e945a5 100644
--- a/gdb/gdbserver/nto-low.c
+++ b/gdb/gdbserver/nto-low.c
@@ -979,6 +979,7 @@ static struct target_ops nto_target_ops = {
   NULL, /* core_of_thread */
   NULL, /* read_loadmap */
   NULL, /* process_qsupported */
+  NULL, /* supports_catch_syscall */
   NULL, /* supports_tracepoints */
   NULL, /* read_pc */
   NULL, /* write_pc */
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index dc9977c..378b174 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -86,8 +86,9 @@ 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"};
+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", ""};
 
 
 /* Return the current client state */
@@ -142,33 +143,32 @@ set_client_state (gdb_fildes_t fd)
     }
 
   /* add client state S for fd F */
-  client_states.current_cs = XCNEW (client_state);
-  *client_states.current_cs = *csidx;
-  client_states.current_cs->ss = XCNEW (server_state);
-  *client_states.current_cs->ss = *csidx->ss;
-  cs = client_states.current_cs;
+  cs = XCNEW (client_state);
+  *(cs) = *(csidx);
+  cs->ss = XCNEW (server_state);
+  *(cs->ss) = *(csidx->ss);
+  cs->file_desc = fd;
   cs->packet_type = other_packet;
   cs->last_packet_type = other_packet;
   cs->pending = none_pending;
+  cs->in_buffer_ = NULL;
+  cs->own_buffer_ = xmalloc (PBUFSIZ + 1);
   cs->client_breakpoints = NULL;
-  in_buffer = NULL;
-  wrapper_argv = NULL;
-  get_client_state()->ss->attach_count_ = 0;
-  cont_thread = null_ptid;
-  general_thread = null_ptid;
-  signal_pid = 0;
-  last_ptid = null_ptid;
-  last_status.kind = TARGET_WAITKIND_IGNORE;
-  current_thread = NULL;
-  all_processes.head = NULL;
-  all_processes.tail = NULL;
-  all_threads.head = NULL;
-  all_threads.tail = NULL;
-  client_states.current_cs->file_desc = fd;
-  own_buffer = xmalloc (PBUFSIZ + 1);
+  client_states.current_cs = cs;
+  cs->ss->attach_count_ = 0;
+  cs->ss->cont_thread_ = null_ptid;
+  cs->ss->general_thread_ = null_ptid;
+  cs->ss->signal_pid_ = 0;
+  cs->ss->last_ptid_ = null_ptid;
+  cs->ss->last_status_.kind = TARGET_WAITKIND_IGNORE;
+  cs->ss->current_thread_ = NULL;
+  cs->ss->all_processes_.head = NULL;
+  cs->ss->all_processes_.tail = NULL;
+  cs->ss->all_threads_.head = NULL;
+  cs->ss->all_threads_.tail = NULL;
   client_states.current_fd = fd;
   csidx->next = client_states.current_cs;
-  return client_states.current_cs;
+  return cs;
 }
 
 /* Add breakpoint ADDR to the per client breakpoint list */
@@ -236,6 +236,14 @@ delete_client_breakpoint (CORE_ADDR addr)
 }
 
 
+static int attached_to_same_proc (client_state *cs1, client_state *cs2)
+{
+  return cs1->file_desc != -1 && cs2->file_desc != -1 
+    && cs1 != cs2 && cs1->ss == cs2->ss;
+}
+
+  
+
 /* Free client state CS; considering the corresponding server state */
 
 static void free_client_state (client_state *cs)
@@ -244,7 +252,8 @@ static void free_client_state (client_state *cs)
   client_state *csi;
   for (csi = client_states.first; csi != NULL; csi = csi->next)
     {
-      if (ptid_equal (csi->ss->general_thread_, null_ptid) && csi != cs && csi->ss == cs->ss)
+      if (ptid_equal (csi->ss->general_thread_, null_ptid) 
+	  && attached_to_same_proc (cs, csi))
 	break;
     }
   delete_client_breakpoint (0);
@@ -272,10 +281,17 @@ dump_client_state (const char *function, const char *comment)
   debug_printf ("***Begin Dumping client state from %s %s\n", function, comment);
   for (cs = client_states.first; cs != NULL; cs = cs->next)
     {
+      char *last_status_kind;
       client_states.current_cs = cs;
+
       if (cs->file_desc == -1)
 	continue;
-      debug_printf ("%d %#lx(%d)/%#lx/%#lx #=%d %s %s %s\n",
+
+      if (cs->ss->last_status_.kind < (sizeof (waitkind_str) / sizeof (void*)))
+	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",
 		    cs->file_desc, 
 		    (long unsigned)general_thread.pid, 
 		    (int)general_thread.pid, 
@@ -284,7 +300,8 @@ dump_client_state (const char *function, const char *comment)
 		    cs->ss->attach_count_,
 		    packet_types_str[cs->packet_type], 
 		    packet_types_str[cs->last_packet_type], 
-		    pending_types_str[cs->pending]);
+		    pending_types_str[cs->pending],
+		    last_status_kind);
     }
   debug_printf ("***End Dumping client state\n");
   client_states.current_cs = save_cs;
@@ -419,20 +436,25 @@ get_packet_type (client_state *cs)
 
 static int queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg);
 
-/* Belatedly reply to last CS previously received and waited on packet  */
+/* Belatedly reply to client CS, which is waiting on a packet reply. */
 
 void
-resolve_waiter (client_state *cs)
+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;
 
-  if (debug_threads)
-    debug_printf ("%s:%d fd=%d %s\n", __FUNCTION__, __LINE__, cs->file_desc, packet_types_str[this_packet_type]);
-
   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
@@ -456,13 +478,26 @@ resolve_waiter (client_state *cs)
 		notif_write_event (&notif_stop, notif_buf);
 	      }
 	  }
-	else if (last_status.kind != TARGET_WAITKIND_EXITED)
+	else if (last_status.kind != TARGET_WAITKIND_EXITED
+	         && cs->last_cont_ptid.pid == cs->ss->last_ptid_.pid)
 	  {
 	    /* reply to vContc with a status */
 	    strcpy (own_buffer, "?");
 	    handle_status (own_buffer);
 	    putpkt (own_buffer);
 	  }
+	else if (last_status.kind == TARGET_WAITKIND_EXITED)
+	  {
+	    /* Is this the same process we are waiting on? */
+	    if (cs->last_cont_ptid.pid != last_ptid.pid)
+	      {
+		prepare_resume_reply (own_buffer, cs->last_cont_ptid,
+				      &cs->last_cont_waitstatus);
+		putpkt (own_buffer);
+	      }
+	    else
+	      putpkt (waitee_cs->own_buffer_);
+	  }
 	break;
       }
   case vConts:
@@ -514,114 +549,153 @@ resolve_waiter (client_state *cs)
 /* Determine the state of client CS with respect to other clients connected to the same server process */
 
 static int
-setup_multiplexing (client_state *cs, char *ch)
+setup_multiplexing (client_state *current_cs)
 {
-  client_state *csidx = NULL;
+  /***
+  If we have two independent clients 4 and 7 and 4 is the current
+  client with a vConts packet then we change both client's state
+  BEFORE
+  packet_type last_packet_type pending last_status_.kind
+  4 vConts    vConts	   not-waiting stopped
+  7 other     vAttach	   not-waiting stopped
+  AFTER
+  4 vConts    vConts	   step-waiter stopped
+  7 other     vAttach	   waitee      stopped
+
+  If we have two dependent clients 4 and 7 and 4 is the current client with a
+  vContc packet then we change nothing here.  process_serial_event will handle
+  the vContc then do_multiplexing will decide to either continue with client 4
+  or wakeup and continue with client 7.
+  4 vContc vConts waitee stopped
+  7 vContc vContc waiter stopped
+  ***/
+
+  client_state *same_pid_cs = NULL;
 
   dump_client_state (__FUNCTION__, "");
 
-  cs->attached_to_client = 1;
+  current_cs->attached_to_client = 1;
 
-  for (csidx = client_states.first; csidx != NULL; csidx = csidx->next)
+  for (same_pid_cs = client_states.first; 
+       same_pid_cs != NULL; 
+       same_pid_cs = same_pid_cs->next)
     {
-      /* another client is attached to the cs process */
-      if (csidx->file_desc != -1 && csidx != cs && cs->ss == csidx->ss)
+      if (! attached_to_same_proc (current_cs, same_pid_cs))
+	continue;
+      switch (same_pid_cs->pending)
 	{
-    	  /* found a client that has nothing pending */
-	  if (!csidx->pending)
+	case 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)
 	    {
-	      /* The cs vContc will wait; found csidx will proceed */
-	      if (cs->packet_type == vContc)
+	    case vContc:
+	      if (current_cs->last_packet_type != vRun)
 		{
-		  if (cs->last_packet_type != vRun)
-		    {
-		      cs->pending = pending_cont_waiter;
-		      csidx->pending = pending_waitee;
-		    }
+		  current_cs->pending = pending_cont_waiter;
+		  same_pid_cs->pending = pending_waitee;
 		}
-	      /* TODO else if (cs->packet_type == vContt) */
-	      else if (cs->packet_type == vConts)
+	      break;
+	      /* TODO else if (current_cs->packet_type == vContt) */
+	    case vConts:
+	      if (same_pid_cs->last_packet_type != vContt)
 		{
-		  if (csidx->last_packet_type != vContt)
-		    {
-		      cs->pending = pending_step_waiter;
-		      csidx->pending = pending_waitee;
-		    }
+		  current_cs->pending = pending_step_waiter;
+		  same_pid_cs->pending = pending_waitee;
 		}
 	    }
-	  /* Current client is continuing and found another waiter client */
-	  else if (csidx->pending == pending_cont_waiter
-		   && cs->packet_type == vContc)
+	  break;
+	case pending_cont_waiter:
+	  switch (current_cs->packet_type)
 	    {
-	      client_state *csi;
-	      int waitee_count = 0;
+	      /* Current client is continuing and found another waiter client */
+	    case 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 (csi->ss == cs->ss && csi->pending == pending_waitee
-		      && csi->file_desc != cs->file_desc)
-		    waitee_count = 1;
-		}
-
-	      /* Don't want to deadlock on everyone waiting */
-	      if (cs->pending == pending_waitee && waitee_count > 0)
-		cs->pending = pending_cont_waiter;
+		/* 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;
+		  }
+
+		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)
+		  current_cs->pending = pending_cont_waiter;
+	      }
 	    }
 	}
-    }
+    } /* for same_pid_cs */
+  
 
-  /* 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_stop)
+  switch (current_cs->pending)
     {
-      if (cs->last_packet_type != vRun 
-	  && cs->last_packet_type != vStopped
-	  && cs->ss->last_status_exited != have_exit)
+    case pending_cont_waiter:
+    case pending_step_waiter:
+    case pending_stop:
+      
+      switch (current_cs->last_packet_type)
 	{
-	  dump_client_state (__FUNCTION__, "return 0");
-	  return 0;		/* Reply to packet later */
+	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");
+	      current_cs->last_cont_ptid = current_cs->ss->general_thread_;
+	      current_cs->last_cont_waitstatus = current_cs->ss->last_status_;
+	      return 0;		/* Reply to packet later */
+	    }
 	}
+    default:
+      dump_client_state (__FUNCTION__, "return 1");
+      return 1;			/* Reply to packet now */
     }
-  dump_client_state (__FUNCTION__, "return 1");
-  return 1;			/* Reply to packet now */
 }
 
 
 static void
-notify_clients (client_state *waitee_cs)
+notify_clients (client_state *current_cs)
 {
-  client_state *csidx = NULL;
+  client_state *same_pid_cs = NULL;
 
-  if (! (waitee_cs->pending == pending_waitee
-	 && waitee_cs->last_packet_type == vStopped
-	 && waitee_cs->ss->last_status_exited == have_exit))
+  if (! (current_cs->pending == pending_waitee
+	 && current_cs->last_packet_type == vStopped
+	 && current_cs->ss->last_status_exited == have_exit))
     return;
 
-  for (csidx = client_states.first; csidx != NULL; csidx = csidx->next)
+  for (same_pid_cs = client_states.first; 
+       same_pid_cs != NULL; 
+       same_pid_cs = same_pid_cs->next)
     {
+      char *out_buf = alloca (64);
+
       /* 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)
+      if (! attached_to_same_proc (current_cs, same_pid_cs))
 	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);
+
+      same_pid_cs->ss->last_status_exited = sent_exit;
+      set_client_state (same_pid_cs->file_desc);
+      same_pid_cs->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 (current_cs->file_desc);
   return;
 }
 
@@ -629,58 +703,126 @@ notify_clients (client_state *waitee_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 *waitee_cs, char ch)
+do_multiplexing (client_state *current_cs, char ch)
 {
-  client_state *csidx = NULL;
+  /***
+  If we have two dependent clients 4 and 7 and 4 is the current client with a
+  vContc packet then if the handling of vContc resulted in hitting a client 7
+  breakpoint then we wakeup client 7.
+
+  BEFORE
+  packet_type last_packet_type pending last_status_.kind
+  4 vContc    vConts		waitee stopped
+  7 vContc    vContc		waiter stopped
+  AFTER
+  4 vContc    vConts		waiter stopped
+  7 vContc    vContc		waitee stopped
+
+  Otherwise we continue with client 4.
+  4 vContc    vConts		waitee stopped
+  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;
 
-  if (waitee_cs->last_packet_type == vAttach && waitee_cs->packet_type == vContt)
+  switch (current_cs->packet_type)
     {
-      resolve_waiter (waitee_cs);
-      dump_client_state (__FUNCTION__, "resolved vContt");
-      return 0;
+    case other_packet:
+      break;
+    case vContt:
+      if (current_cs->last_packet_type == vAttach)
+	{
+	  resolve_waiter (current_cs, NULL);


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


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

only message in thread, other threads:[~2016-02-08 15:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-08 15:40 [SCM] scox/globalstate: Support multiple clients that use upstream syscall 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).