public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v3 01/19] btrace: fix non-stop check in to_wait
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
@ 2015-09-17 14:09 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 08/19] btrace: lock-step Markus Metzger
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:09 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

The record btrace target stops other threads in non-stop mode after stepping
the to-be-resumed thread.

The check is done on the non_stop variable.  It should rather be done on
target_is_non_stop_p ().  With all-stop on top of non-stop, infrun will
take care of stopping other threads.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_wait): Replace non_stop check with
	target_is_non_stop_p ().
---
 gdb/record-btrace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 9e16ab4..2d8b20b 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -2104,7 +2104,7 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
   *status = record_btrace_step_thread (tp);
 
   /* Stop all other threads. */
-  if (!non_stop)
+  if (!target_is_non_stop_p ())
     ALL_NON_EXITED_THREADS (other)
       other->btrace.flags &= ~BTHR_MOVE;
 
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 06/19] btrace: move breakpoint checking into stepping functions
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (3 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 17/19] target: add to_record_will_replay target method Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 15/19] btrace: allow full memory and register access for non-replaying threads Markus Metzger
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

Breakpoints are only checked for BTHR_CONT and BTHR_RCONT stepping requests.
A BTHR_STEP and BTHR_RSTEP request will always report stopped without reason.
Since breakpoints are reported correctly, I assume infrun is handling this.

Move the breakpoint check into the btrace single stepping functions.  This
will cause us to report breakpoint hits now also for single-step requests.

One thing to notice is that

  - when executing forwards, the breakpoint is checked before 'executing'
    the instruction, i.e. before moving the PC to the next instruction.

  - when executing backwards,  the breakpoint is checked after 'executing'
    the instruction, i.e. after moving the PC to the preceding instruction
    in the recorded execution.

There is code in infrun (see, for example proceed and adjust_pc_after_break)
that handles this and also depends on this behaviour.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_step_thread): Move breakpoint check
	to ...
	(record_btrace_single_step_forward): ... here and
	(record_btrace_single_step_backward): ... here.
---
 gdb/record-btrace.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index fdf7afb..5e8c1d4 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -2038,6 +2038,10 @@ record_btrace_single_step_forward (struct thread_info *tp)
   if (replay == NULL)
     return btrace_step_no_history ();
 
+  /* Check if we're stepping a breakpoint.  */
+  if (record_btrace_replay_at_breakpoint (tp))
+    return btrace_step_stopped ();
+
   /* Skip gaps during replay.  */
   do
     {
@@ -2089,6 +2093,18 @@ record_btrace_single_step_backward (struct thread_info *tp)
     }
   while (btrace_insn_get (replay) == NULL);
 
+  /* Check if we're stepping a breakpoint.
+
+     For reverse-stepping, this check is after the step.  There is logic in
+     infrun.c that handles reverse-stepping separately.  See, for example,
+     proceed and adjust_pc_after_break.
+
+     This code assumes that for reverse-stepping, PC points to the last
+     de-executed instruction, whereas for forward-stepping PC points to the
+     next to-be-executed instruction.  */
+  if (record_btrace_replay_at_breakpoint (tp))
+    return btrace_step_stopped ();
+
   return btrace_step_spurious ();
 }
 
@@ -2154,9 +2170,6 @@ record_btrace_step_thread (struct thread_info *tp)
 		     target_pid_to_str (tp->ptid),
 		     core_addr_to_string_nz (insn->pc));
 	    }
-
-	  if (record_btrace_replay_at_breakpoint (tp))
-	    return btrace_step_stopped ();
 	}
 
     case BTHR_RCONT:
@@ -2176,9 +2189,6 @@ record_btrace_step_thread (struct thread_info *tp)
 	  DEBUG ("reverse-stepping %d (%s) ... %s", tp->num,
 		 target_pid_to_str (tp->ptid),
 		 core_addr_to_string_nz (insn->pc));
-
-	  if (record_btrace_replay_at_breakpoint (tp))
-	    return btrace_step_stopped ();
 	}
     }
 }
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS
@ 2015-09-17 14:10 Markus Metzger
  2015-09-17 14:09 ` [PATCH v3 01/19] btrace: fix non-stop check in to_wait Markus Metzger
                   ` (19 more replies)
  0 siblings, 20 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

Changes to v2:
  - renamed the new scheduler-locking mode from "reverse" to "replay"
  - added to_record_will_replay target method to support the case where
    record full records during reverse execution
  - added support for scheduler-locking for all-stop targets

Changes to v1:
  - reworked non-stop test
  - changed the error string when trying to store registers while replaying
  - fixed all-stop/non-stop confusion in comments

This patch series adds support for non-stop mode to the record btrace target
and prepares for all-stop on top of non-stop (ASNS).

It adds a new scheduler-locking mode "reverse" for the current record btrace
behaviour of scheduler-locking during reverse/replay execution.

I tested this with the current all-stop and with Pedro's ASNS (by reverting
his disable patch).

The patch series can also be found on branch users/mmetzger/btrace-non-stop.

Markus Metzger (19):
  btrace: fix non-stop check in to_wait
  btrace: support to_stop
  btrace: improve stepping debugging
  btrace: extract the breakpoint check from record_btrace_step_thread
  btrace: split record_btrace_step_thread
  btrace: move breakpoint checking into stepping functions
  btrace: add missing NO_HISTORY
  btrace: lock-step
  btrace: resume all requested threads
  btrace: temporarily set inferior_ptid in record_btrace_start_replaying
  btrace: async
  infrun: switch to NO_HISTORY thread
  btrace: non-stop
  target, record: add PTID argument to to_record_is_replaying
  btrace: allow full memory and register access for non-replaying
    threads
  target: add to_record_stop_replaying target method
  target: add to_record_will_replay target method
  infrun: scheduler-locking replay
  btrace: honour scheduler-locking for all-stop targets

 gdb/NEWS                                       |   5 +
 gdb/btrace.h                                   |   5 +-
 gdb/doc/gdb.texinfo                            |  25 +-
 gdb/infrun.c                                   |  47 +-
 gdb/record-btrace.c                            | 751 ++++++++++++++++++-------
 gdb/record-full.c                              |  25 +-
 gdb/record.c                                   |   2 +-
 gdb/target-delegates.c                         |  73 ++-
 gdb/target.c                                   |  20 +-
 gdb/target.h                                   |  21 +-
 gdb/testsuite/gdb.btrace/multi-thread-step.exp | 233 +++++---
 gdb/testsuite/gdb.btrace/non-stop.c            |  45 ++
 gdb/testsuite/gdb.btrace/non-stop.exp          | 245 ++++++++
 13 files changed, 1182 insertions(+), 315 deletions(-)
 create mode 100644 gdb/testsuite/gdb.btrace/non-stop.c
 create mode 100644 gdb/testsuite/gdb.btrace/non-stop.exp

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 08/19] btrace: lock-step
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
  2015-09-17 14:09 ` [PATCH v3 01/19] btrace: fix non-stop check in to_wait Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 09/19] btrace: resume all requested threads Markus Metzger
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

Record btrace's to_wait method picks a single thread to step.  When passed
minus_one_ptid, it picks the current thread.  All other threads remain where
they are.

Change this to step all resumed threads together, one step at a time, until
the first thread reports an event.

We do delay reporting NO_HISTORY events until there are no other events to
report to prevent threads at the end of their execution history from starving
other threads.

We keep threads at the end of their execution history moving and replaying
until we announce their stop in to_wait.  This shouldn't really be user-visible
but its a detail worth mentioning.

Since record btrace's to_resume method also picks only a single thread to
resume, there shouldn't be a difference with the current all-stop.

With non-stop or all-stop on top of non-stop, we will see differences.  The
behaviour should be more natural as we're moving all threads.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c: Include vec.h.
	(record_btrace_find_thread_to_move): Removed.
	(btrace_step_no_resumed, btrace_step_again)
	(record_btrace_stop_replaying_at_end): New.
	(record_btrace_cancel_resume): Call record_btrace_stop_replaying_at_end.
	(record_btrace_single_step_forward): Remove calls to
	record_btrace_stop_replaying.
	(record_btrace_step_thread): Do only one step for BTHR_CONT and
	BTHR_RCONT.  Keep threads at the end of their history moving.
	(record_btrace_wait): Call record_btrace_step_thread for all threads
	until one reports an event.  Call record_btrace_stop_replaying_at_end
	for the eventing thread.
---
 gdb/record-btrace.c | 252 ++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 175 insertions(+), 77 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index fcd4351..bda9b7c 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -37,6 +37,7 @@
 #include "infrun.h"
 #include "event-loop.h"
 #include "inf-loop.h"
+#include "vec.h"
 
 /* The target_ops of record-btrace.  */
 static struct target_ops record_btrace_ops;
@@ -1838,6 +1839,26 @@ record_btrace_stop_replaying (struct thread_info *tp)
   registers_changed_ptid (tp->ptid);
 }
 
+/* Stop replaying TP if it is at the end of its execution history.  */
+
+static void
+record_btrace_stop_replaying_at_end (struct thread_info *tp)
+{
+  struct btrace_insn_iterator *replay, end;
+  struct btrace_thread_info *btinfo;
+
+  btinfo = &tp->btrace;
+  replay = btinfo->replay;
+
+  if (replay == NULL)
+    return;
+
+  btrace_insn_end (&end, btinfo);
+
+  if (btrace_insn_cmp (replay, &end) == 0)
+    record_btrace_stop_replaying (tp);
+}
+
 /* The to_resume method of target record-btrace.  */
 
 static void
@@ -1910,26 +1931,7 @@ record_btrace_cancel_resume (struct thread_info *tp)
 	 btrace_thread_flag_to_str (flags));
 
   tp->btrace.flags &= ~(BTHR_MOVE | BTHR_STOP);
-}
-
-/* Find a thread to move.  */
-
-static struct thread_info *
-record_btrace_find_thread_to_move (ptid_t ptid)
-{
-  struct thread_info *tp;
-
-  /* First check the parameter thread.  */
-  tp = find_thread_ptid (ptid);
-  if (tp != NULL && (tp->btrace.flags & (BTHR_MOVE | BTHR_STOP)) != 0)
-    return tp;
-
-  /* Otherwise, find one other thread that has been resumed.  */
-  ALL_NON_EXITED_THREADS (tp)
-    if ((tp->btrace.flags & (BTHR_MOVE | BTHR_STOP)) != 0)
-      return tp;
-
-  return NULL;
+  record_btrace_stop_replaying_at_end (tp);
 }
 
 /* Return a target_waitstatus indicating that we ran out of history.  */
@@ -1983,6 +1985,30 @@ btrace_step_spurious (void)
   return status;
 }
 
+/* Return a target_waitstatus indicating that the thread was not resumed.  */
+
+static struct target_waitstatus
+btrace_step_no_resumed (void)
+{
+  struct target_waitstatus status;
+
+  status.kind = TARGET_WAITKIND_NO_RESUMED;
+
+  return status;
+}
+
+/* Return a target_waitstatus indicating that we should wait again.  */
+
+static struct target_waitstatus
+btrace_step_again (void)
+{
+  struct target_waitstatus status;
+
+  status.kind = TARGET_WAITKIND_IGNORE;
+
+  return status;
+}
+
 /* Clear the record histories.  */
 
 static void
@@ -2047,24 +2073,22 @@ record_btrace_single_step_forward (struct thread_info *tp)
     {
       unsigned int steps;
 
+      /* We will bail out here if we continue stepping after reaching the end
+	 of the execution history.  */
       steps = btrace_insn_next (replay, 1);
       if (steps == 0)
-	{
-	  record_btrace_stop_replaying (tp);
-	  return btrace_step_no_history ();
-	}
+	return btrace_step_no_history ();
     }
   while (btrace_insn_get (replay) == NULL);
 
   /* Determine the end of the instruction trace.  */
   btrace_insn_end (&end, btinfo);
 
-  /* We stop replaying if we reached the end of the trace.  */
+  /* The execution trace contains (and ends with) the current instruction.
+     This instruction has not been executed, yet, so the trace really ends
+     one instruction earlier.  */
   if (btrace_insn_cmp (replay, &end) == 0)
-    {
-      record_btrace_stop_replaying (tp);
-      return btrace_step_no_history ();
-    }
+    return btrace_step_no_history ();
 
   return btrace_step_spurious ();
 }
@@ -2144,65 +2168,56 @@ record_btrace_step_thread (struct thread_info *tp)
     case BTHR_STEP:
       status = record_btrace_single_step_forward (tp);
       if (status.kind != TARGET_WAITKIND_SPURIOUS)
-	return status;
+	break;
 
       return btrace_step_stopped ();
 
     case BTHR_RSTEP:
       status = record_btrace_single_step_backward (tp);
       if (status.kind != TARGET_WAITKIND_SPURIOUS)
-	return status;
+	break;
 
       return btrace_step_stopped ();
 
     case BTHR_CONT:
-      for (;;)
-	{
-	  status = record_btrace_single_step_forward (tp);
-	  if (status.kind != TARGET_WAITKIND_SPURIOUS)
-	    return status;
-
-	  if (btinfo->replay != NULL)
-	    {
-	      const struct btrace_insn *insn;
-
-	      insn = btrace_insn_get (btinfo->replay);
-	      gdb_assert (insn != NULL);
+      status = record_btrace_single_step_forward (tp);
+      if (status.kind != TARGET_WAITKIND_SPURIOUS)
+	break;
 
-	      DEBUG ("stepping %d (%s) ... %s", tp->num,
-		     target_pid_to_str (tp->ptid),
-		     core_addr_to_string_nz (insn->pc));
-	    }
-	}
+      btinfo->flags |= flags;
+      return btrace_step_again ();
 
     case BTHR_RCONT:
-      for (;;)
-	{
-	  const struct btrace_insn *insn;
-
-	  status = record_btrace_single_step_backward (tp);
-	  if (status.kind != TARGET_WAITKIND_SPURIOUS)
-	    return status;
+      status = record_btrace_single_step_backward (tp);
+      if (status.kind != TARGET_WAITKIND_SPURIOUS)
+	break;
 
-	  gdb_assert (btinfo->replay != NULL);
+      btinfo->flags |= flags;
+      return btrace_step_again ();
+    }
 
-	  insn = btrace_insn_get (btinfo->replay);
-	  gdb_assert (insn != NULL);
+  /* We keep threads moving at the end of their execution history.  The to_wait
+     method will stop the thread for whom the event is reported.  */
+  if (status.kind == TARGET_WAITKIND_NO_HISTORY)
+    btinfo->flags |= flags;
 
-	  DEBUG ("reverse-stepping %d (%s) ... %s", tp->num,
-		 target_pid_to_str (tp->ptid),
-		 core_addr_to_string_nz (insn->pc));
-	}
-    }
+  return status;
 }
 
+/* A vector of threads.  */
+
+typedef struct thread_info * tp_t;
+DEF_VEC_P (tp_t);
+
 /* The to_wait method of target record-btrace.  */
 
 static ptid_t
 record_btrace_wait (struct target_ops *ops, ptid_t ptid,
 		    struct target_waitstatus *status, int options)
 {
-  struct thread_info *tp, *other;
+  VEC (tp_t) *moving, *no_history;
+  struct thread_info *tp, *eventing;
+  struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
 
   DEBUG ("wait %s (0x%x)", target_pid_to_str (ptid), options);
 
@@ -2213,31 +2228,114 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
       return ops->to_wait (ops, ptid, status, options);
     }
 
-  /* Let's find a thread to move.  */
-  tp = record_btrace_find_thread_to_move (ptid);
-  if (tp == NULL)
+  moving = NULL;
+  no_history = NULL;
+
+  make_cleanup (VEC_cleanup (tp_t), &moving);
+  make_cleanup (VEC_cleanup (tp_t), &no_history);
+
+  /* Keep a work list of moving threads.  */
+  ALL_NON_EXITED_THREADS (tp)
+    if (ptid_match (tp->ptid, ptid)
+	&& ((tp->btrace.flags & (BTHR_MOVE | BTHR_STOP)) != 0))
+      VEC_safe_push (tp_t, moving, tp);
+
+  if (VEC_empty (tp_t, moving))
+    {
+      *status = btrace_step_no_resumed ();
+
+      DEBUG ("wait ended by %s: %s", target_pid_to_str (null_ptid),
+	     target_waitstatus_to_string (status));
+
+      do_cleanups (cleanups);
+      return null_ptid;
+    }
+
+  /* Step moving threads one by one, one step each, until either one thread
+     reports an event or we run out of threads to step.
+
+     When stepping more than one thread, chances are that some threads reach
+     the end of their execution history earlier than others.  If we reported
+     this immediately, all-stop on top of non-stop would stop all threads and
+     resume the same threads next time.  And we would report the same thread
+     having reached the end of its execution history again.
+
+     In the worst case, this would starve the other threads.  But even if other
+     threads would be allowed to make progress, this would result in far too
+     many intermediate stops.
+
+     We therefore delay the reporting of "no execution history" until we have
+     nothing else to report.  By this time, all threads should have moved to
+     either the beginning or the end of their execution history.  There will
+     be a single user-visible stop.  */
+  eventing = NULL;
+  while ((eventing == NULL) && !VEC_empty (tp_t, moving))
+    {
+      unsigned int ix;
+
+      ix = 0;
+      while ((eventing == NULL) && VEC_iterate (tp_t, moving, ix, tp))
+	{
+	  *status = record_btrace_step_thread (tp);
+
+	  switch (status->kind)
+	    {
+	    case TARGET_WAITKIND_IGNORE:
+	      ix++;
+	      break;
+
+	    case TARGET_WAITKIND_NO_HISTORY:
+	      VEC_safe_push (tp_t, no_history,
+			     VEC_ordered_remove (tp_t, moving, ix));
+	      break;
+
+	    default:
+	      eventing = VEC_unordered_remove (tp_t, moving, ix);
+	      break;
+	    }
+	}
+    }
+
+  if (eventing == NULL)
     {
-      DEBUG ("wait %s: no thread", target_pid_to_str (ptid));
+      /* We started with at least one moving thread.  This thread must have
+	 either stopped or reached the end of its execution history.
 
-      status->kind = TARGET_WAITKIND_IGNORE;
-      return minus_one_ptid;
+	 In the former case, EVENTING must not be NULL.
+	 In the latter case, NO_HISTORY must not be empty.  */
+      gdb_assert (!VEC_empty (tp_t, no_history));
+
+      /* We kept threads moving at the end of their execution history.  Stop
+	 EVENTING now that we are going to report its stop.  */
+      eventing = VEC_unordered_remove (tp_t, no_history, 0);
+      eventing->btrace.flags &= ~BTHR_MOVE;
+
+      *status = btrace_step_no_history ();
     }
 
-  /* We only move a single thread.  We're not able to correlate threads.  */
-  *status = record_btrace_step_thread (tp);
+  gdb_assert (eventing != NULL);
+
+  /* We kept threads replaying at the end of their execution history.  Stop
+     replaying EVENTING now that we are going to report its stop.  */
+  record_btrace_stop_replaying_at_end (eventing);
 
   /* Stop all other threads. */
   if (!target_is_non_stop_p ())
-    ALL_NON_EXITED_THREADS (other)
-      record_btrace_cancel_resume (other);
+    ALL_NON_EXITED_THREADS (tp)
+      record_btrace_cancel_resume (tp);
 
   /* Start record histories anew from the current position.  */
-  record_btrace_clear_histories (&tp->btrace);
+  record_btrace_clear_histories (&eventing->btrace);
 
   /* We moved the replay position but did not update registers.  */
-  registers_changed_ptid (tp->ptid);
+  registers_changed_ptid (eventing->ptid);
+
+  DEBUG ("wait ended by thread %d (%s): %s", eventing->num,
+	 target_pid_to_str (eventing->ptid),
+	 target_waitstatus_to_string (status));
 
-  return tp->ptid;
+  do_cleanups (cleanups);
+  return eventing->ptid;
 }
 
 /* The to_stop method of target record-btrace.  */
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 13/19] btrace: non-stop
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (7 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 11/19] btrace: async Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 10/19] btrace: temporarily set inferior_ptid in record_btrace_start_replaying Markus Metzger
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches, Eli Zaretskii

Support non-stop mode in record btrace.

CC: Eli Zaretskii <eliz@gnu.org>

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_open): Remove non_stop check.
	* NEWS: Announce that record btrace supports non-stop mode.

testsuite/
	* gdb.btrace/non-stop.c: New.
	* gdb.btrace/non-stop.exp: New.
---
 gdb/NEWS                              |   2 +
 gdb/record-btrace.c                   |   3 -
 gdb/testsuite/gdb.btrace/non-stop.c   |  45 +++++++
 gdb/testsuite/gdb.btrace/non-stop.exp | 245 ++++++++++++++++++++++++++++++++++
 4 files changed, 292 insertions(+), 3 deletions(-)
 create mode 100644 gdb/testsuite/gdb.btrace/non-stop.c
 create mode 100644 gdb/testsuite/gdb.btrace/non-stop.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index f563b8c..0d17ef4 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,8 @@
 
 *** Changes since GDB 7.10
 
+* Record btrace now supports non-stop mode.
+
 * Support for tracepoints on aarch64-linux was added in GDBserver.
 
 * The 'record instruction-history' command now indicates speculative execution
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 764b349..8eefae2 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -216,9 +216,6 @@ record_btrace_open (const char *args, int from_tty)
   if (!target_has_execution)
     error (_("The program is not being run."));
 
-  if (non_stop)
-    error (_("Record btrace can't debug inferior in non-stop mode."));
-
   gdb_assert (record_btrace_thread_observer == NULL);
 
   disable_chain = make_cleanup (null_cleanup, NULL);
diff --git a/gdb/testsuite/gdb.btrace/non-stop.c b/gdb/testsuite/gdb.btrace/non-stop.c
new file mode 100644
index 0000000..2fc8dfb
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/non-stop.c
@@ -0,0 +1,45 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+
+static int global;
+
+static void *
+test (void *arg)
+{
+  unsigned int i;
+
+  i = 0; /* bp.1 */
+  for (; i < 10; ++i) global += i; /* loop */
+
+  return arg; /* bp.2 */
+}
+
+int
+main (void)
+{
+  pthread_t th;
+
+  pthread_create (&th, NULL, test, NULL);
+
+  test (NULL);
+
+  pthread_join (th, NULL);
+
+  return 0; /* bp.3 */
+}
diff --git a/gdb/testsuite/gdb.btrace/non-stop.exp b/gdb/testsuite/gdb.btrace/non-stop.exp
new file mode 100644
index 0000000..bc4ffb1
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/non-stop.exp
@@ -0,0 +1,245 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2015 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+
+# start inferior
+standard_testfile
+if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" "$binfile" executable {debug}] != "" } {
+    return -1
+}
+clean_restart $testfile
+
+gdb_test_no_output "set non-stop on"
+
+if ![runto_main] {
+    return -1
+}
+
+# set up breakpoints
+set bp_1 [gdb_get_line_number "bp.1" $srcfile]
+set bp_2 [gdb_get_line_number "bp.2" $srcfile]
+set bp_3 [gdb_get_line_number "bp.3" $srcfile]
+
+gdb_breakpoint $bp_1
+gdb_breakpoint $bp_2
+
+# get the line number containing most of the trace
+set loop [gdb_get_line_number "loop" $srcfile]
+
+# a stop on the above line as reported by GDB
+set loop_line "$loop\[^\\\r\\\n\]*/\\\* loop \\\*/"
+
+# make sure $line matches the full expected output per thread.
+# and let's hope that GDB never mixes the output from different threads.
+proc gdb_cont_to { threads cmd line nthreads } {
+    global gdb_prompt
+    set full_cmd "thread apply $threads $cmd"
+
+    # consume the prompt.  since we started the command in the background,
+    # the prompt precedes any further output except some errors.
+    gdb_test_multiple "$full_cmd &" "$full_cmd: prompt" {
+        -re "$gdb_prompt " {
+            pass "$full_cmd: prompt"
+        }
+    }
+
+    # now check for the expected line - one per thread.
+    for {set i 0} {$i < $nthreads} {incr i} {
+        set test "$full_cmd: thread $i"
+
+        gdb_test_multiple "" $test {
+            -re "$line\[^\\\r\\\n\]*\r\n" {
+                pass $test
+            }
+        }
+    }
+}
+
+proc gdb_cont_to_bp_line { line threads nthreads } {
+    gdb_cont_to $threads "continue" \
+        [multi_line \
+             "Breakpoint\[^\\\r\\\n\]*$line" \
+             "\[^\\\r\\\n\]*" \
+            ] \
+        $nthreads
+}
+
+proc gdb_cont_to_no_history { threads cmd nthreads } {
+    gdb_cont_to $threads $cmd \
+        [multi_line \
+             "No more reverse-execution history\." \
+             "\[^\\\r\\\n\]*" \
+             "\[^\\\r\\\n\]*" \
+            ] \
+        $nthreads
+}
+
+# trace the code between the two breakpoints
+gdb_cont_to_bp_line "$srcfile:$bp_1" all 2
+gdb_test_no_output "record btrace"
+gdb_cont_to_bp_line "$srcfile:$bp_2" all 2
+
+# we don't need those breakpoints any longer.
+# they will only disturb our stepping.
+delete_breakpoints
+
+# show the threads - this is useful for debugging fails
+gdb_test "thread apply all info rec" ".*"
+gdb_test "info threads" ".*"
+
+with_test_prefix "navigate" {
+    gdb_test "thread apply 1 record goto 2" "$loop_line"
+    gdb_test "thread apply 2 record goto 4" "$loop_line"
+    gdb_test "thread apply 1 info record" \
+        ".*Replay in progress\.  At instruction 2\."
+    gdb_test "thread apply 2 info record" \
+        ".*Replay in progress\.  At instruction 4\."
+
+    gdb_test "thread apply all record goto 5" "$loop_line"
+    gdb_test "thread apply 1 info record" \
+        ".*Replay in progress\.  At instruction 5\."
+    gdb_test "thread apply 2 info record" \
+        ".*Replay in progress\.  At instruction 5\."
+}
+
+with_test_prefix "step" {
+    with_test_prefix "thread 1" {
+        gdb_test "thread apply 1 stepi 2" "$loop_line"
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 7\."
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 5\."
+    }
+
+    with_test_prefix "thread 2" {
+        gdb_test "thread apply 2 stepi 3" "$loop_line"
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 7\."
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 8\."
+    }
+
+    with_test_prefix "all" {
+        gdb_cont_to all "stepi 4" "$loop_line" 2
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 11\."
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 12\."
+    }
+}
+
+with_test_prefix "reverse-step" {
+    with_test_prefix "thread 1" {
+        gdb_test "thread apply 1 reverse-stepi 2" "$loop_line"
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 9\."
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 12\."
+    }
+
+    with_test_prefix "thread 2" {
+        gdb_test "thread apply 2 reverse-stepi 3" "$loop_line"
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 9\."
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 9\."
+    }
+
+    with_test_prefix "all" {
+        gdb_cont_to all "reverse-stepi 4" "$loop_line" 2
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 5\."
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 5\."
+    }
+}
+
+with_test_prefix "continue" {
+    with_test_prefix "thread 1" {
+        gdb_cont_to_no_history 1 "continue" 1
+        gdb_test "thread apply 1 info record" \
+            ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 5\."
+
+        gdb_cont_to_no_history 1 "reverse-continue" 1
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 1\."
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 5\."
+    }
+
+    with_test_prefix "thread 2" {
+        gdb_cont_to_no_history 2 "continue" 1
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 1\."
+        gdb_test "thread apply 2 info record" \
+            ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
+
+        gdb_cont_to_no_history 2 "reverse-continue" 1
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 1\."
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 1\."
+    }
+}
+
+# a thread may only resume if no thread is still replaying
+with_test_prefix "no progress" {
+    with_test_prefix "thread 1" {
+        gdb_test "thread apply 1 record goto end" ".*"
+        gdb_test "thread apply 2 record goto begin" ".*"
+
+        gdb_cont_to_no_history 1 "continue" 1
+        gdb_cont_to_no_history 1 "step" 1
+        gdb_test "thread apply 1 info record" \
+            ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
+        gdb_test "thread apply 2 info record" \
+            ".*Replay in progress\.  At instruction 1\."
+    }
+
+    with_test_prefix "thread 2" {
+        gdb_test "thread apply 1 record goto begin" ".*"
+        gdb_test "thread apply 2 record goto end" ".*"
+
+        gdb_cont_to_no_history 2 "continue" 1
+        gdb_cont_to_no_history 2 "step" 1
+        gdb_test "thread apply 1 info record" \
+            ".*Replay in progress\.  At instruction 1\."
+        gdb_test "thread apply 2 info record" \
+            ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
+    }
+
+    with_test_prefix "all" {
+        gdb_test "thread apply all record goto begin" ".*"
+
+        gdb_cont_to_no_history all "continue" 2
+        gdb_test "thread apply 1 info record" \
+            ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
+        gdb_test "thread apply 2 info record" \
+            ".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
+    }
+}
+
+# now that both threads stopped replaying we may resume recording
+with_test_prefix "cont to end" {
+    gdb_breakpoint $bp_3
+    gdb_cont_to_bp_line "$srcfile:$bp_3" all 1
+}
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 16/19] target: add to_record_stop_replaying target method
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (9 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 10/19] btrace: temporarily set inferior_ptid in record_btrace_start_replaying Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 18/19] infrun: scheduler-locking replay Markus Metzger
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

Add a new target method to_record_stop_replaying to stop replaying.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_resume): Call
	target_record_stop_replaying.
	(record_btrace_stop_replaying_all): New.
	(init_record_btrace_ops): Initialize to_record_stop_replaying.
	* record-full.c (record_full_stop_replaying): New.
	(init_record_full_ops ): Initialize to_record_stop_replaying.
	* target-delegates.c: Regenerated.
	* target.c (target_record_stop_replaying): New.
	* target.h (struct target_ops) <to_record_stop_replaying>: New.
	(target_record_stop_replaying): New.
---
 gdb/record-btrace.c    | 15 +++++++++++++--
 gdb/record-full.c      |  9 +++++++++
 gdb/target-delegates.c | 26 ++++++++++++++++++++++++++
 gdb/target.c           |  8 ++++++++
 gdb/target.h           |  7 +++++++
 5 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index b4e4560..e0b79a8 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1910,8 +1910,7 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
       /* ...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);
+	target_record_stop_replaying ();
     }
 
   /* As long as we're not replaying, just forward the request.
@@ -2596,6 +2595,17 @@ record_btrace_goto (struct target_ops *self, ULONGEST insn)
   record_btrace_set_replay (tp, &it);
 }
 
+/* The to_record_stop_replaying method of target record-btrace.  */
+
+static void
+record_btrace_stop_replaying_all (struct target_ops *self)
+{
+  struct thread_info *tp;
+
+  ALL_NON_EXITED_THREADS (tp)
+    record_btrace_stop_replaying (tp);
+}
+
 /* The to_execution_direction target method.  */
 
 static enum exec_direction_kind
@@ -2647,6 +2657,7 @@ init_record_btrace_ops (void)
   ops->to_call_history_from = record_btrace_call_history_from;
   ops->to_call_history_range = record_btrace_call_history_range;
   ops->to_record_is_replaying = record_btrace_is_replaying;
+  ops->to_record_stop_replaying = record_btrace_stop_replaying_all;
   ops->to_xfer_partial = record_btrace_xfer_partial;
   ops->to_remove_breakpoint = record_btrace_remove_breakpoint;
   ops->to_insert_breakpoint = record_btrace_insert_breakpoint;
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 03dc22d..35b3841 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -1917,6 +1917,14 @@ record_full_goto (struct target_ops *self, ULONGEST target_insn)
   record_full_goto_entry (p);
 }
 
+/* The "to_record_stop_replaying" target method.  */
+
+static void
+record_full_stop_replaying (struct target_ops *self)
+{
+  record_full_goto_end (self);
+}
+
 static void
 init_record_full_ops (void)
 {
@@ -1957,6 +1965,7 @@ init_record_full_ops (void)
   record_full_ops.to_save_record = record_full_save;
   record_full_ops.to_delete_record = record_full_delete;
   record_full_ops.to_record_is_replaying = record_full_is_replaying;
+  record_full_ops.to_record_stop_replaying = record_full_stop_replaying;
   record_full_ops.to_goto_record_begin = record_full_goto_begin;
   record_full_ops.to_goto_record_end = record_full_goto_end;
   record_full_ops.to_goto_record = record_full_goto;
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index 9f909a0..a07c8c9 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -3631,6 +3631,28 @@ debug_record_is_replaying (struct target_ops *self, ptid_t arg1)
 }
 
 static void
+delegate_record_stop_replaying (struct target_ops *self)
+{
+  self = self->beneath;
+  self->to_record_stop_replaying (self);
+}
+
+static void
+tdefault_record_stop_replaying (struct target_ops *self)
+{
+}
+
+static void
+debug_record_stop_replaying (struct target_ops *self)
+{
+  fprintf_unfiltered (gdb_stdlog, "-> %s->to_record_stop_replaying (...)\n", debug_target.to_shortname);
+  debug_target.to_record_stop_replaying (&debug_target);
+  fprintf_unfiltered (gdb_stdlog, "<- %s->to_record_stop_replaying (", debug_target.to_shortname);
+  target_debug_print_struct_target_ops_p (&debug_target);
+  fputs_unfiltered (")\n", gdb_stdlog);
+}
+
+static void
 delegate_goto_record_begin (struct target_ops *self)
 {
   self = self->beneath;
@@ -4267,6 +4289,8 @@ install_delegators (struct target_ops *ops)
     ops->to_delete_record = delegate_delete_record;
   if (ops->to_record_is_replaying == NULL)
     ops->to_record_is_replaying = delegate_record_is_replaying;
+  if (ops->to_record_stop_replaying == NULL)
+    ops->to_record_stop_replaying = delegate_record_stop_replaying;
   if (ops->to_goto_record_begin == NULL)
     ops->to_goto_record_begin = delegate_goto_record_begin;
   if (ops->to_goto_record_end == NULL)
@@ -4434,6 +4458,7 @@ install_dummy_methods (struct target_ops *ops)
   ops->to_save_record = tdefault_save_record;
   ops->to_delete_record = tdefault_delete_record;
   ops->to_record_is_replaying = tdefault_record_is_replaying;
+  ops->to_record_stop_replaying = tdefault_record_stop_replaying;
   ops->to_goto_record_begin = tdefault_goto_record_begin;
   ops->to_goto_record_end = tdefault_goto_record_end;
   ops->to_goto_record = tdefault_goto_record;
@@ -4587,6 +4612,7 @@ init_debug_target (struct target_ops *ops)
   ops->to_save_record = debug_save_record;
   ops->to_delete_record = debug_delete_record;
   ops->to_record_is_replaying = debug_record_is_replaying;
+  ops->to_record_stop_replaying = debug_record_stop_replaying;
   ops->to_goto_record_begin = debug_goto_record_begin;
   ops->to_goto_record_end = debug_goto_record_end;
   ops->to_goto_record = debug_goto_record;
diff --git a/gdb/target.c b/gdb/target.c
index 34d57ea..f73067c 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3664,6 +3664,14 @@ target_record_is_replaying (ptid_t ptid)
 /* See target.h.  */
 
 void
+target_record_stop_replaying (void)
+{
+  current_target.to_record_stop_replaying (&current_target);
+}
+
+/* See target.h.  */
+
+void
 target_goto_record_begin (void)
 {
   current_target.to_goto_record_begin (&current_target);
diff --git a/gdb/target.h b/gdb/target.h
index 2afeae2..169785d 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1157,6 +1157,10 @@ struct target_ops
     int (*to_record_is_replaying) (struct target_ops *, ptid_t ptid)
       TARGET_DEFAULT_RETURN (0);
 
+    /* Stop replaying.  */
+    void (*to_record_stop_replaying) (struct target_ops *)
+      TARGET_DEFAULT_IGNORE ();
+
     /* Go to the begin of the execution trace.  */
     void (*to_goto_record_begin) (struct target_ops *)
       TARGET_DEFAULT_NORETURN (tcomplain ());
@@ -2442,6 +2446,9 @@ extern void target_delete_record (void);
 /* See to_record_is_replaying in struct target_ops.  */
 extern int target_record_is_replaying (ptid_t ptid);
 
+/* See to_record_stop_replaying in struct target_ops.  */
+extern void target_record_stop_replaying (void);
+
 /* See to_goto_record_begin in struct target_ops.  */
 extern void target_goto_record_begin (void);
 
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 15/19] btrace: allow full memory and register access for non-replaying threads
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (4 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 06/19] btrace: move breakpoint checking into stepping functions Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 14/19] target, record: add PTID argument to to_record_is_replaying Markus Metzger
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

The record btrace target does not allow accessing memory and storing registers
while replaying.  For multi-threaded applications, this prevents those
accesses also for threads that are at the end of their execution history as
long as at least one thread is replaying.

Change this to only check if the selected thread is replaying.  This allows
threads that are at the end of their execution history to read and write
memory and to store registers.

Also change the error message to reflect this change.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_xfer_partial)
	(record_btrace_store_registers, record_btrace_prepare_to_store):
	Call record_btrace_is_replaying with inferior_ptid instead of
	minus_one_ptid.
	(record_btrace_store_registers): Change error message.
---
 gdb/record-btrace.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 481d22d..b4e4560 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1160,7 +1160,7 @@ record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,
   /* Filter out requests that don't make sense during replay.  */
   if (replay_memory_access == replay_memory_access_read_only
       && !record_btrace_generating_corefile
-      && record_btrace_is_replaying (ops, minus_one_ptid))
+      && record_btrace_is_replaying (ops, inferior_ptid))
     {
       switch (object)
 	{
@@ -1314,8 +1314,8 @@ record_btrace_store_registers (struct target_ops *ops,
   struct target_ops *t;
 
   if (!record_btrace_generating_corefile
-      && record_btrace_is_replaying (ops, minus_one_ptid))
-    error (_("This record target does not allow writing registers."));
+      && record_btrace_is_replaying (ops, inferior_ptid))
+    error (_("Cannot write registers while replaying."));
 
   gdb_assert (may_write_registers != 0);
 
@@ -1332,7 +1332,7 @@ record_btrace_prepare_to_store (struct target_ops *ops,
   struct target_ops *t;
 
   if (!record_btrace_generating_corefile
-      && record_btrace_is_replaying (ops, minus_one_ptid))
+      && record_btrace_is_replaying (ops, inferior_ptid))
     return;
 
   t = ops->beneath;
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 18/19] infrun: scheduler-locking replay
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (10 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 16/19] target: add to_record_stop_replaying target method Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-18 11:39   ` Pedro Alves
  2015-09-17 14:10 ` [PATCH v3 05/19] btrace: split record_btrace_step_thread Markus Metzger
                   ` (7 subsequent siblings)
  19 siblings, 1 reply; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches, Eli Zaretskii, Jan Kratochvil

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.

CC: Eli Zaretskii <eliz@gnu.org>
CC: Jan Kratochvil <jan.kratochvil@redhat.com>

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

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/NEWS            |  3 +++
 gdb/doc/gdb.texinfo | 25 ++++++++++++++-----------
 gdb/infrun.c        | 39 +++++++++++++++++++++++++++++++++------
 gdb/record-btrace.c | 10 ++--------
 4 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 0d17ef4..86c6f02 100644
--- 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
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4ecdb8f..0687039 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -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.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 75ac80a..9101fb4 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -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);
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index df15d77..42195d1 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -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.
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 12/19] infrun: switch to NO_HISTORY thread
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (13 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 02/19] btrace: support to_stop Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 07/19] btrace: add missing NO_HISTORY Markus Metzger
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

A thread that runs out of its execution history is stopped.  We already set
stop_pc and call stop_waiting.  But we do not switch to the stopped thread.

In normal_stop, we call finish_thread_state_cleanup to set a thread's running
state.  In all-stop mode, we call it with minus_one_ptid; in non-stop mode, we
only call it for inferior_ptid.

If in non-stop mode normal_stop is called on behalf of a thread that is not
inferior_ptid, that other thread will still be reported as running.  If it is
actually stopped it can't be resumed again.

Record targets traditionally don't support non-stop and only resume
inferior_ptid.  So this has not been a problem, so far.

Switch to the eventing thread for NO_HISTORY events as preparation to support
non-stop for the record btrace target.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* infrun.c (handle_inferior_event_1): Switch to the eventing thread
	in the TARKET_WAITKIND_NO_HISTORY case.
---
 gdb/infrun.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 8175fb1..75ac80a 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5126,8 +5126,14 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
         fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_NO_HISTORY\n");
       /* Reverse execution: target ran out of history info.  */
 
+      /* Switch to the stopped thread.  */
+      if (!ptid_equal (ecs->ptid, inferior_ptid))
+	context_switch (ecs->ptid);
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
+
       delete_just_stopped_threads_single_step_breakpoints ();
-      stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+      stop_pc = regcache_read_pc (get_thread_regcache (inferior_ptid));
       observer_notify_no_history ();
       stop_waiting (ecs);
       return;
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 02/19] btrace: support to_stop
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (12 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 05/19] btrace: split record_btrace_step_thread Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 12/19] infrun: switch to NO_HISTORY thread Markus Metzger
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

Add support for the to_stop target method to the btrace record target.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* btrace.h (enum btrace_thread_flag) <BTHR_STOP>: New.
	* record-btrace (record_btrace_resume_thread): Clear BTHR_STOP.
	(record_btrace_find_thread_to_move): Also accept threads that have
	BTHR_STOP set.
	(btrace_step_stopped_on_request, record_btrace_stop): New.
	(record_btrace_step_thread): Support BTHR_STOP.
	(record_btrace_wait): Also clear BTHR_STOP when stopping other threads.
	(init_record_btrace_ops): Initialize to_stop.
---
 gdb/btrace.h        |  5 ++++-
 gdb/record-btrace.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/gdb/btrace.h b/gdb/btrace.h
index 756a778..f844df8 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -240,7 +240,10 @@ enum btrace_thread_flag
   BTHR_RCONT = (1 << 3),
 
   /* The thread is to be moved.  */
-  BTHR_MOVE = (BTHR_STEP | BTHR_RSTEP | BTHR_CONT | BTHR_RCONT)
+  BTHR_MOVE = (BTHR_STEP | BTHR_RSTEP | BTHR_CONT | BTHR_RCONT),
+
+  /* The thread is to be stopped.  */
+  BTHR_STOP = (1 << 4)
 };
 
 #if defined (HAVE_LIBIPT)
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 2d8b20b..a9ed4b7 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1677,6 +1677,8 @@ record_btrace_resume_thread (struct thread_info *tp,
   /* Fetch the latest branch trace.  */
   btrace_fetch (tp);
 
+  /* A resume request overwrites a preceding stop request.  */
+  btinfo->flags &= ~BTHR_STOP;
   btinfo->flags |= flag;
 }
 
@@ -1872,12 +1874,12 @@ record_btrace_find_thread_to_move (ptid_t ptid)
 
   /* First check the parameter thread.  */
   tp = find_thread_ptid (ptid);
-  if (tp != NULL && (tp->btrace.flags & BTHR_MOVE) != 0)
+  if (tp != NULL && (tp->btrace.flags & (BTHR_MOVE | BTHR_STOP)) != 0)
     return tp;
 
   /* Otherwise, find one other thread that has been resumed.  */
   ALL_NON_EXITED_THREADS (tp)
-    if ((tp->btrace.flags & BTHR_MOVE) != 0)
+    if ((tp->btrace.flags & (BTHR_MOVE | BTHR_STOP)) != 0)
       return tp;
 
   return NULL;
@@ -1908,6 +1910,20 @@ btrace_step_stopped (void)
   return status;
 }
 
+/* Return a target_waitstatus indicating that a thread was stopped as
+   requested.  */
+
+static struct target_waitstatus
+btrace_step_stopped_on_request (void)
+{
+  struct target_waitstatus status;
+
+  status.kind = TARGET_WAITKIND_STOPPED;
+  status.value.sig = GDB_SIGNAL_0;
+
+  return status;
+}
+
 /* Clear the record histories.  */
 
 static void
@@ -1932,23 +1948,27 @@ record_btrace_step_thread (struct thread_info *tp)
   enum btrace_thread_flag flags;
   unsigned int steps;
 
-  /* We can't step without an execution history.  */
-  if (btrace_is_empty (tp))
-    return btrace_step_no_history ();
 
   btinfo = &tp->btrace;
   replay = btinfo->replay;
 
-  flags = btinfo->flags & BTHR_MOVE;
-  btinfo->flags &= ~BTHR_MOVE;
+  flags = btinfo->flags & (BTHR_MOVE | BTHR_STOP);
+  btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP);
 
   DEBUG ("stepping %d (%s): %u", tp->num, target_pid_to_str (tp->ptid), flags);
 
+  /* We can't step without an execution history.  */
+  if ((flags & BTHR_MOVE) != 0 && btrace_is_empty (tp))
+    return btrace_step_no_history ();
+
   switch (flags)
     {
     default:
       internal_error (__FILE__, __LINE__, _("invalid stepping type."));
 
+    case BTHR_STOP:
+      return btrace_step_stopped_on_request ();
+
     case BTHR_STEP:
       /* We're done if we're not replaying.  */
       if (replay == NULL)
@@ -2106,7 +2126,7 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
   /* Stop all other threads. */
   if (!target_is_non_stop_p ())
     ALL_NON_EXITED_THREADS (other)
-      other->btrace.flags &= ~BTHR_MOVE;
+      other->btrace.flags &= ~(BTHR_MOVE | BTHR_STOP);
 
   /* Start record histories anew from the current position.  */
   record_btrace_clear_histories (&tp->btrace);
@@ -2117,6 +2137,32 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
   return tp->ptid;
 }
 
+/* The to_stop method of target record-btrace.  */
+
+static void
+record_btrace_stop (struct target_ops *ops, ptid_t ptid)
+{
+  DEBUG ("stop %s", target_pid_to_str (ptid));
+
+  /* As long as we're not replaying, just forward the request.  */
+  if (!record_btrace_is_replaying (ops) && execution_direction != EXEC_REVERSE)
+    {
+      ops = ops->beneath;
+      ops->to_stop (ops, ptid);
+    }
+  else
+    {
+      struct thread_info *tp;
+
+      ALL_NON_EXITED_THREADS (tp)
+       if (ptid_match (tp->ptid, ptid))
+         {
+           tp->btrace.flags &= ~BTHR_MOVE;
+           tp->btrace.flags |= BTHR_STOP;
+         }
+    }
+ }
+
 /* The to_can_execute_reverse method of target record-btrace.  */
 
 static int
@@ -2350,6 +2396,7 @@ init_record_btrace_ops (void)
   ops->to_get_tailcall_unwinder = &record_btrace_to_get_tailcall_unwinder;
   ops->to_resume = record_btrace_resume;
   ops->to_wait = record_btrace_wait;
+  ops->to_stop = record_btrace_stop;
   ops->to_update_thread_list = record_btrace_update_thread_list;
   ops->to_thread_alive = record_btrace_thread_alive;
   ops->to_goto_record_begin = record_btrace_goto_begin;
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 17/19] target: add to_record_will_replay target method
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (2 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 09/19] btrace: resume all requested threads Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-18 11:39   ` Pedro Alves
  2015-09-17 14:10 ` [PATCH v3 06/19] btrace: move breakpoint checking into stepping functions Markus Metzger
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

Add a new target method to_record_will_replay to query if there is a record
target that will replay at least one thread matching the argument PTID if it
were executed in the argument execution direction.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c ((record_btrace_will_replay): New.
	(init_record_btrace_ops): Initialize to_record_will_replay.
	* record-full.c ((record_full_will_replay): New.
	(init_record_full_ops): Initialize to_record_will_replay.
	* target-delegates.c: Regenerated.
	* target.c (target_record_will_replay): New.
	* target.h (struct target_ops) <to_record_will_replay>: New.
	(target_record_will_replay): New.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>
---
 gdb/record-btrace.c    |  9 +++++++++
 gdb/record-full.c      | 14 ++++++++++++++
 gdb/target-delegates.c | 35 +++++++++++++++++++++++++++++++++++
 gdb/target.c           |  8 ++++++++
 gdb/target.h           |  8 ++++++++
 5 files changed, 74 insertions(+)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index e0b79a8..df15d77 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1147,6 +1147,14 @@ record_btrace_is_replaying (struct target_ops *self, ptid_t ptid)
   return 0;
 }
 
+/* The to_record_will_replay method of target record-btrace.  */
+
+static int
+record_btrace_will_replay (struct target_ops *self, ptid_t ptid, int dir)
+{
+  return dir == EXEC_REVERSE || record_btrace_is_replaying (self, ptid);
+}
+
 /* The to_xfer_partial method of target record-btrace.  */
 
 static enum target_xfer_status
@@ -2657,6 +2665,7 @@ init_record_btrace_ops (void)
   ops->to_call_history_from = record_btrace_call_history_from;
   ops->to_call_history_range = record_btrace_call_history_range;
   ops->to_record_is_replaying = record_btrace_is_replaying;
+  ops->to_record_will_replay = record_btrace_will_replay;
   ops->to_record_stop_replaying = record_btrace_stop_replaying_all;
   ops->to_xfer_partial = record_btrace_xfer_partial;
   ops->to_remove_breakpoint = record_btrace_remove_breakpoint;
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 35b3841..cb05437 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -1845,6 +1845,18 @@ record_full_is_replaying (struct target_ops *self, ptid_t ptid)
   return RECORD_FULL_IS_REPLAY;
 }
 
+/* The "to_record_will_replay" target method.  */
+
+static int
+record_full_will_replay (struct target_ops *self, ptid_t ptid, int dir)
+{
+  /* We can currently only record when executing forwards.  Should we be able
+     to record when executing backwards on targets that support reverse
+     execution, this needs to be changed.  */
+
+  return RECORD_FULL_IS_REPLAY || dir == EXEC_REVERSE;
+}
+
 /* Go to a specific entry.  */
 
 static void
@@ -1965,6 +1977,7 @@ init_record_full_ops (void)
   record_full_ops.to_save_record = record_full_save;
   record_full_ops.to_delete_record = record_full_delete;
   record_full_ops.to_record_is_replaying = record_full_is_replaying;
+  record_full_ops.to_record_will_replay = record_full_will_replay;
   record_full_ops.to_record_stop_replaying = record_full_stop_replaying;
   record_full_ops.to_goto_record_begin = record_full_goto_begin;
   record_full_ops.to_goto_record_end = record_full_goto_end;
@@ -2212,6 +2225,7 @@ init_record_full_core_ops (void)
   record_full_core_ops.to_info_record = record_full_info;
   record_full_core_ops.to_delete_record = record_full_delete;
   record_full_core_ops.to_record_is_replaying = record_full_is_replaying;
+  record_full_core_ops.to_record_will_replay = record_full_will_replay;
   record_full_core_ops.to_goto_record_begin = record_full_goto_begin;
   record_full_core_ops.to_goto_record_end = record_full_goto_end;
   record_full_core_ops.to_goto_record = record_full_goto;
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index a07c8c9..a7271fa 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -3630,6 +3630,37 @@ debug_record_is_replaying (struct target_ops *self, ptid_t arg1)
   return result;
 }
 
+static int
+delegate_record_will_replay (struct target_ops *self, ptid_t arg1, int arg2)
+{
+  self = self->beneath;
+  return self->to_record_will_replay (self, arg1, arg2);
+}
+
+static int
+tdefault_record_will_replay (struct target_ops *self, ptid_t arg1, int arg2)
+{
+  return 0;
+}
+
+static int
+debug_record_will_replay (struct target_ops *self, ptid_t arg1, int arg2)
+{
+  int result;
+  fprintf_unfiltered (gdb_stdlog, "-> %s->to_record_will_replay (...)\n", debug_target.to_shortname);
+  result = debug_target.to_record_will_replay (&debug_target, arg1, arg2);
+  fprintf_unfiltered (gdb_stdlog, "<- %s->to_record_will_replay (", debug_target.to_shortname);
+  target_debug_print_struct_target_ops_p (&debug_target);
+  fputs_unfiltered (", ", gdb_stdlog);
+  target_debug_print_ptid_t (arg1);
+  fputs_unfiltered (", ", gdb_stdlog);
+  target_debug_print_int (arg2);
+  fputs_unfiltered (") = ", gdb_stdlog);
+  target_debug_print_int (result);
+  fputs_unfiltered ("\n", gdb_stdlog);
+  return result;
+}
+
 static void
 delegate_record_stop_replaying (struct target_ops *self)
 {
@@ -4289,6 +4320,8 @@ install_delegators (struct target_ops *ops)
     ops->to_delete_record = delegate_delete_record;
   if (ops->to_record_is_replaying == NULL)
     ops->to_record_is_replaying = delegate_record_is_replaying;
+  if (ops->to_record_will_replay == NULL)
+    ops->to_record_will_replay = delegate_record_will_replay;
   if (ops->to_record_stop_replaying == NULL)
     ops->to_record_stop_replaying = delegate_record_stop_replaying;
   if (ops->to_goto_record_begin == NULL)
@@ -4458,6 +4491,7 @@ install_dummy_methods (struct target_ops *ops)
   ops->to_save_record = tdefault_save_record;
   ops->to_delete_record = tdefault_delete_record;
   ops->to_record_is_replaying = tdefault_record_is_replaying;
+  ops->to_record_will_replay = tdefault_record_will_replay;
   ops->to_record_stop_replaying = tdefault_record_stop_replaying;
   ops->to_goto_record_begin = tdefault_goto_record_begin;
   ops->to_goto_record_end = tdefault_goto_record_end;
@@ -4612,6 +4646,7 @@ init_debug_target (struct target_ops *ops)
   ops->to_save_record = debug_save_record;
   ops->to_delete_record = debug_delete_record;
   ops->to_record_is_replaying = debug_record_is_replaying;
+  ops->to_record_will_replay = debug_record_will_replay;
   ops->to_record_stop_replaying = debug_record_stop_replaying;
   ops->to_goto_record_begin = debug_goto_record_begin;
   ops->to_goto_record_end = debug_goto_record_end;
diff --git a/gdb/target.c b/gdb/target.c
index f73067c..8df862b 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3663,6 +3663,14 @@ target_record_is_replaying (ptid_t ptid)
 
 /* See target.h.  */
 
+int
+target_record_will_replay (ptid_t ptid, int dir)
+{
+  return current_target.to_record_will_replay (&current_target, ptid, dir);
+}
+
+/* See target.h.  */
+
 void
 target_record_stop_replaying (void)
 {
diff --git a/gdb/target.h b/gdb/target.h
index 169785d..16ae469 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1157,6 +1157,11 @@ struct target_ops
     int (*to_record_is_replaying) (struct target_ops *, ptid_t ptid)
       TARGET_DEFAULT_RETURN (0);
 
+    /* Query if the record target will replay PTID if it were resumed in
+       executin direction DIR.  */
+    int (*to_record_will_replay) (struct target_ops *, ptid_t ptid, int dir)
+      TARGET_DEFAULT_RETURN (0);
+
     /* Stop replaying.  */
     void (*to_record_stop_replaying) (struct target_ops *)
       TARGET_DEFAULT_IGNORE ();
@@ -2446,6 +2451,9 @@ extern void target_delete_record (void);
 /* See to_record_is_replaying in struct target_ops.  */
 extern int target_record_is_replaying (ptid_t ptid);
 
+/* See to_record_will_replay in struct target_ops.  */
+extern int target_record_will_replay (ptid_t ptid, int dir);
+
 /* See to_record_stop_replaying in struct target_ops.  */
 extern void target_record_stop_replaying (void);
 
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 03/19] btrace: improve stepping debugging
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (16 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 04/19] btrace: extract the breakpoint check from record_btrace_step_thread Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 19/19] btrace: honour scheduler-locking for all-stop targets Markus Metzger
  2015-09-18 11:41 ` [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Pedro Alves
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (btrace_thread_flag_to_str)
	(record_btrace_cancel_resume): New.
	(record_btrace_step_thread): Call btrace_thread_flag_to_str.
	(record_btrace_resume): Print execution direction.
	(record_btrace_resume_thread): Call btrace_thread_flag_to_str.
	(record_btrace_wait): Call record_btrace_cancel_resume.
---
 gdb/record-btrace.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 53 insertions(+), 4 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index a9ed4b7..7ee681c 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1659,6 +1659,32 @@ record_btrace_to_get_tailcall_unwinder (struct target_ops *self)
   return &record_btrace_tailcall_frame_unwind;
 }
 
+/* Return a human-readable string for FLAG.  */
+
+static const char *
+btrace_thread_flag_to_str (enum btrace_thread_flag flag)
+{
+  switch (flag)
+    {
+    case BTHR_STEP:
+      return "step";
+
+    case BTHR_RSTEP:
+      return "reverse-step";
+
+    case BTHR_CONT:
+      return "cont";
+
+    case BTHR_RCONT:
+      return "reverse-cont";
+
+    case BTHR_STOP:
+      return "stop";
+    }
+
+  return "<invalid>";
+}
+
 /* Indicate that TP should be resumed according to FLAG.  */
 
 static void
@@ -1667,7 +1693,8 @@ record_btrace_resume_thread (struct thread_info *tp,
 {
   struct btrace_thread_info *btinfo;
 
-  DEBUG ("resuming %d (%s): %u", tp->num, target_pid_to_str (tp->ptid), flag);
+  DEBUG ("resuming thread %d (%s): %x (%s)", tp->num,
+	 target_pid_to_str (tp->ptid), flag, btrace_thread_flag_to_str (flag));
 
   btinfo = &tp->btrace;
 
@@ -1820,7 +1847,9 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
   struct thread_info *tp, *other;
   enum btrace_thread_flag flag;
 
-  DEBUG ("resume %s: %s", target_pid_to_str (ptid), step ? "step" : "cont");
+  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.  */
   record_btrace_resume_exec_dir = execution_direction;
@@ -1865,6 +1894,24 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
     }
 }
 
+/* Cancel resuming TP.  */
+
+static void
+record_btrace_cancel_resume (struct thread_info *tp)
+{
+  enum btrace_thread_flag flags;
+
+  flags = tp->btrace.flags & (BTHR_MOVE | BTHR_STOP);
+  if (flags == 0)
+    return;
+
+  DEBUG ("cancel resume thread %d (%s): %x (%s)", tp->num,
+	 target_pid_to_str (tp->ptid), flags,
+	 btrace_thread_flag_to_str (flags));
+
+  tp->btrace.flags &= ~(BTHR_MOVE | BTHR_STOP);
+}
+
 /* Find a thread to move.  */
 
 static struct thread_info *
@@ -1955,7 +2002,9 @@ record_btrace_step_thread (struct thread_info *tp)
   flags = btinfo->flags & (BTHR_MOVE | BTHR_STOP);
   btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP);
 
-  DEBUG ("stepping %d (%s): %u", tp->num, target_pid_to_str (tp->ptid), flags);
+  DEBUG ("stepping thread %d (%s): %x (%s)", tp->num,
+	 target_pid_to_str (tp->ptid), flags,
+	 btrace_thread_flag_to_str (flags));
 
   /* We can't step without an execution history.  */
   if ((flags & BTHR_MOVE) != 0 && btrace_is_empty (tp))
@@ -2126,7 +2175,7 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
   /* Stop all other threads. */
   if (!target_is_non_stop_p ())
     ALL_NON_EXITED_THREADS (other)
-      other->btrace.flags &= ~(BTHR_MOVE | BTHR_STOP);
+      record_btrace_cancel_resume (other);
 
   /* Start record histories anew from the current position.  */
   record_btrace_clear_histories (&tp->btrace);
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 07/19] btrace: add missing NO_HISTORY
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (14 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 12/19] infrun: switch to NO_HISTORY thread Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 04/19] btrace: extract the breakpoint check from record_btrace_step_thread Markus Metzger
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

If a single-step ended right at the end of the execution history, we forgot
to announce that.  Fix it.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_single_step_forward): Return
	NO_HISTORY if a step brings us to the end of the execution history.
---
 gdb/record-btrace.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 5e8c1d4..fcd4351 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -2061,7 +2061,10 @@ record_btrace_single_step_forward (struct thread_info *tp)
 
   /* We stop replaying if we reached the end of the trace.  */
   if (btrace_insn_cmp (replay, &end) == 0)
-    record_btrace_stop_replaying (tp);
+    {
+      record_btrace_stop_replaying (tp);
+      return btrace_step_no_history ();
+    }
 
   return btrace_step_spurious ();
 }
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 14/19] target, record: add PTID argument to to_record_is_replaying
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (5 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 15/19] btrace: allow full memory and register access for non-replaying threads Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 11/19] btrace: async Markus Metzger
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

The to_record_is_replaying target method is used to query record targets if
they are replaying.  This is currently interpreted as "is any thread being
replayed".

Add a PTID argument and change the interpretation to "is any thread matching
PTID being replayed".

Change all users to pass minus_one_ptid to preserve the old meaning.

The record full target does not really support multi-threading and ignores
the PTID argument.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_is_replaying): Add ptid argument.
	Update users to pass minus_one_ptid.
	* record-full.c (record_full_is_replaying): Add ptid argument (ignored).
	* record.c (cmd_record_delete): Pass inferior_ptid to
	target_record_is_replaying.
	* target-delegates.c: Regenerated.
	* target.c (target_record_is_replaying): Add ptid argument.
	* target.h (struct target_ops) <to_record_is_replaying>: Add ptid
	argument.
	(target_record_is_replaying): Add ptid argument.
---
 gdb/record-btrace.c    | 33 +++++++++++++++++++--------------
 gdb/record-full.c      |  2 +-
 gdb/record.c           |  2 +-
 gdb/target-delegates.c | 12 +++++++-----
 gdb/target.c           |  4 ++--
 gdb/target.h           |  6 +++---
 6 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 8eefae2..481d22d 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1136,12 +1136,12 @@ record_btrace_call_history_from (struct target_ops *self,
 /* The to_record_is_replaying method of target record-btrace.  */
 
 static int
-record_btrace_is_replaying (struct target_ops *self)
+record_btrace_is_replaying (struct target_ops *self, ptid_t ptid)
 {
   struct thread_info *tp;
 
   ALL_NON_EXITED_THREADS (tp)
-    if (btrace_is_replaying (tp))
+    if (ptid_match (tp->ptid, ptid) && btrace_is_replaying (tp))
       return 1;
 
   return 0;
@@ -1160,7 +1160,7 @@ record_btrace_xfer_partial (struct target_ops *ops, enum target_object object,
   /* Filter out requests that don't make sense during replay.  */
   if (replay_memory_access == replay_memory_access_read_only
       && !record_btrace_generating_corefile
-      && record_btrace_is_replaying (ops))
+      && record_btrace_is_replaying (ops, minus_one_ptid))
     {
       switch (object)
 	{
@@ -1313,7 +1313,8 @@ record_btrace_store_registers (struct target_ops *ops,
 {
   struct target_ops *t;
 
-  if (!record_btrace_generating_corefile && record_btrace_is_replaying (ops))
+  if (!record_btrace_generating_corefile
+      && record_btrace_is_replaying (ops, minus_one_ptid))
     error (_("This record target does not allow writing registers."));
 
   gdb_assert (may_write_registers != 0);
@@ -1330,7 +1331,8 @@ record_btrace_prepare_to_store (struct target_ops *ops,
 {
   struct target_ops *t;
 
-  if (!record_btrace_generating_corefile && record_btrace_is_replaying (ops))
+  if (!record_btrace_generating_corefile
+      && record_btrace_is_replaying (ops, minus_one_ptid))
     return;
 
   t = ops->beneath;
@@ -1917,7 +1919,8 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
      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)
+  if ((execution_direction != EXEC_REVERSE)
+      && !record_btrace_is_replaying (ops, minus_one_ptid))
     {
       ops = ops->beneath;
       return ops->to_resume (ops, orig_ptid, step, signal);
@@ -2273,7 +2276,8 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
   DEBUG ("wait %s (0x%x)", target_pid_to_str (ptid), options);
 
   /* As long as we're not replaying, just forward the request.  */
-  if (!record_btrace_is_replaying (ops) && execution_direction != EXEC_REVERSE)
+  if ((execution_direction != EXEC_REVERSE)
+      && !record_btrace_is_replaying (ops, minus_one_ptid))
     {
       ops = ops->beneath;
       return ops->to_wait (ops, ptid, status, options);
@@ -2401,7 +2405,8 @@ record_btrace_stop (struct target_ops *ops, ptid_t ptid)
   DEBUG ("stop %s", target_pid_to_str (ptid));
 
   /* As long as we're not replaying, just forward the request.  */
-  if (!record_btrace_is_replaying (ops) && execution_direction != EXEC_REVERSE)
+  if ((execution_direction != EXEC_REVERSE)
+      && !record_btrace_is_replaying (ops, minus_one_ptid))
     {
       ops = ops->beneath;
       ops->to_stop (ops, ptid);
@@ -2432,7 +2437,7 @@ record_btrace_can_execute_reverse (struct target_ops *self)
 static int
 record_btrace_stopped_by_sw_breakpoint (struct target_ops *ops)
 {
-  if (record_btrace_is_replaying (ops))
+  if (record_btrace_is_replaying (ops, minus_one_ptid))
     {
       struct thread_info *tp = inferior_thread ();
 
@@ -2448,7 +2453,7 @@ record_btrace_stopped_by_sw_breakpoint (struct target_ops *ops)
 static int
 record_btrace_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
 {
-  if (record_btrace_is_replaying (ops))
+  if (record_btrace_is_replaying (ops, minus_one_ptid))
     return 1;
 
   return ops->beneath->to_supports_stopped_by_sw_breakpoint (ops->beneath);
@@ -2459,7 +2464,7 @@ record_btrace_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
 static int
 record_btrace_stopped_by_hw_breakpoint (struct target_ops *ops)
 {
-  if (record_btrace_is_replaying (ops))
+  if (record_btrace_is_replaying (ops, minus_one_ptid))
     {
       struct thread_info *tp = inferior_thread ();
 
@@ -2475,7 +2480,7 @@ record_btrace_stopped_by_hw_breakpoint (struct target_ops *ops)
 static int
 record_btrace_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
 {
-  if (record_btrace_is_replaying (ops))
+  if (record_btrace_is_replaying (ops, minus_one_ptid))
     return 1;
 
   return ops->beneath->to_supports_stopped_by_hw_breakpoint (ops->beneath);
@@ -2487,7 +2492,7 @@ static void
 record_btrace_update_thread_list (struct target_ops *ops)
 {
   /* We don't add or remove threads during replay.  */
-  if (record_btrace_is_replaying (ops))
+  if (record_btrace_is_replaying (ops, minus_one_ptid))
     return;
 
   /* Forward the request.  */
@@ -2501,7 +2506,7 @@ static int
 record_btrace_thread_alive (struct target_ops *ops, ptid_t ptid)
 {
   /* We don't add or remove threads during replay.  */
-  if (record_btrace_is_replaying (ops))
+  if (record_btrace_is_replaying (ops, minus_one_ptid))
     return find_thread_ptid (ptid) != NULL;
 
   /* Forward the request.  */
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 06bfdb8..03dc22d 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -1840,7 +1840,7 @@ record_full_delete (struct target_ops *self)
 /* The "to_record_is_replaying" target method.  */
 
 static int
-record_full_is_replaying (struct target_ops *self)
+record_full_is_replaying (struct target_ops *self, ptid_t ptid)
 {
   return RECORD_FULL_IS_REPLAY;
 }
diff --git a/gdb/record.c b/gdb/record.c
index ad83a29..71ef973 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -234,7 +234,7 @@ cmd_record_delete (char *args, int from_tty)
 {
   require_record_target ();
 
-  if (!target_record_is_replaying ())
+  if (!target_record_is_replaying (inferior_ptid))
     {
       printf_unfiltered (_("Already at end of record list.\n"));
       return;
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index c358814..9f909a0 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -3602,26 +3602,28 @@ debug_delete_record (struct target_ops *self)
 }
 
 static int
-delegate_record_is_replaying (struct target_ops *self)
+delegate_record_is_replaying (struct target_ops *self, ptid_t arg1)
 {
   self = self->beneath;
-  return self->to_record_is_replaying (self);
+  return self->to_record_is_replaying (self, arg1);
 }
 
 static int
-tdefault_record_is_replaying (struct target_ops *self)
+tdefault_record_is_replaying (struct target_ops *self, ptid_t arg1)
 {
   return 0;
 }
 
 static int
-debug_record_is_replaying (struct target_ops *self)
+debug_record_is_replaying (struct target_ops *self, ptid_t arg1)
 {
   int result;
   fprintf_unfiltered (gdb_stdlog, "-> %s->to_record_is_replaying (...)\n", debug_target.to_shortname);
-  result = debug_target.to_record_is_replaying (&debug_target);
+  result = debug_target.to_record_is_replaying (&debug_target, arg1);
   fprintf_unfiltered (gdb_stdlog, "<- %s->to_record_is_replaying (", debug_target.to_shortname);
   target_debug_print_struct_target_ops_p (&debug_target);
+  fputs_unfiltered (", ", gdb_stdlog);
+  target_debug_print_ptid_t (arg1);
   fputs_unfiltered (") = ", gdb_stdlog);
   target_debug_print_int (result);
   fputs_unfiltered ("\n", gdb_stdlog);
diff --git a/gdb/target.c b/gdb/target.c
index f425fbc..34d57ea 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3656,9 +3656,9 @@ target_delete_record (void)
 /* See target.h.  */
 
 int
-target_record_is_replaying (void)
+target_record_is_replaying (ptid_t ptid)
 {
-  return current_target.to_record_is_replaying (&current_target);
+  return current_target.to_record_is_replaying (&current_target, ptid);
 }
 
 /* See target.h.  */
diff --git a/gdb/target.h b/gdb/target.h
index 2875ad4..2afeae2 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1153,8 +1153,8 @@ struct target_ops
     void (*to_delete_record) (struct target_ops *)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
-    /* Query if the record target is currently replaying.  */
-    int (*to_record_is_replaying) (struct target_ops *)
+    /* Query if the record target is currently replaying PTID.  */
+    int (*to_record_is_replaying) (struct target_ops *, ptid_t ptid)
       TARGET_DEFAULT_RETURN (0);
 
     /* Go to the begin of the execution trace.  */
@@ -2440,7 +2440,7 @@ extern int target_supports_delete_record (void);
 extern void target_delete_record (void);
 
 /* See to_record_is_replaying in struct target_ops.  */
-extern int target_record_is_replaying (void);
+extern int target_record_is_replaying (ptid_t ptid);
 
 /* See to_goto_record_begin in struct target_ops.  */
 extern void target_goto_record_begin (void);
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 05/19] btrace: split record_btrace_step_thread
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (11 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 18/19] infrun: scheduler-locking replay Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 02/19] btrace: support to_stop Markus Metzger
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

The code for BTHR_STEP and BTHR_CONT is fairly similar.  Extract the common
parts into a new function record_btrace_single_step_forward.  The function
returns TARGET_WAITKIND_SPURIOUS to indicate that the single-step completed
without triggering a trap.

Same for BTHR_RSTEP and BTHR_RCONT.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (btrace_step_spurious)
	(record_btrace_single_step_forward)
	(record_btrace_single_step_backward): New.
	(record_btrace_step_thread): Call record_btrace_single_step_forward
	and record_btrace_single_step_backward.
---
 gdb/record-btrace.c | 187 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 105 insertions(+), 82 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 77494ba..fdf7afb 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1971,6 +1971,18 @@ btrace_step_stopped_on_request (void)
   return status;
 }
 
+/* Return a target_waitstatus indicating a spurious stop.  */
+
+static struct target_waitstatus
+btrace_step_spurious (void)
+{
+  struct target_waitstatus status;
+
+  status.kind = TARGET_WAITKIND_SPURIOUS;
+
+  return status;
+}
+
 /* Clear the record histories.  */
 
 static void
@@ -2011,20 +2023,86 @@ record_btrace_replay_at_breakpoint (struct thread_info *tp)
 					     &btinfo->stop_reason);
 }
 
-/* Step a single thread.  */
+/* Step one instruction in forward direction.  */
 
 static struct target_waitstatus
-record_btrace_step_thread (struct thread_info *tp)
+record_btrace_single_step_forward (struct thread_info *tp)
 {
   struct btrace_insn_iterator *replay, end;
   struct btrace_thread_info *btinfo;
-  enum btrace_thread_flag flags;
-  unsigned int steps;
 
+  btinfo = &tp->btrace;
+  replay = btinfo->replay;
+
+  /* We're done if we're not replaying.  */
+  if (replay == NULL)
+    return btrace_step_no_history ();
+
+  /* Skip gaps during replay.  */
+  do
+    {
+      unsigned int steps;
+
+      steps = btrace_insn_next (replay, 1);
+      if (steps == 0)
+	{
+	  record_btrace_stop_replaying (tp);
+	  return btrace_step_no_history ();
+	}
+    }
+  while (btrace_insn_get (replay) == NULL);
+
+  /* Determine the end of the instruction trace.  */
+  btrace_insn_end (&end, btinfo);
+
+  /* We stop replaying if we reached the end of the trace.  */
+  if (btrace_insn_cmp (replay, &end) == 0)
+    record_btrace_stop_replaying (tp);
+
+  return btrace_step_spurious ();
+}
+
+/* Step one instruction in backward direction.  */
+
+static struct target_waitstatus
+record_btrace_single_step_backward (struct thread_info *tp)
+{
+  struct btrace_insn_iterator *replay;
+  struct btrace_thread_info *btinfo;
 
   btinfo = &tp->btrace;
   replay = btinfo->replay;
 
+  /* Start replaying if we're not already doing so.  */
+  if (replay == NULL)
+    replay = record_btrace_start_replaying (tp);
+
+  /* If we can't step any further, we reached the end of the history.
+     Skip gaps during replay.  */
+  do
+    {
+      unsigned int steps;
+
+      steps = btrace_insn_prev (replay, 1);
+      if (steps == 0)
+	return btrace_step_no_history ();
+    }
+  while (btrace_insn_get (replay) == NULL);
+
+  return btrace_step_spurious ();
+}
+
+/* Step a single thread.  */
+
+static struct target_waitstatus
+record_btrace_step_thread (struct thread_info *tp)
+{
+  struct btrace_thread_info *btinfo;
+  struct target_waitstatus status;
+  enum btrace_thread_flag flags;
+
+  btinfo = &tp->btrace;
+
   flags = btinfo->flags & (BTHR_MOVE | BTHR_STOP);
   btinfo->flags &= ~(BTHR_MOVE | BTHR_STOP);
 
@@ -2045,110 +2123,55 @@ record_btrace_step_thread (struct thread_info *tp)
       return btrace_step_stopped_on_request ();
 
     case BTHR_STEP:
-      /* We're done if we're not replaying.  */
-      if (replay == NULL)
-	return btrace_step_no_history ();
-
-      /* Skip gaps during replay.  */
-      do
-	{
-	  steps = btrace_insn_next (replay, 1);
-	  if (steps == 0)
-	    {
-	      record_btrace_stop_replaying (tp);
-	      return btrace_step_no_history ();
-	    }
-	}
-      while (btrace_insn_get (replay) == NULL);
-
-      /* Determine the end of the instruction trace.  */
-      btrace_insn_end (&end, btinfo);
-
-      /* We stop replaying if we reached the end of the trace.  */
-      if (btrace_insn_cmp (replay, &end) == 0)
-	record_btrace_stop_replaying (tp);
+      status = record_btrace_single_step_forward (tp);
+      if (status.kind != TARGET_WAITKIND_SPURIOUS)
+	return status;
 
       return btrace_step_stopped ();
 
     case BTHR_RSTEP:
-      /* Start replaying if we're not already doing so.  */
-      if (replay == NULL)
-	replay = record_btrace_start_replaying (tp);
-
-      /* If we can't step any further, we reached the end of the history.
-	 Skip gaps during replay.  */
-      do
-	{
-	  steps = btrace_insn_prev (replay, 1);
-	  if (steps == 0)
-	    return btrace_step_no_history ();
-
-	}
-      while (btrace_insn_get (replay) == NULL);
+      status = record_btrace_single_step_backward (tp);
+      if (status.kind != TARGET_WAITKIND_SPURIOUS)
+	return status;
 
       return btrace_step_stopped ();
 
     case BTHR_CONT:
-      /* We're done if we're not replaying.  */
-      if (replay == NULL)
-	return btrace_step_no_history ();
-
-      /* Determine the end of the instruction trace.  */
-      btrace_insn_end (&end, btinfo);
-
       for (;;)
 	{
-	  const struct btrace_insn *insn;
+	  status = record_btrace_single_step_forward (tp);
+	  if (status.kind != TARGET_WAITKIND_SPURIOUS)
+	    return status;
 
-	  /* Skip gaps during replay.  */
-	  do
+	  if (btinfo->replay != NULL)
 	    {
-	      steps = btrace_insn_next (replay, 1);
-	      if (steps == 0)
-		{
-		  record_btrace_stop_replaying (tp);
-		  return btrace_step_no_history ();
-		}
+	      const struct btrace_insn *insn;
 
-	      insn = btrace_insn_get (replay);
-	    }
-	  while (insn == NULL);
+	      insn = btrace_insn_get (btinfo->replay);
+	      gdb_assert (insn != NULL);
 
-	  /* We stop replaying if we reached the end of the trace.  */
-	  if (btrace_insn_cmp (replay, &end) == 0)
-	    {
-	      record_btrace_stop_replaying (tp);
-	      return btrace_step_no_history ();
+	      DEBUG ("stepping %d (%s) ... %s", tp->num,
+		     target_pid_to_str (tp->ptid),
+		     core_addr_to_string_nz (insn->pc));
 	    }
 
-	  DEBUG ("stepping %d (%s) ... %s", tp->num,
-		 target_pid_to_str (tp->ptid),
-		 core_addr_to_string_nz (insn->pc));
-
 	  if (record_btrace_replay_at_breakpoint (tp))
 	    return btrace_step_stopped ();
 	}
 
     case BTHR_RCONT:
-      /* Start replaying if we're not already doing so.  */
-      if (replay == NULL)
-	replay = record_btrace_start_replaying (tp);
-
       for (;;)
 	{
 	  const struct btrace_insn *insn;
 
-	  /* If we can't step any further, we reached the end of the history.
-	     Skip gaps during replay.  */
-	  do
-	    {
-	      steps = btrace_insn_prev (replay, 1);
-	      if (steps == 0)
-		return btrace_step_no_history ();
+	  status = record_btrace_single_step_backward (tp);
+	  if (status.kind != TARGET_WAITKIND_SPURIOUS)
+	    return status;
 
-	      insn = btrace_insn_get (replay);
-	    }
-	  while (insn == NULL);
+	  gdb_assert (btinfo->replay != NULL);
+
+	  insn = btrace_insn_get (btinfo->replay);
+	  gdb_assert (insn != NULL);
 
 	  DEBUG ("reverse-stepping %d (%s) ... %s", tp->num,
 		 target_pid_to_str (tp->ptid),
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 19/19] btrace: honour scheduler-locking for all-stop targets
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (17 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 03/19] btrace: improve stepping debugging Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-18 11:39   ` Pedro Alves
  2015-09-18 11:41 ` [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Pedro Alves
  19 siblings, 1 reply; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

In all-stop mode, record btrace maintains the old behaviour of an implicit
scheduler-locking on.

Now that we added a scheduler-locking mode to model this old behaviour, we
don't need the respective code in record btrace anymore.  Remove it.

For all-stop targets, step inferior_ptid and continue other threads matching
the argument ptid.  Assert that inferior_ptid matches the argument ptid.

This should make record btrace honour scheduler-locking.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_resume): Honour scheduler-locking.

testsuite/
	* gdb.btrace/multi-thread-step.exp: Test scheduler-locking on, step,
	and replay.
---
 gdb/record-btrace.c                            |  57 +++---
 gdb/testsuite/gdb.btrace/multi-thread-step.exp | 233 +++++++++++++++++--------
 2 files changed, 192 insertions(+), 98 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 42195d1..d14e6cf 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1888,33 +1888,18 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
 		      enum gdb_signal signal)
 {
   struct thread_info *tp;
-  enum btrace_thread_flag flag;
-  ptid_t orig_ptid;
+  enum btrace_thread_flag flag, cflag;
 
   DEBUG ("resume %s: %s%s", target_pid_to_str (ptid),
 	 execution_direction == EXEC_REVERSE ? "reverse-" : "",
 	 step ? "step" : "cont");
 
-  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;
 
-  /* For all-stop targets we pick the current thread when asked to resume an
-     entire process or everything.  */
-  if (!target_is_non_stop_p ())
-    {
-      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."));
-    }
-
   /* 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
@@ -1924,20 +1909,44 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step,
       && !record_btrace_is_replaying (ops, minus_one_ptid))
     {
       ops = ops->beneath;
-      return ops->to_resume (ops, orig_ptid, step, signal);
+      return ops->to_resume (ops, ptid, step, signal);
     }
 
   /* Compute the btrace thread flag for the requested move.  */
-  if (step == 0)
-    flag = execution_direction == EXEC_REVERSE ? BTHR_RCONT : BTHR_CONT;
+  if (execution_direction == EXEC_REVERSE)
+    {
+      flag = step == 0 ? BTHR_RCONT : BTHR_RSTEP;
+      cflag = BTHR_RCONT;
+    }
   else
-    flag = execution_direction == EXEC_REVERSE ? BTHR_RSTEP : BTHR_STEP;
+    {
+      flag = step == 0 ? BTHR_CONT : BTHR_STEP;
+      cflag = BTHR_CONT;
+    }
 
   /* 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);
+     record_btrace_wait below.
+
+     For all-stop targets, we only step INFERIOR_PTID and continue others.  */
+  if (!target_is_non_stop_p ())
+    {
+      gdb_assert (ptid_match (inferior_ptid, ptid));
+
+      ALL_NON_EXITED_THREADS (tp)
+	if (ptid_match (tp->ptid, ptid))
+	  {
+	    if (ptid_match (tp->ptid, inferior_ptid))
+	      record_btrace_resume_thread (tp, flag);
+	    else
+	      record_btrace_resume_thread (tp, cflag);
+	  }
+    }
+  else
+    {
+      ALL_NON_EXITED_THREADS (tp)
+	if (ptid_match (tp->ptid, ptid))
+	  record_btrace_resume_thread (tp, flag);
+    }
 
   /* Async support.  */
   if (target_can_async_p ())
diff --git a/gdb/testsuite/gdb.btrace/multi-thread-step.exp b/gdb/testsuite/gdb.btrace/multi-thread-step.exp
index 2295f71..c8f55d0 100644
--- a/gdb/testsuite/gdb.btrace/multi-thread-step.exp
+++ b/gdb/testsuite/gdb.btrace/multi-thread-step.exp
@@ -37,9 +37,29 @@ set bp_2 [gdb_get_line_number "bp.2" $srcfile]
 set bp_3 [gdb_get_line_number "bp.3" $srcfile]
 
 proc gdb_cont_to_line { line } {
-	gdb_breakpoint $line
-	gdb_continue_to_breakpoint "cont to $line" ".*$line\r\n.*"
-	delete_breakpoints
+    gdb_breakpoint $line
+    gdb_continue_to_breakpoint "cont to $line" ".*$line\r\n.*"
+    delete_breakpoints
+}
+
+proc check_replay_insn { thread insn } {
+    gdb_test "thread apply $thread info record" \
+        "Replay in progress\.  At instruction $insn\."
+}
+
+proc check_not_replaying { thread } {
+    global gdb_prompt
+
+    set test "thread $thread not replaying"
+
+    gdb_test_multiple "thread apply $thread info record" $test {
+        -re "Replay in progress" {
+            fail $test
+        }
+        -re "$gdb_prompt $" {
+            pass $test
+        }
+    }
 }
 
 # trace the code between the two breakpoints
@@ -50,86 +70,151 @@ gdb_test "info threads" ".*"
 gdb_test_no_output "record btrace"
 gdb_cont_to_line $srcfile:$bp_2
 
-# navigate in the trace history for both threads
-with_test_prefix "navigate" {
-  gdb_test "thread 1" ".*"
-  with_test_prefix "thread 1" {
-    gdb_test "record goto begin" ".*"
-    gdb_test "info record" ".*Replay in progress\.  At instruction 1\."
-  }
-  gdb_test "thread 2" ".*"
-  with_test_prefix "thread 2" {
-    gdb_test "record goto begin" ".*"
-    gdb_test "info record" ".*Replay in progress\.  At instruction 1\."
-  }
+proc test_navigate {} {
+    with_test_prefix "navigate" {
+        gdb_test "thread 1" ".*"
+        with_test_prefix "thread 1" {
+            gdb_test "record goto begin" ".*"
+
+            check_replay_insn 1 1
+            check_not_replaying 2
+        }
+        gdb_test "thread 2" ".*"
+        with_test_prefix "thread 2" {
+            gdb_test "record goto begin" ".*"
+
+            check_replay_insn 1 1
+            check_replay_insn 2 1
+        }
+    }
+}
+
+proc test_step {} {
+    with_test_prefix "step" {
+        gdb_test "thread 1" ".*"
+        with_test_prefix "thread 1" {
+            gdb_test "stepi" ".*"
+
+            check_replay_insn 1 2
+            check_replay_insn 2 1
+        }
+        gdb_test "thread 2" ".*"
+        with_test_prefix "thread 2" {
+            gdb_test "stepi" ".*"
+
+            check_replay_insn 1 2
+            check_replay_insn 2 2
+        }
+    }
+}
+
+proc test_cont {} {
+    with_test_prefix "cont" {
+        gdb_test "thread 1" ".*"
+        with_test_prefix "thread 1" {
+            gdb_test "continue" "No more reverse-execution history.*"
+
+            check_not_replaying 1
+            check_replay_insn 2 2
+        }
+        gdb_test "thread 2" ".*"
+        with_test_prefix "thread 2" {
+            gdb_test "continue" "No more reverse-execution history.*"
+
+            check_not_replaying 1
+            check_not_replaying 2
+        }
+    }
 }
 
-# step both threads
-with_test_prefix "step" {
-  gdb_test "thread 1" ".*"
-  with_test_prefix "thread 1" {
-    gdb_test "info record" ".*Replay in progress\.  At instruction 1\."
-    gdb_test "stepi" ".*"
-    gdb_test "info record" ".*Replay in progress\.  At instruction 2\."
-  }
-  gdb_test "thread 2" ".*"
-  with_test_prefix "thread 2" {
-    gdb_test "info record" ".*Replay in progress\.  At instruction 1\."
-    gdb_test "stepi" ".*"
-    gdb_test "info record" ".*Replay in progress\.  At instruction 2\."
-  }
+proc test_cont_all {} {
+    with_test_prefix "cont-all" {
+        gdb_test "continue" "No more reverse-execution history.*"
+
+        # this works because we're lock-stepping threads that executed exactly
+        # the same code starting from the same instruction.
+
+        check_not_replaying 1
+        check_not_replaying 2
+    }
+}
+
+proc test_rstep {} {
+    with_test_prefix "reverse-step" {
+        gdb_test "thread apply all record goto 3"
+
+        gdb_test "thread 1" ".*"
+        with_test_prefix "thread 1" {
+            gdb_test "reverse-stepi" ".*"
+
+            check_replay_insn 1 2
+            check_replay_insn 2 3
+        }
+        gdb_test "thread 2" ".*"
+        with_test_prefix "thread 2" {
+            gdb_test "reverse-stepi" ".*"
+
+            check_replay_insn 1 2
+            check_replay_insn 2 2
+        }
+    }
 }
 
-# run to the end of the history for both threads
-with_test_prefix "cont" {
-  gdb_test "thread 1" ".*"
-  with_test_prefix "thread 1" {
-    gdb_test "info record" ".*Replay in progress\.  At instruction 2\."
-    gdb_test "continue" "No more reverse-execution history.*"
-  }
-  gdb_test "thread 2" ".*"
-  with_test_prefix "thread 2" {
-    gdb_test "info record" ".*Replay in progress\.  At instruction 2\."
-    gdb_test "continue" "No more reverse-execution history.*"
-  }
+proc test_goto_end {} {
+    with_test_prefix "goto-end" {
+        gdb_test "thread apply all record goto end"
+
+        check_not_replaying 1
+        check_not_replaying 2
+    }
 }
 
-# reverse-step both threads
-with_test_prefix "reverse-step" {
-  gdb_test "thread 1" ".*"
-  with_test_prefix "thread 1" {
-    gdb_test "reverse-stepi" ".*"
-    gdb_test "info record" ".*Replay in progress\..*"
-  }
-  gdb_test "thread 2" ".*"
-  with_test_prefix "thread 2" {
-    gdb_test "reverse-stepi" ".*"
-    gdb_test "info record" ".*Replay in progress\..*"
-  }
+foreach schedlock { "replay" "on" } {
+	with_test_prefix "schedlock-$schedlock" {
+		gdb_test_no_output "set scheduler-locking $schedlock"
+
+		test_navigate
+		test_step
+		test_cont
+		test_rstep
+		test_goto_end
+	}
 }
 
-# both threads are still replaying
-with_test_prefix "check" {
-  gdb_test "thread 1" ".*"
-  with_test_prefix "thread 1" {
-    gdb_test "info record" ".*Replay in progress\..*"
-  }
-  gdb_test "thread 2" ".*"
-  with_test_prefix "thread 2" {
-    gdb_test "info record" ".*Replay in progress\..*"
-  }
+with_test_prefix "schedlock-step" {
+    gdb_test_no_output "set scheduler-locking step"
+
+    test_navigate
+    test_step
+    test_cont_all
+    test_rstep
+    test_goto_end
 }
 
+# schedlock-off is difficult to test since we can't really say where the other
+# thread will be when the resumed thread stops.
+
 # navigate back into the history for thread 1 and continue thread 2
-with_test_prefix "cont" {
-  gdb_test "thread 1" ".*"
-  with_test_prefix "thread 1" {
-    gdb_test "record goto begin" ".*"
-    gdb_test "info record" ".*Replay in progress\.  At instruction 1\."
-  }
-  gdb_test "thread 2" ".*"
-  with_test_prefix "thread 2" {
-    gdb_test "record goto end" ".*"
-    gdb_cont_to_line $srcfile:$bp_3
-  }
+with_test_prefix "cont-to-end" {
+    # this test only works for scheduler-locking replay
+    gdb_test_no_output "set scheduler-locking replay"
+
+    gdb_test "thread 1" ".*"
+    with_test_prefix "thread 1" {
+        gdb_test "record goto begin" ".*"
+
+        check_replay_insn 1 1
+    }
+    gdb_test "thread 2" ".*"
+    with_test_prefix "thread 2" {
+        gdb_test "record goto end" ".*"
+
+        check_not_replaying 2
+
+        # if we reach the breakpoint, thread 2 terminated...
+        gdb_cont_to_line $srcfile:$bp_3
+
+        # and thread 1 stopped replaying
+        check_not_replaying 1
+    }
 }
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 11/19] btrace: async
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (6 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 14/19] target, record: add PTID argument to to_record_is_replaying Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 13/19] btrace: non-stop Markus Metzger
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

The record btrace target runs synchronous with GDB.  That is, GDB steps
resumed threads in record btrace's to_wait method.  Without GDB calling
to_wait, nothing happens 'on the target'.

Check for further expected events in to_wait before reporting the current
event and mark record btrace's async event handler in async mode.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_maybe_mark_async_event): New.
	(record_btrace_wait): Call record_btrace_maybe_mark_async_event.
---
 gdb/record-btrace.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 0514471..764b349 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -2240,6 +2240,29 @@ record_btrace_step_thread (struct thread_info *tp)
 typedef struct thread_info * tp_t;
 DEF_VEC_P (tp_t);
 
+/* Announce further events if necessary.  */
+
+static void
+record_btrace_maybe_mark_async_event (const VEC (tp_t) *moving,
+				      const VEC (tp_t) *no_history)
+{
+  int more_moving, more_no_history;
+
+  more_moving = !VEC_empty (tp_t, moving);
+  more_no_history = !VEC_empty (tp_t, no_history);
+
+  if (!more_moving && !more_no_history)
+    return;
+
+  if (more_moving)
+    DEBUG ("movers pending");
+
+  if (more_no_history)
+    DEBUG ("no-history pending");
+
+  mark_async_event_handler (record_btrace_async_inferior_event_handler);
+}
+
 /* The to_wait method of target record-btrace.  */
 
 static ptid_t
@@ -2355,6 +2378,10 @@ record_btrace_wait (struct target_ops *ops, ptid_t ptid,
     ALL_NON_EXITED_THREADS (tp)
       record_btrace_cancel_resume (tp);
 
+  /* In async mode, we need to announce further events.  */
+  if (target_is_async_p ())
+    record_btrace_maybe_mark_async_event (moving, no_history);
+
   /* Start record histories anew from the current position.  */
   record_btrace_clear_histories (&eventing->btrace);
 
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 10/19] btrace: temporarily set inferior_ptid in record_btrace_start_replaying
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (8 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 13/19] btrace: non-stop Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 16/19] target: add to_record_stop_replaying target method Markus Metzger
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

Get_current_frame uses inferior_ptid.  In record_btrace_start_replaying,
we need to get the current frame of the argument thread.  So far, this
has always been inferior_ptid.  With non-stop, this is not guaranteed.

Temporarily set inferior_ptid to the ptid of the argument thread.

We already temporarily set the argument thread's executing flag to false.

Move both into a new function get_thread_current_frame that does the temporary
adjustments, calls get_current_frame, and restores the previous values.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (get_thread_current_frame): New.
	(record_btrace_start_replaying): Call get_thread_current_frame.
---
 gdb/record-btrace.c | 70 ++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 51 insertions(+), 19 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index c25b8f4..0514471 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1707,6 +1707,55 @@ record_btrace_resume_thread (struct thread_info *tp,
   btinfo->flags |= flag;
 }
 
+/* Get the current frame for TP.  */
+
+static struct frame_info *
+get_thread_current_frame (struct thread_info *tp)
+{
+  struct frame_info *frame;
+  ptid_t old_inferior_ptid;
+  int executing;
+
+  /* Set INFERIOR_PTID, which is implicitly used by get_current_frame.  */
+  old_inferior_ptid = inferior_ptid;
+  inferior_ptid = tp->ptid;
+
+  /* Clear the executing flag to allow changes to the current frame.
+     We are not actually running, yet.  We just started a reverse execution
+     command or a record goto command.
+     For the latter, EXECUTING is false and this has no effect.
+     For the former, EXECUTING is true and we're in to_wait, about to
+     move the thread.  Since we need to recompute the stack, we temporarily
+     set EXECUTING to flase.  */
+  executing = is_executing (inferior_ptid);
+  set_executing (inferior_ptid, 0);
+
+  frame = NULL;
+  TRY
+    {
+      frame = get_current_frame ();
+    }
+  CATCH (except, RETURN_MASK_ALL)
+    {
+      /* Restore the previous execution state.  */
+      set_executing (inferior_ptid, executing);
+
+      /* Restore the previous inferior_ptid.  */
+      inferior_ptid = old_inferior_ptid;
+
+      throw_exception (except);
+    }
+  END_CATCH
+
+  /* Restore the previous execution state.  */
+  set_executing (inferior_ptid, executing);
+
+  /* Restore the previous inferior_ptid.  */
+  inferior_ptid = old_inferior_ptid;
+
+  return frame;
+}
+
 /* Start replaying a thread.  */
 
 static struct btrace_insn_iterator *
@@ -1714,7 +1763,6 @@ record_btrace_start_replaying (struct thread_info *tp)
 {
   struct btrace_insn_iterator *replay;
   struct btrace_thread_info *btinfo;
-  int executing;
 
   btinfo = &tp->btrace;
   replay = NULL;
@@ -1723,16 +1771,6 @@ record_btrace_start_replaying (struct thread_info *tp)
   if (btinfo->begin == NULL)
     return NULL;
 
-  /* Clear the executing flag to allow changes to the current frame.
-     We are not actually running, yet.  We just started a reverse execution
-     command or a record goto command.
-     For the latter, EXECUTING is false and this has no effect.
-     For the former, EXECUTING is true and we're in to_wait, about to
-     move the thread.  Since we need to recompute the stack, we temporarily
-     set EXECUTING to flase.  */
-  executing = is_executing (tp->ptid);
-  set_executing (tp->ptid, 0);
-
   /* GDB stores the current frame_id when stepping in order to detects steps
      into subroutines.
      Since frames are computed differently when we're replaying, we need to
@@ -1745,7 +1783,7 @@ record_btrace_start_replaying (struct thread_info *tp)
       int upd_step_frame_id, upd_step_stack_frame_id;
 
       /* The current frame without replaying - computed via normal unwind.  */
-      frame = get_current_frame ();
+      frame = get_thread_current_frame (tp);
       frame_id = get_frame_id (frame);
 
       /* Check if we need to update any stepping-related frame id's.  */
@@ -1777,7 +1815,7 @@ record_btrace_start_replaying (struct thread_info *tp)
       registers_changed_ptid (tp->ptid);
 
       /* The current frame with replaying - computed via btrace unwind.  */
-      frame = get_current_frame ();
+      frame = get_thread_current_frame (tp);
       frame_id = get_frame_id (frame);
 
       /* Replace stepping related frames where necessary.  */
@@ -1788,9 +1826,6 @@ record_btrace_start_replaying (struct thread_info *tp)
     }
   CATCH (except, RETURN_MASK_ALL)
     {
-      /* Restore the previous execution state.  */
-      set_executing (tp->ptid, executing);
-
       xfree (btinfo->replay);
       btinfo->replay = NULL;
 
@@ -1800,9 +1835,6 @@ record_btrace_start_replaying (struct thread_info *tp)
     }
   END_CATCH
 
-  /* Restore the previous execution state.  */
-  set_executing (tp->ptid, executing);
-
   return replay;
 }
 
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 04/19] btrace: extract the breakpoint check from record_btrace_step_thread
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (15 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 07/19] btrace: add missing NO_HISTORY Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 03/19] btrace: improve stepping debugging Markus Metzger
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

There are two places where record_btrace_step_thread checks for a breakpoint
at the current replay position.  Move this code into its own function.

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

gdb/
	* record-btrace.c (record_btrace_replay_at_breakpoint): New.
	(record_btrace_step_thread): Call record_btrace_replay_at_breakpoint.
---
 gdb/record-btrace.c | 42 ++++++++++++++++++++++++++++++------------
 1 file changed, 30 insertions(+), 12 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 7ee681c..77494ba 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1983,6 +1983,34 @@ record_btrace_clear_histories (struct btrace_thread_info *btinfo)
   btinfo->call_history = NULL;
 }
 
+/* Check whether TP's current replay position is at a breakpoint.  */
+
+static int
+record_btrace_replay_at_breakpoint (struct thread_info *tp)
+{
+  struct btrace_insn_iterator *replay;
+  struct btrace_thread_info *btinfo;
+  const struct btrace_insn *insn;
+  struct inferior *inf;
+
+  btinfo = &tp->btrace;
+  replay = btinfo->replay;
+
+  if (replay == NULL)
+    return 0;
+
+  insn = btrace_insn_get (replay);
+  if (insn == NULL)
+    return 0;
+
+  inf = find_inferior_ptid (tp->ptid);
+  if (inf == NULL)
+    return 0;
+
+  return record_check_stopped_by_breakpoint (inf->aspace, insn->pc,
+					     &btinfo->stop_reason);
+}
+
 /* Step a single thread.  */
 
 static struct target_waitstatus
@@ -1990,8 +2018,6 @@ record_btrace_step_thread (struct thread_info *tp)
 {
   struct btrace_insn_iterator *replay, end;
   struct btrace_thread_info *btinfo;
-  struct address_space *aspace;
-  struct inferior *inf;
   enum btrace_thread_flag flags;
   unsigned int steps;
 
@@ -2067,9 +2093,6 @@ record_btrace_step_thread (struct thread_info *tp)
       if (replay == NULL)
 	return btrace_step_no_history ();
 
-      inf = find_inferior_ptid (tp->ptid);
-      aspace = inf->aspace;
-
       /* Determine the end of the instruction trace.  */
       btrace_insn_end (&end, btinfo);
 
@@ -2102,8 +2125,7 @@ record_btrace_step_thread (struct thread_info *tp)
 		 target_pid_to_str (tp->ptid),
 		 core_addr_to_string_nz (insn->pc));
 
-	  if (record_check_stopped_by_breakpoint (aspace, insn->pc,
-						  &btinfo->stop_reason))
+	  if (record_btrace_replay_at_breakpoint (tp))
 	    return btrace_step_stopped ();
 	}
 
@@ -2112,9 +2134,6 @@ record_btrace_step_thread (struct thread_info *tp)
       if (replay == NULL)
 	replay = record_btrace_start_replaying (tp);
 
-      inf = find_inferior_ptid (tp->ptid);
-      aspace = inf->aspace;
-
       for (;;)
 	{
 	  const struct btrace_insn *insn;
@@ -2135,8 +2154,7 @@ record_btrace_step_thread (struct thread_info *tp)
 		 target_pid_to_str (tp->ptid),
 		 core_addr_to_string_nz (insn->pc));
 
-	  if (record_check_stopped_by_breakpoint (aspace, insn->pc,
-						  &btinfo->stop_reason))
+	  if (record_btrace_replay_at_breakpoint (tp))
 	    return btrace_step_stopped ();
 	}
     }
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v3 09/19] btrace: resume all requested threads
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
  2015-09-17 14:09 ` [PATCH v3 01/19] btrace: fix non-stop check in to_wait Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 08/19] btrace: lock-step Markus Metzger
@ 2015-09-17 14:10 ` Markus Metzger
  2015-09-17 14:10 ` [PATCH v3 17/19] target: add to_record_will_replay target method Markus Metzger
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 27+ messages in thread
From: Markus Metzger @ 2015-09-17 14:10 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

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".

2015-09-17  Markus Metzger <markus.t.metzger@intel.com>

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/record-btrace.c | 73 ++++++++++++++++++++++++++---------------------------
 1 file changed, 36 insertions(+), 37 deletions(-)

diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index bda9b7c..c25b8f4 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 ())
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 19/19] btrace: honour scheduler-locking for all-stop targets
  2015-09-17 14:10 ` [PATCH v3 19/19] btrace: honour scheduler-locking for all-stop targets Markus Metzger
@ 2015-09-18 11:39   ` Pedro Alves
  0 siblings, 0 replies; 27+ messages in thread
From: Pedro Alves @ 2015-09-18 11:39 UTC (permalink / raw)
  To: Markus Metzger; +Cc: gdb-patches

On 09/17/2015 03:09 PM, Markus Metzger wrote:
> +foreach schedlock { "replay" "on" } {
> +	with_test_prefix "schedlock-$schedlock" {
> +		gdb_test_no_output "set scheduler-locking $schedlock"
> +
> +		test_navigate
> +		test_step
> +		test_cont
> +		test_rstep
> +		test_goto_end
> +	}
>  }
>  

Indenting here looks odd compared to the rest of the file.

I'd merge in the "step" case too, like:

foreach schedlock { "replay" "on" "step" } {
    with_test_prefix "schedlock-$schedlock" {
	gdb_test_no_output "set scheduler-locking $schedlock"

	test_navigate
	test_step
	if {$schedlock == "step"} {
	    test_cont_all
	} else {
	    test_cont
	}
	test_rstep
	test_goto_end
    }
}

Otherwise looks fine to me.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 17/19] target: add to_record_will_replay target method
  2015-09-17 14:10 ` [PATCH v3 17/19] target: add to_record_will_replay target method Markus Metzger
@ 2015-09-18 11:39   ` Pedro Alves
  0 siblings, 0 replies; 27+ messages in thread
From: Pedro Alves @ 2015-09-18 11:39 UTC (permalink / raw)
  To: Markus Metzger; +Cc: gdb-patches

On 09/17/2015 03:09 PM, Markus Metzger wrote:
>  
> +    /* Query if the record target will replay PTID if it were resumed in
> +       executin direction DIR.  */

Typo: "execution".

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 18/19] infrun: scheduler-locking replay
  2015-09-17 14:10 ` [PATCH v3 18/19] infrun: scheduler-locking replay Markus Metzger
@ 2015-09-18 11:39   ` Pedro Alves
  0 siblings, 0 replies; 27+ messages in thread
From: Pedro Alves @ 2015-09-18 11:39 UTC (permalink / raw)
  To: Markus Metzger; +Cc: gdb-patches, Eli Zaretskii, Jan Kratochvil

On 09/17/2015 03:09 PM, Markus Metzger wrote:
> +  if (!non_stop && (scheduler_mode == schedlock_replay)

Unnecessary parens.

> +      && target_record_is_replaying (minus_one_ptid)
> +      && !target_record_will_replay (user_visible_resume_ptid (step),
> +				     execution_direction))
> +    target_record_stop_replaying ();


Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS
  2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
                   ` (18 preceding siblings ...)
  2015-09-17 14:10 ` [PATCH v3 19/19] btrace: honour scheduler-locking for all-stop targets Markus Metzger
@ 2015-09-18 11:41 ` Pedro Alves
  2015-09-18 11:52   ` Metzger, Markus T
  19 siblings, 1 reply; 27+ messages in thread
From: Pedro Alves @ 2015-09-18 11:41 UTC (permalink / raw)
  To: Markus Metzger; +Cc: gdb-patches

On 09/17/2015 03:09 PM, Markus Metzger wrote:

> The patch series can also be found on branch users/mmetzger/btrace-non-stop.

This looks good to me.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS
  2015-09-18 11:41 ` [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Pedro Alves
@ 2015-09-18 11:52   ` Metzger, Markus T
  2015-09-18 11:56     ` Jan Kratochvil
  2015-09-18 12:14     ` Eli Zaretskii
  0 siblings, 2 replies; 27+ messages in thread
From: Metzger, Markus T @ 2015-09-18 11:52 UTC (permalink / raw)
  To: Pedro Alves, Jan Kratochvil (jan.kratochvil@redhat.com),
	Eli Zaretskii (eliz@gnu.org)
  Cc: gdb-patches

> -----Original Message-----
> From: Pedro Alves [mailto:palves@redhat.com]
> Sent: Friday, September 18, 2015 1:41 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH v3 00/19] record btrace: non-stop, scheduler-locking,
> and ASNS
> 
> On 09/17/2015 03:09 PM, Markus Metzger wrote:
> 
> > The patch series can also be found on branch users/mmetzger/btrace-non-
> stop.
> 
> This looks good to me.

Thanks a lot for your review.  Jan, Eli, are you OK with the changes, as well?

Thanks,
Markus.

Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Prof. Dr. Hermann Eul
Chairperson of the Supervisory Board: Tiffany Doon Silva
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS
  2015-09-18 11:52   ` Metzger, Markus T
@ 2015-09-18 11:56     ` Jan Kratochvil
  2015-09-18 12:14     ` Eli Zaretskii
  1 sibling, 0 replies; 27+ messages in thread
From: Jan Kratochvil @ 2015-09-18 11:56 UTC (permalink / raw)
  To: Metzger, Markus T; +Cc: Pedro Alves, Eli Zaretskii (eliz@gnu.org), gdb-patches

On Fri, 18 Sep 2015 13:52:15 +0200, Metzger, Markus T wrote:
> > From: Pedro Alves [mailto:palves@redhat.com]
> > This looks good to me.
> 
> Thanks a lot for your review.  Jan, Eli, are you OK with the changes, as well?

Yes, thanks for the doc integration.


Jan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS
  2015-09-18 11:52   ` Metzger, Markus T
  2015-09-18 11:56     ` Jan Kratochvil
@ 2015-09-18 12:14     ` Eli Zaretskii
  1 sibling, 0 replies; 27+ messages in thread
From: Eli Zaretskii @ 2015-09-18 12:14 UTC (permalink / raw)
  To: Metzger, Markus T; +Cc: palves, jan.kratochvil, gdb-patches

> From: "Metzger, Markus T" <markus.t.metzger@intel.com>
> CC: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
> Date: Fri, 18 Sep 2015 11:52:15 +0000
> 
> Thanks a lot for your review.  Jan, Eli, are you OK with the changes, as well?

I didn't see any changes except those that I explicitly requested.  So
yes, OK.

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2015-09-18 12:14 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-17 14:10 [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Markus Metzger
2015-09-17 14:09 ` [PATCH v3 01/19] btrace: fix non-stop check in to_wait Markus Metzger
2015-09-17 14:10 ` [PATCH v3 08/19] btrace: lock-step Markus Metzger
2015-09-17 14:10 ` [PATCH v3 09/19] btrace: resume all requested threads Markus Metzger
2015-09-17 14:10 ` [PATCH v3 17/19] target: add to_record_will_replay target method Markus Metzger
2015-09-18 11:39   ` Pedro Alves
2015-09-17 14:10 ` [PATCH v3 06/19] btrace: move breakpoint checking into stepping functions Markus Metzger
2015-09-17 14:10 ` [PATCH v3 15/19] btrace: allow full memory and register access for non-replaying threads Markus Metzger
2015-09-17 14:10 ` [PATCH v3 14/19] target, record: add PTID argument to to_record_is_replaying Markus Metzger
2015-09-17 14:10 ` [PATCH v3 11/19] btrace: async Markus Metzger
2015-09-17 14:10 ` [PATCH v3 13/19] btrace: non-stop Markus Metzger
2015-09-17 14:10 ` [PATCH v3 10/19] btrace: temporarily set inferior_ptid in record_btrace_start_replaying Markus Metzger
2015-09-17 14:10 ` [PATCH v3 16/19] target: add to_record_stop_replaying target method Markus Metzger
2015-09-17 14:10 ` [PATCH v3 18/19] infrun: scheduler-locking replay Markus Metzger
2015-09-18 11:39   ` Pedro Alves
2015-09-17 14:10 ` [PATCH v3 05/19] btrace: split record_btrace_step_thread Markus Metzger
2015-09-17 14:10 ` [PATCH v3 02/19] btrace: support to_stop Markus Metzger
2015-09-17 14:10 ` [PATCH v3 12/19] infrun: switch to NO_HISTORY thread Markus Metzger
2015-09-17 14:10 ` [PATCH v3 07/19] btrace: add missing NO_HISTORY Markus Metzger
2015-09-17 14:10 ` [PATCH v3 04/19] btrace: extract the breakpoint check from record_btrace_step_thread Markus Metzger
2015-09-17 14:10 ` [PATCH v3 03/19] btrace: improve stepping debugging Markus Metzger
2015-09-17 14:10 ` [PATCH v3 19/19] btrace: honour scheduler-locking for all-stop targets Markus Metzger
2015-09-18 11:39   ` Pedro Alves
2015-09-18 11:41 ` [PATCH v3 00/19] record btrace: non-stop, scheduler-locking, and ASNS Pedro Alves
2015-09-18 11:52   ` Metzger, Markus T
2015-09-18 11:56     ` Jan Kratochvil
2015-09-18 12:14     ` Eli Zaretskii

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).