From 0ca912dfef6289f9d2cd7d70b7ec80883a9b4395 Mon Sep 17 00:00:00 2001 From: Markus Metzger Date: Tue, 25 Aug 2015 13:42:39 +0200 Subject: [PATCH] btrace: resume all requested threads The record targets are implicitly schedlocked. They only step the current thread and keep other threads where they are. Change record btrace to step all requested threads in to_resume. For maintenance and debugging, we keep the old behaviour when the target below is not non-stop. Enable with "maint set target-non-stop on". gdb/ * record-btrace.c (record_btrace_resume_thread): A move request overwrites a previous move request. (record_btrace_find_resume_thread): Removed. (record_btrace_resume): Resume all requested threads. --- gdb/ChangeLog | 7 +++++ gdb/record-btrace.c | 73 ++++++++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7c927bb9400..d6901c8835b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2015-09-18 Markus Metzger + + * record-btrace.c (record_btrace_resume_thread): A move request + overwrites a previous move request. + (record_btrace_find_resume_thread): Removed. + (record_btrace_resume): Resume all requested threads. + 2015-09-18 Markus Metzger * record-btrace.c: Include vec.h. diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index bda9b7c87fc..c25b8f49b3c 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -1699,31 +1699,14 @@ record_btrace_resume_thread (struct thread_info *tp, btinfo = &tp->btrace; - if ((btinfo->flags & BTHR_MOVE) != 0) - error (_("Thread already moving.")); - /* Fetch the latest branch trace. */ btrace_fetch (tp); - /* A resume request overwrites a preceding stop request. */ - btinfo->flags &= ~BTHR_STOP; + /* A resume request overwrites a preceding resume or stop request. */ + btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP); btinfo->flags |= flag; } -/* Find the thread to resume given a PTID. */ - -static struct thread_info * -record_btrace_find_resume_thread (ptid_t ptid) -{ - struct thread_info *tp; - - /* When asked to resume everything, we pick the current thread. */ - if (ptid_equal (minus_one_ptid, ptid) || ptid_is_pid (ptid)) - ptid = inferior_ptid; - - return find_thread_ptid (ptid); -} - /* Start replaying a thread. */ static struct btrace_insn_iterator * @@ -1865,30 +1848,50 @@ static void record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step, enum gdb_signal signal) { - struct thread_info *tp, *other; + struct thread_info *tp; enum btrace_thread_flag flag; + ptid_t orig_ptid; DEBUG ("resume %s: %s%s", target_pid_to_str (ptid), execution_direction == EXEC_REVERSE ? "reverse-" : "", step ? "step" : "cont"); - /* Store the execution direction of the last resume. */ + orig_ptid = ptid; + + /* Store the execution direction of the last resume. + + If there is more than one to_resume call, we have to rely on infrun + to not change the execution direction in-between. */ record_btrace_resume_exec_dir = execution_direction; - tp = record_btrace_find_resume_thread (ptid); - if (tp == NULL) - error (_("Cannot find thread to resume.")); + /* For all-stop targets... */ + if (!target_is_non_stop_p ()) + { + /* ...we pick the current thread when asked to resume an entire process + or everything. */ + if (ptid_equal (minus_one_ptid, ptid) || ptid_is_pid (ptid)) + ptid = inferior_ptid; + + tp = find_thread_ptid (ptid); + if (tp == NULL) + error (_("Cannot find thread to resume.")); + + /* ...and we stop replaying other threads if the thread to resume is not + replaying. */ + if (!btrace_is_replaying (tp) && execution_direction != EXEC_REVERSE) + ALL_NON_EXITED_THREADS (tp) + record_btrace_stop_replaying (tp); + } - /* Stop replaying other threads if the thread to resume is not replaying. */ - if (!btrace_is_replaying (tp) && execution_direction != EXEC_REVERSE) - ALL_NON_EXITED_THREADS (other) - record_btrace_stop_replaying (other); + /* As long as we're not replaying, just forward the request. - /* As long as we're not replaying, just forward the request. */ + For non-stop targets this means that no thread is replaying. In order to + make progress, we may need to explicitly move replaying threads to the end + of their execution history. */ if (!record_btrace_is_replaying (ops) && execution_direction != EXEC_REVERSE) { ops = ops->beneath; - return ops->to_resume (ops, ptid, step, signal); + return ops->to_resume (ops, orig_ptid, step, signal); } /* Compute the btrace thread flag for the requested move. */ @@ -1897,15 +1900,11 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step, else flag = execution_direction == EXEC_REVERSE ? BTHR_RSTEP : BTHR_STEP; - /* At the moment, we only move a single thread. We could also move - all threads in parallel by single-stepping each resumed thread - until the first runs into an event. - When we do that, we would want to continue all other threads. - For now, just resume one thread to not confuse to_wait. */ - record_btrace_resume_thread (tp, flag); - /* We just indicate the resume intent here. The actual stepping happens in record_btrace_wait below. */ + ALL_NON_EXITED_THREADS (tp) + if (ptid_match (tp->ptid, ptid)) + record_btrace_resume_thread (tp, flag); /* Async support. */ if (target_can_async_p ()) -- 2.30.2