btrace: resume all requested threads
authorMarkus Metzger <markus.t.metzger@intel.com>
Tue, 25 Aug 2015 11:42:39 +0000 (13:42 +0200)
committerMarkus Metzger <markus.t.metzger@intel.com>
Fri, 18 Sep 2015 12:24:25 +0000 (14:24 +0200)
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
gdb/record-btrace.c

index 7c927bb..d6901c8 100644 (file)
@@ -1,5 +1,12 @@
 2015-09-18  Markus Metzger  <markus.t.metzger@intel.com>
 
+       * 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  <markus.t.metzger@intel.com>
+
        * record-btrace.c: Include vec.h.
        (record_btrace_find_thread_to_move): Removed.
        (btrace_step_no_resumed, btrace_step_again)
index bda9b7c..c25b8f4 100644 (file)
@@ -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 ())