diff mbox series

[v2,28/38] gdbserver: add multi-threaded start/stop helper functions

Message ID 20220329154931.493851-29-npiggin@gmail.com
State New
Headers show
Series gdbserver multi-threaded debugging and POWER9/10 support | expand

Commit Message

Nicholas Piggin March 29, 2022, 3:49 p.m. UTC
Prepare for multi threaded debugging (in gdb's "all-stop" mode) by
providing helpers that stop and start all target threads.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 src/pdbgproxy.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 85 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c
index 1d33352..139b29e 100644
--- a/src/pdbgproxy.c
+++ b/src/pdbgproxy.c
@@ -43,6 +43,7 @@ 
 
 #define TEST_SKIBOOT_ADDR 0x40000000
 
+static bool all_stopped = true; /* must be started with targets stopped */
 static struct pdbg_target *thread_target = NULL;
 static struct pdbg_target *adu_target;
 static struct timeval timeout;
@@ -542,10 +543,50 @@  static void v_conts(uint64_t *stack, void *priv)
 	send_response(fd, TRAP);
 }
 
+static void __start_all(void)
+{
+	struct pdbg_target *target;
+
+	if (!all_stopped)
+		PR_ERROR("starting while not all stopped\n");
+
+	for_each_path_target_class("thread", target) {
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
+		if (thread_start(target)) {
+			PR_ERROR("Could not start thread %s\n",
+				 pdbg_target_path(target));
+		}
+	}
+
+	all_stopped = false;
+}
+
+static void start_all(void)
+{
+	struct pdbg_target *target;
+
+	for_each_path_target_class("thread", target) {
+		struct thread_state status;
+
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
+		target->probe(target);
+		status = thread_status(target);
+		if (!status.quiesced)
+			PR_ERROR("starting thread not quiesced\n");
+	}
+
+	__start_all();
+}
+
 #define VCONT_POLL_DELAY 100000
 static void v_contc(uint64_t *stack, void *priv)
 {
-	thread_start(thread_target);
+	start_all();
+
 	state = SIGNAL_WAIT;
 	poll_interval = 1;
 }
@@ -603,13 +644,55 @@  static bool thread_check_attn(struct pdbg_target *target)
 	return false;
 }
 
+static void __stop_all(void)
+{
+	struct pdbg_target *target;
+
+	if (all_stopped)
+		PR_ERROR("stopping while all stopped\n");
+
+	for_each_path_target_class("thread", target) {
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
+		if (thread_stop(target)) {
+			PR_ERROR("Could not stop thread %s\n",
+				 pdbg_target_path(target));
+			/* How to fix? */
+		}
+	}
+
+	all_stopped = true;
+}
+
+static void stop_all(void)
+{
+	struct pdbg_target *target;
+
+	__stop_all();
+
+	for_each_path_target_class("thread", target) {
+		struct thread_state status;
+
+		if (pdbg_target_status(target) != PDBG_TARGET_ENABLED)
+			continue;
+
+		target->probe(target);
+		status = thread_status(target);
+		if (!status.quiesced) {
+			PR_ERROR("Could not quiesce thread\n");
+			/* How to fix? */
+		}
+	}
+}
+
 static void interrupt(uint64_t *stack, void *priv)
 {
 	struct thread_state status;
 
 	PR_INFO("Interrupt from gdb client\n");
 
-	thread_stop(thread_target);
+	stop_all();
 
 	status = thread_status(thread_target);
 	if (!(status.quiesced)) {