[PATCH v2 15/47] Windows gdb+gdbserver: Move suspending thread to when returning event

Pedro Alves
2025-05-19T13:30:10Z

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 | 12 +++++-------
gdbserver/win32-low.cc | 5 +++++
2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 9b8bb66d700..61bccb365d0 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -702,7 +702,6 @@ windows_nat_target::fetch_registers (struct regcache *regcache, int r)
{
if (context->ContextFlags == 0)
{
- th->suspend ();
context->ContextFlags = WindowsContext<decltype(context)>::all;
CHECK (get_thread_context (th->h, context));
}
@@ -1229,12 +1228,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 ([&] ()
@@ -1713,6 +1706,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 c99248d37cb..a23a41b9c02 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -1194,6 +1194,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:
--
2.49.0