infrun: scheduler-locking replay
authorMarkus Metzger <markus.t.metzger@intel.com>
Mon, 7 Sep 2015 13:41:00 +0000 (15:41 +0200)
committerMarkus Metzger <markus.t.metzger@intel.com>
Fri, 18 Sep 2015 12:32:00 +0000 (14:32 +0200)
Record targets behave as if scheduler-locking were on in replay mode.  Add a
new scheduler-locking option "replay" to make this implicit behaviour explicit.
It behaves like "on" in replay mode and like "off" in record mode.

By making the current behaviour a scheduler-locking option, we allow the user
to change it.  Since it is the current behaviour, this new option is also
the new default.

One caveat is that when resuming a thread that is at the end of its execution
history, record btrace implicitly stops replaying other threads and resumes
the entire process.  This is a convenience feature to not require the user
to explicitly move all other threads to the end of their execution histories
before being able to resume the process.

We mimick this behaviour with scheduler-locking replay and move it from
record-btrace into infrun.  With all-stop on top of non-stop, we can't do
this in record-btrace anymore.

Record full does not really support multi-threading and is therefore not
impacted.  If it were extended to support multi-threading, it would 'benefit'
from this change.  The good thing is that all record targets will behave the
same with respect to scheduler-locking.

I put the code for this into clear_proceed_status.  It also sends the
about_to_proceed notification.

gdb/
* NEWS: Announce new scheduler-locking mode.
* infrun.c (schedlock_replay): New.
(scheduler_enums): Add schedlock_replay.
(scheduler_mode): Change default to schedlock_replay.
(user_visible_resume_ptid): Handle schedlock_replay.
(clear_proceed_status_thread): Stop replaying if resumed thread is
not replaying.
(schedlock_applies): Handle schedlock_replay.
(_initialize_infrun): Document new scheduler-locking mode.
* record-btrace.c (record_btrace_resume): Remove code to stop other
threads when not replaying the resumed thread.

doc/
* gdb.texinfo (All-Stop Mode): Describe new scheduler-locking mode.

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/infrun.c
gdb/record-btrace.c

index a2bd84340498dc4d98be7b67af8884db8220f204..ee90a762b4caefc88f0a92dc3eec3e51e9851ac2 100644 (file)
@@ -1,3 +1,17 @@
+2015-09-18  Markus Metzger  <markus.t.metzger@intel.com>
+
+       * NEWS: Announce new scheduler-locking mode.
+       * infrun.c (schedlock_replay): New.
+       (scheduler_enums): Add schedlock_replay.
+       (scheduler_mode): Change default to schedlock_replay.
+       (user_visible_resume_ptid): Handle schedlock_replay.
+       (clear_proceed_status_thread): Stop replaying if resumed thread is
+       not replaying.
+       (schedlock_applies): Handle schedlock_replay.
+       (_initialize_infrun): Document new scheduler-locking mode.
+       * record-btrace.c (record_btrace_resume): Remove code to stop other
+       threads when not replaying the resumed thread.
+
 2015-09-18  Markus Metzger  <markus.t.metzger@intel.com>
 
        * record-btrace.c ((record_btrace_will_replay): New.
index 0d17ef4ff1d45b8a23fa2c986c2002d1dcee395b..86c6f021a18eb3ddd88e2f228d011dd1b1e5c70a 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -45,6 +45,9 @@ show remote multiprocess-extensions-packet
   The "/m" option is now considered deprecated: its "source-centric"
   output hasn't proved useful in practice.
 
+* The "set scheduler-locking" command supports a new mode "replay".
+  It behaves like "off" in record mode and like "on" in replay mode.
+
 * Support for various ROM monitors has been removed:
 
   target dbug          dBUG ROM monitor for Motorola ColdFire
index 1e16e92932292e362faea6f8168f1cdb838221d4..9164b89379e1f13b3e50617b31bd460ce3aad8f8 100644 (file)
@@ -1,3 +1,7 @@
+2015-09-18  Markus Metzger  <markus.t.metzger@intel.com>
+
+       * gdb.texinfo (All-Stop Mode): Describe new scheduler-locking mode.
+
 2015-09-15  Pedro Alves  <palves@redhat.com>
 
        PR remote/18965
index 4ecdb8fc7b7cb6264691fa42d4651e8fa7232a33..068703963015b836f6258c83844c86a4795af91a 100644 (file)
@@ -5836,17 +5836,20 @@ locking the OS scheduler to allow only a single thread to run.
 @item set scheduler-locking @var{mode}
 @cindex scheduler locking mode
 @cindex lock scheduler
-Set the scheduler locking mode.  If it is @code{off}, then there is no
-locking and any thread may run at any time.  If @code{on}, then only the
-current thread may run when the inferior is resumed.  The @code{step}
-mode optimizes for single-stepping; it prevents other threads 
-from preempting the current thread while you are stepping, so that 
-the focus of debugging does not change unexpectedly.
-Other threads never get a chance to run when you step, and they are
-completely free to run when you use commands
-like @samp{continue}, @samp{until}, or @samp{finish}.  However, unless another
-thread hits a breakpoint during its timeslice, @value{GDBN} does not change
-the current thread away from the thread that you are debugging.
+Set the scheduler locking mode.  It applies to normal execution,
+record mode, and replay mode.  If it is @code{off}, then there is no
+locking and any thread may run at any time.  If @code{on}, then only
+the current thread may run when the inferior is resumed.  The
+@code{step} mode optimizes for single-stepping; it prevents other
+threads from preempting the current thread while you are stepping, so
+that the focus of debugging does not change unexpectedly.  Other
+threads never get a chance to run when you step, and they are
+completely free to run when you use commands like @samp{continue},
+@samp{until}, or @samp{finish}.  However, unless another thread hits a
+breakpoint during its timeslice, @value{GDBN} does not change the
+current thread away from the thread that you are debugging.  The
+@code{replay} mode behaves like @code{off} in record mode and like
+@code{on} in replay mode.
 
 @item show scheduler-locking
 Display the current scheduler locking mode.
index 75ac80abd9f47035476aa8a7cf1d346729d50b1e..701ea37eb5d50c31bb64095e6489d9c1a32810e3 100644 (file)
@@ -2166,13 +2166,15 @@ resume_cleanups (void *ignore)
 static const char schedlock_off[] = "off";
 static const char schedlock_on[] = "on";
 static const char schedlock_step[] = "step";
+static const char schedlock_replay[] = "replay";
 static const char *const scheduler_enums[] = {
   schedlock_off,
   schedlock_on,
   schedlock_step,
+  schedlock_replay,
   NULL
 };
-static const char *scheduler_mode = schedlock_off;
+static const char *scheduler_mode = schedlock_replay;
 static void
 show_scheduler_mode (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
@@ -2238,6 +2240,13 @@ user_visible_resume_ptid (int step)
         resume.  */
       resume_ptid = inferior_ptid;
     }
+  else if ((scheduler_mode == schedlock_replay)
+          && target_record_will_replay (minus_one_ptid, execution_direction))
+    {
+      /* User-settable 'scheduler' mode requires solo thread resume in replay
+        mode.  */
+      resume_ptid = inferior_ptid;
+    }
   else if (!sched_multi && target_supports_multi_process ())
     {
       /* Resume all threads of the current process (and none of other
@@ -2803,6 +2812,18 @@ clear_proceed_status_thread (struct thread_info *tp)
 void
 clear_proceed_status (int step)
 {
+  /* With scheduler-locking replay, stop replaying other threads if we're
+     not replaying the user-visible resume ptid.
+
+     This is a convenience feature to not require the user to explicitly
+     stop replaying the other threads.  We're assuming that the user's
+     intent is to resume tracing the recorded process.  */
+  if (!non_stop && scheduler_mode == schedlock_replay
+      && target_record_is_replaying (minus_one_ptid)
+      && !target_record_will_replay (user_visible_resume_ptid (step),
+                                    execution_direction))
+    target_record_stop_replaying ();
+
   if (!non_stop)
     {
       struct thread_info *tp;
@@ -2890,7 +2911,10 @@ schedlock_applies (struct thread_info *tp)
 {
   return (scheduler_mode == schedlock_on
          || (scheduler_mode == schedlock_step
-             && tp->control.stepping_command));
+             && tp->control.stepping_command)
+         || (scheduler_mode == schedlock_replay
+             && target_record_will_replay (minus_one_ptid,
+                                           execution_direction)));
 }
 
 /* Basic routine for continuing the program in various fashions.
@@ -9187,10 +9211,13 @@ By default, the debugger will use the same inferior."),
                        scheduler_enums, &scheduler_mode, _("\
 Set mode for locking scheduler during execution."), _("\
 Show mode for locking scheduler during execution."), _("\
-off  == no locking (threads may preempt at any time)\n\
-on   == full locking (no thread except the current thread may run)\n\
-step == scheduler locked during stepping commands (step, next, stepi, nexti).\n\
-       In this mode, other threads may run during other commands."),
+off    == no locking (threads may preempt at any time)\n\
+on     == full locking (no thread except the current thread may run)\n\
+          This applies to both normal execution and replay mode.\n\
+step   == scheduler locked during stepping commands (step, next, stepi, nexti).\n\
+          In this mode, other threads may run during other commands.\n\
+          This applies to both normal execution and replay mode.\n\
+replay == scheduler locked in replay mode and unlocked during normal execution."),
                        set_schedlock_func,     /* traps on target vector */
                        show_scheduler_mode,
                        &setlist, &showlist);
index df15d7770fc2bd17ac09fd20f73e89a7bf18c1a4..42195d1a1ec6726f3228a85e9095556a669f2129 100644 (file)
@@ -1903,22 +1903,16 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
      to not change the execution direction in-between.  */
   record_btrace_resume_exec_dir = execution_direction;
 
-  /* For all-stop targets...  */
+  /* For all-stop targets we pick the current thread when asked to resume an
+     entire process or everything.  */
   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)
-       target_record_stop_replaying ();
     }
 
   /* As long as we're not replaying, just forward the request.