[10/34] Windows gdb+gdbserver: Move suspending thread to when returning event

Message ID 20240507234233.371123-11-pedro@palves.net
State New
Headers
Series Windows non-stop mode |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed

Commit Message

Pedro Alves May 7, 2024, 11:42 p.m. UTC
  The current code suspends a thread just before calling
GetThreadContext.  You can only call GetThreadContext if the thread is
suspended.  But, after WaitForDebugEvent, all threads are implicitly
suspended.  So I don't think we even needed to call SuspendThread
explictly at all before our GetThreadContext calls.

However, suspending threads when we're about to present a stop to gdb
simplifies adding non-stop support later.  This way, the windows
SuspendThread state corresponds to whether a thread is suspended or
resumed from the core's perspective.  Curiously, I noticed that Wine's
winedbg does something similar:
https://github.com/wine-mirror/wine/blob/234943344f7495d1e072338f0e06fa2d5cbf0aa1/programs/winedbg/gdbproxy.c#L651

This makes it much easier to reason about a thread's suspend state,
and simplifies adding non-stop mode later on.

Change-Id: Ifd6889a8afc041fad33cd1c4500e38941da6781b
---
 gdb/windows-nat.c      | 13 +++++--------
 gdbserver/win32-low.cc |  5 +++++
 2 files changed, 10 insertions(+), 8 deletions(-)
  

Patch

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 9730377d6fc..aa531c4208a 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -710,7 +710,6 @@  windows_nat_target::fetch_registers (struct regcache *regcache, int r)
     {
       if (th->wow64_context.ContextFlags == 0)
 	{
-	  th->suspend ();
 	  th->wow64_context.ContextFlags = CONTEXT_DEBUGGER_DR;
 	  CHECK (Wow64GetThreadContext (th->h, &th->wow64_context));
 	}
@@ -720,7 +719,6 @@  windows_nat_target::fetch_registers (struct regcache *regcache, int r)
     {
       if (th->context.ContextFlags == 0)
 	{
-	  th->suspend ();
 	  th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
 	  CHECK (GetThreadContext (th->h, &th->context));
 	}
@@ -1320,12 +1318,6 @@  windows_nat_target::windows_continue (DWORD continue_status, int id,
 	  }
 	th->resume ();
       }
-    else
-      {
-	/* When single-stepping a specific thread, other threads must
-	   be suspended.  */
-	th->suspend ();
-      }
 
   std::optional<unsigned> err;
   do_synchronously ([&] ()
@@ -1816,6 +1808,11 @@  windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
 		  th->stopped_at_software_breakpoint = true;
 		  th->pc_adjusted = false;
 		}
+
+	      /* All-stop, suspend all threads until they are
+		 explicitly resumed.  */
+	      for (auto &thr : windows_process.thread_list)
+		thr->suspend ();
 	    }
 
 	  return result;
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index 0d67cd984e4..8dd8f21330d 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -1226,6 +1226,11 @@  win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
 	    OUTMSG2 (("Child Stopped with signal = %d \n",
 		      ourstatus->sig ()));
 	    maybe_adjust_pc ();
+
+	    /* All-stop, suspend all threads until they are explicitly
+	       resumed.  */
+	    for_each_thread (suspend_one_thread);
+
 	    return debug_event_ptid (&windows_process.current_event);
 	  }
 	default: