* [PATCH 04/17] btrace: extract the breakpoint check from record_btrace_step_thread
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (7 preceding siblings ...)
2015-09-09 10:35 ` [PATCH 03/17] btrace: improve stepping debugging Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 10:35 ` [PATCH 14/17] target, record: add PTID argument to to_record_is_replaying Markus Metzger
` (8 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 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-09 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] 45+ messages in thread
* [PATCH 01/17] btrace: fix non-stop check in to_wait
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (4 preceding siblings ...)
2015-09-09 10:35 ` [PATCH 11/17] btrace: async Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 10:35 ` [PATCH 15/17] btrace: allow full memory and register access for non-replaying threads Markus Metzger
` (11 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 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-09 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] 45+ messages in thread
* [PATCH 15/17] btrace: allow full memory and register access for non-replaying threads
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (5 preceding siblings ...)
2015-09-09 10:35 ` [PATCH 01/17] btrace: fix non-stop check in to_wait Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 11:57 ` Pedro Alves
2015-09-09 10:35 ` [PATCH 03/17] btrace: improve stepping debugging Markus Metzger
` (10 subsequent siblings)
17 siblings, 1 reply; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 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.
2015-09-09 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.
---
gdb/record-btrace.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 7e1df13..e5aabd0 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,7 +1314,7 @@ 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))
+ && record_btrace_is_replaying (ops, inferior_ptid))
error (_("This record target does not allow writing registers."));
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] 45+ messages in thread
* [PATCH 03/17] btrace: improve stepping debugging
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (6 preceding siblings ...)
2015-09-09 10:35 ` [PATCH 15/17] btrace: allow full memory and register access for non-replaying threads Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 10:35 ` [PATCH 04/17] btrace: extract the breakpoint check from record_btrace_step_thread Markus Metzger
` (9 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 UTC (permalink / raw)
To: palves; +Cc: gdb-patches
2015-09-09 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] 45+ messages in thread
* [PATCH 05/17] btrace: split record_btrace_step_thread
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (2 preceding siblings ...)
2015-09-09 10:35 ` [PATCH 12/17] infrun: switch to NO_HISTORY thread Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 10:35 ` [PATCH 11/17] btrace: async Markus Metzger
` (13 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 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-09 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] 45+ messages in thread
* [PATCH 12/17] infrun: switch to NO_HISTORY thread
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
2015-09-09 10:35 ` [PATCH 08/17] btrace: lock-step Markus Metzger
2015-09-09 10:35 ` [PATCH 10/17] btrace: temporarily set inferior_ptid in record_btrace_start_replaying Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 10:35 ` [PATCH 05/17] btrace: split record_btrace_step_thread Markus Metzger
` (14 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 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 stop-all 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-09 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 70dffca..6bf9fcb 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5042,8 +5042,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] 45+ messages in thread
* [PATCH 08/17] btrace: lock-step
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 10:35 ` [PATCH 10/17] btrace: temporarily set inferior_ptid in record_btrace_start_replaying Markus Metzger
` (16 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 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-09 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..0ce8825 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, stop-all on 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] 45+ messages in thread
* [PATCH 14/17] target, record: add PTID argument to to_record_is_replaying
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (8 preceding siblings ...)
2015-09-09 10:35 ` [PATCH 04/17] btrace: extract the breakpoint check from record_btrace_step_thread Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 10:36 ` [PATCH 07/17] btrace: add missing NO_HISTORY Markus Metzger
` (7 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 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-09 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 f3e6abe..7e1df13 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 ddcad94..ba6c4c6 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -3555,26 +3555,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 ea541aa..5f97a65 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3637,9 +3637,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 (¤t_target);
+ return current_target.to_record_is_replaying (¤t_target, ptid);
}
/* See target.h. */
diff --git a/gdb/target.h b/gdb/target.h
index 37e4edb..877075a 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1152,8 +1152,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. */
@@ -2424,7 +2424,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] 45+ messages in thread
* [PATCH 11/17] btrace: async
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (3 preceding siblings ...)
2015-09-09 10:35 ` [PATCH 05/17] btrace: split record_btrace_step_thread Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 10:35 ` [PATCH 01/17] btrace: fix non-stop check in to_wait Markus Metzger
` (12 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 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-09 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 a38faf3..119bf92 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] 45+ messages in thread
* [PATCH 10/17] btrace: temporarily set inferior_ptid in record_btrace_start_replaying
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
2015-09-09 10:35 ` [PATCH 08/17] btrace: lock-step Markus Metzger
@ 2015-09-09 10:35 ` Markus Metzger
2015-09-09 10:35 ` [PATCH 12/17] infrun: switch to NO_HISTORY thread Markus Metzger
` (15 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:35 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-09 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 64c8132..a38faf3 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] 45+ messages in thread
* [PATCH 02/17] btrace: support to_stop
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (15 preceding siblings ...)
2015-09-09 10:36 ` [PATCH 13/17] btrace: non-stop Markus Metzger
@ 2015-09-09 10:36 ` Markus Metzger
2015-09-09 13:56 ` [PATCH 00/17] record btrace: non-stop and ASNS Pedro Alves
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:36 UTC (permalink / raw)
To: palves; +Cc: gdb-patches
Add support for the to_stop target method to the btrace record target.
2015-09-09 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] 45+ messages in thread
* [PATCH 06/17] btrace: move breakpoint checking into stepping functions
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (10 preceding siblings ...)
2015-09-09 10:36 ` [PATCH 07/17] btrace: add missing NO_HISTORY Markus Metzger
@ 2015-09-09 10:36 ` Markus Metzger
2015-09-09 10:36 ` [PATCH 09/17] btrace: resume all requested threads Markus Metzger
` (5 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:36 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-09 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] 45+ messages in thread
* [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (12 preceding siblings ...)
2015-09-09 10:36 ` [PATCH 09/17] btrace: resume all requested threads Markus Metzger
@ 2015-09-09 10:36 ` Markus Metzger
2015-09-09 13:54 ` Pedro Alves
2015-09-09 10:36 ` [PATCH 16/17] target: add to_record_stop_replaying target method Markus Metzger
` (3 subsequent siblings)
17 siblings, 1 reply; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:36 UTC (permalink / raw)
To: palves; +Cc: gdb-patches
Record targets behave as if scheduler-locking were on during replay/reverse
execution. Add a new scheduler-locking option "reverse" to make this implicit
behaviour explicit. It behaves like "on" during reverse/replay execution and
like "off" during normal execution.
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 reverse 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.
2015-09-09 Markus Metzger <markus.t.metzger@intel.com>
gdb/
* NEWS: Announce new scheduler-locking mode.
* infrun.c (schedlock_reverse): New.
(scheduler_enums): Add schedlock_reverse.
(scheduler_mode): Change default to schedlock_reverse.
(user_visible_resume_ptid): Handle schedlock_reverse.
(clear_proceed_status_thread): Stop replaying if resumed thread is
not replaying.
(schedlock_applies): Handle schedlock_reverse.
(_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 | 4 ++++
gdb/doc/gdb.texinfo | 4 +++-
gdb/infrun.c | 35 ++++++++++++++++++++++++++++++-----
gdb/record-btrace.c | 10 ++--------
4 files changed, 39 insertions(+), 14 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index 1fa1862..896cdeb 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -45,6 +45,10 @@ 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 "reverse".
+ It behaves like "off" during normal execution and like "on" during
+ reverse or replay execution.
+
* 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 cd0abad..36a6777 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -5846,7 +5846,9 @@ 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 current thread away from the thread that you are debugging. The
+@code{reverse} mode behaves like @code{off} during normal execution
+and like @code{on} during reverse or replay execution.
@item show scheduler-locking
Display the current scheduler locking mode.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 6bf9fcb..7bf5a8f 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2158,13 +2158,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_reverse[] = "reverse";
static const char *const scheduler_enums[] = {
schedlock_off,
schedlock_on,
schedlock_step,
+ schedlock_reverse,
NULL
};
-static const char *scheduler_mode = schedlock_off;
+static const char *scheduler_mode = schedlock_reverse;
static void
show_scheduler_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@@ -2230,6 +2232,14 @@ user_visible_resume_ptid (int step)
resume. */
resume_ptid = inferior_ptid;
}
+ else if ((scheduler_mode == schedlock_reverse)
+ && ((execution_direction == EXEC_REVERSE)
+ || target_record_is_replaying (minus_one_ptid)))
+ {
+ /* User-settable 'scheduler' mode requires solo thread resume during
+ reverse/replay stepping. */
+ resume_ptid = inferior_ptid;
+ }
else if (!sched_multi && target_supports_multi_process ())
{
/* Resume all threads of the current process (and none of other
@@ -2765,6 +2775,18 @@ clear_proceed_status_thread (struct thread_info *tp)
void
clear_proceed_status (int step)
{
+ /* With scheduler-locking reverse, 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_reverse)
+ && (execution_direction != EXEC_REVERSE)
+ && target_record_is_replaying (minus_one_ptid)
+ && !target_record_is_replaying (user_visible_resume_ptid (step)))
+ target_record_stop_replaying ();
+
if (!non_stop)
{
struct thread_info *tp;
@@ -2852,7 +2874,9 @@ 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_reverse
+ && target_record_is_replaying (minus_one_ptid)));
}
/* Basic routine for continuing the program in various fashions.
@@ -9036,9 +9060,10 @@ 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\
+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\
+reverse == scheduler locked during reverse/replay execution.\n\
In this mode, other threads may run during other commands."),
set_schedlock_func, /* traps on target vector */
show_scheduler_mode,
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index c0e6c73..810baf1 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1895,22 +1895,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 non-stop targets... */
+ /* For non-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] 45+ messages in thread
* [PATCH 00/17] record btrace: non-stop and ASNS
@ 2015-09-09 10:36 Markus Metzger
2015-09-09 10:35 ` [PATCH 08/17] btrace: lock-step Markus Metzger
` (17 more replies)
0 siblings, 18 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:36 UTC (permalink / raw)
To: palves; +Cc: gdb-patches
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).
Markus Metzger (17):
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
infrun: scheduler-locking reverse
gdb/NEWS | 6 +
gdb/btrace.h | 5 +-
gdb/doc/gdb.texinfo | 4 +-
gdb/infrun.c | 43 +-
gdb/record-btrace.c | 721 ++++++++++++++++++++++++----------
gdb/record-full.c | 11 +-
gdb/record.c | 2 +-
gdb/target-delegates.c | 38 +-
gdb/target.c | 12 +-
gdb/target.h | 13 +-
gdb/testsuite/gdb.btrace/non-stop.c | 45 +++
gdb/testsuite/gdb.btrace/non-stop.exp | 264 +++++++++++++
12 files changed, 940 insertions(+), 224 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] 45+ messages in thread
* [PATCH 09/17] btrace: resume all requested threads
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (11 preceding siblings ...)
2015-09-09 10:36 ` [PATCH 06/17] btrace: move breakpoint checking into stepping functions Markus Metzger
@ 2015-09-09 10:36 ` Markus Metzger
2015-09-09 12:06 ` Pedro Alves
2015-09-09 10:36 ` [PATCH 17/17] infrun: scheduler-locking reverse Markus Metzger
` (4 subsequent siblings)
17 siblings, 1 reply; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:36 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-09 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 0ce8825..64c8132 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 non-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] 45+ messages in thread
* [PATCH 16/17] target: add to_record_stop_replaying target method
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (13 preceding siblings ...)
2015-09-09 10:36 ` [PATCH 17/17] infrun: scheduler-locking reverse Markus Metzger
@ 2015-09-09 10:36 ` Markus Metzger
2015-09-09 11:59 ` Pedro Alves
2015-09-09 10:36 ` [PATCH 13/17] btrace: non-stop Markus Metzger
` (2 subsequent siblings)
17 siblings, 1 reply; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:36 UTC (permalink / raw)
To: palves; +Cc: gdb-patches
Add a new target method to_record_stop_replaying to stop replaying.
2015-09-09 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 e5aabd0..c0e6c73 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 ba6c4c6..ed4ac21 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -3584,6 +3584,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;
@@ -4216,6 +4238,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)
@@ -4381,6 +4405,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;
@@ -4532,6 +4557,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 5f97a65..add6119 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -3645,6 +3645,14 @@ target_record_is_replaying (ptid_t ptid)
/* See target.h. */
void
+target_record_stop_replaying (void)
+{
+ return current_target.to_record_stop_replaying (¤t_target);
+}
+
+/* See target.h. */
+
+void
target_goto_record_begin (void)
{
current_target.to_goto_record_begin (¤t_target);
diff --git a/gdb/target.h b/gdb/target.h
index 877075a..d8ead97 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1156,6 +1156,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 ());
@@ -2426,6 +2430,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] 45+ messages in thread
* [PATCH 07/17] btrace: add missing NO_HISTORY
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (9 preceding siblings ...)
2015-09-09 10:35 ` [PATCH 14/17] target, record: add PTID argument to to_record_is_replaying Markus Metzger
@ 2015-09-09 10:36 ` Markus Metzger
2015-09-09 10:36 ` [PATCH 06/17] btrace: move breakpoint checking into stepping functions Markus Metzger
` (6 subsequent siblings)
17 siblings, 0 replies; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:36 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-09 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] 45+ messages in thread
* [PATCH 13/17] btrace: non-stop
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (14 preceding siblings ...)
2015-09-09 10:36 ` [PATCH 16/17] target: add to_record_stop_replaying target method Markus Metzger
@ 2015-09-09 10:36 ` Markus Metzger
2015-09-09 11:54 ` Pedro Alves
2015-09-09 10:36 ` [PATCH 02/17] btrace: support to_stop Markus Metzger
2015-09-09 13:56 ` [PATCH 00/17] record btrace: non-stop and ASNS Pedro Alves
17 siblings, 1 reply; 45+ messages in thread
From: Markus Metzger @ 2015-09-09 10:36 UTC (permalink / raw)
To: palves; +Cc: gdb-patches
Support non-stop mode in record btrace.
2015-09-09 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 | 264 ++++++++++++++++++++++++++++++++++
4 files changed, 311 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 0cf51e1..1fa1862 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 119bf92..f3e6abe 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..ee7d1b6
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/non-stop.exp
@@ -0,0 +1,264 @@
+# 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.
+#
+# this is quite fragile, mostly because the prompt appears somewhere in
+# the middle of the output.
+proc gdb_cont_to { threads cmd line nthreads } {
+ global gdb_prompt
+ set full_cmd "thread apply $threads $cmd"
+ set prompt_seen 0
+
+ send_gdb "$full_cmd\n"
+
+ for {set i 0} {$i < $nthreads} {incr i} {
+ set test "$full_cmd: thread $i"
+
+ # check for the prompt. it may be in front of one of the lines we
+ # try to match.
+ gdb_test_multiple "" "$test: check prompt" {
+ -notransfer -re "$gdb_prompt " {
+ set prompt_seen 1
+ }
+ }
+
+ # check for the line. and for a typical error.
+ gdb_test_multiple "" $test {
+ -re "Cannot execute this command \[^\\\r\\\n\]* is running\." {
+ fail $test
+ }
+ -re "$line\[^\\\r\\\n\]*\r\n" {
+ pass $test
+ }
+ }
+ }
+
+ # make sure we consume the prompt if we have not skipped it before.
+ if {$prompt_seen == 0} {
+ set test "$full_cmd: consume prompt"
+ gdb_test_multiple "" $test {
+ -re "$gdb_prompt " {
+ 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] 45+ messages in thread
* Re: [PATCH 13/17] btrace: non-stop
2015-09-09 10:36 ` [PATCH 13/17] btrace: non-stop Markus Metzger
@ 2015-09-09 11:54 ` Pedro Alves
2015-09-09 12:20 ` Metzger, Markus T
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2015-09-09 11:54 UTC (permalink / raw)
To: Markus Metzger; +Cc: gdb-patches
On 09/09/2015 11:35 AM, Markus Metzger wrote:
> +# make sure $line matches the full expected output per thread.
> +# and let's hope that GDB never mixes the output from different threads.
> +#
> +# this is quite fragile, mostly because the prompt appears somewhere in
> +# the middle of the output.
> +proc gdb_cont_to { threads cmd line nthreads } {
> + global gdb_prompt
> + set full_cmd "thread apply $threads $cmd"
> + set prompt_seen 0
> +
> + send_gdb "$full_cmd\n"
> +
> + for {set i 0} {$i < $nthreads} {incr i} {
> + set test "$full_cmd: thread $i"
> +
> + # check for the prompt. it may be in front of one of the lines we
> + # try to match.
> + gdb_test_multiple "" "$test: check prompt" {
> + -notransfer -re "$gdb_prompt " {
> + set prompt_seen 1
> + }
> + }
> +
Hmmm. I'm not sure I'm missing some subtlety, but it seems to me
that if you used -notransfer, then the prompt will still be in the buffer,
and ...
> + # check for the line. and for a typical error.
> + gdb_test_multiple "" $test {
> + -re "Cannot execute this command \[^\\\r\\\n\]* is running\." {
> + fail $test
> + }
> + -re "$line\[^\\\r\\\n\]*\r\n" {
> + pass $test
> + }
> + }
... thus this gdb_test_multiple can trip on it and issue a fail.
Wouldn't this instead work?
gdb_test_multiple "" $test {
-re "Cannot execute this command \[^\\\r\\\n\]* is running\." {
fail $test
}
-re "$line\[^\\\r\\\n\]*\r\n" {
pass $test
}
-re "$gdb_prompt " {
set prompt_seen 1
exp_continue
}
}
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 15/17] btrace: allow full memory and register access for non-replaying threads
2015-09-09 10:35 ` [PATCH 15/17] btrace: allow full memory and register access for non-replaying threads Markus Metzger
@ 2015-09-09 11:57 ` Pedro Alves
0 siblings, 0 replies; 45+ messages in thread
From: Pedro Alves @ 2015-09-09 11:57 UTC (permalink / raw)
To: Markus Metzger; +Cc: gdb-patches
On 09/09/2015 11:35 AM, Markus Metzger wrote:
> @@ -1314,7 +1314,7 @@ 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))
> + && record_btrace_is_replaying (ops, inferior_ptid))
> error (_("This record target does not allow writing registers."));
>
I'd suggest also tweaking the error string.
"Cannot write registers of thread that is replaying" or some such.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 16/17] target: add to_record_stop_replaying target method
2015-09-09 10:36 ` [PATCH 16/17] target: add to_record_stop_replaying target method Markus Metzger
@ 2015-09-09 11:59 ` Pedro Alves
0 siblings, 0 replies; 45+ messages in thread
From: Pedro Alves @ 2015-09-09 11:59 UTC (permalink / raw)
To: Markus Metzger; +Cc: gdb-patches
On 09/09/2015 11:35 AM, Markus Metzger wrote:
> --- a/gdb/target.c
> +++ b/gdb/target.c
> @@ -3645,6 +3645,14 @@ target_record_is_replaying (ptid_t ptid)
> /* See target.h. */
>
> void
> +target_record_stop_replaying (void)
> +{
> + return current_target.to_record_stop_replaying (¤t_target);
> +}
Unnecessary "return". (I think some compilers complain.)
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 09/17] btrace: resume all requested threads
2015-09-09 10:36 ` [PATCH 09/17] btrace: resume all requested threads Markus Metzger
@ 2015-09-09 12:06 ` Pedro Alves
2015-09-09 13:06 ` Metzger, Markus T
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2015-09-09 12:06 UTC (permalink / raw)
To: Markus Metzger; +Cc: gdb-patches
On 09/09/2015 11:35 AM, Markus Metzger wrote:
> + /* For non-stop targets... */
ITYM "for all-stop". Might be worth an audit for other
all-stop / non-stop flips. I think I saw a "stop-all" typo
somewhere else in the series, but I can't find it right now...
> + if (!target_is_non_stop_p ())
> + {
> + /* ...we pick the current thread when asked to resume an entire process
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 13/17] btrace: non-stop
2015-09-09 11:54 ` Pedro Alves
@ 2015-09-09 12:20 ` Metzger, Markus T
2015-09-09 13:47 ` Pedro Alves
0 siblings, 1 reply; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-09 12:20 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> -----Original Message-----
> From: Pedro Alves [mailto:palves@redhat.com]
> Sent: Wednesday, September 9, 2015 1:54 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH 13/17] btrace: non-stop
>
> On 09/09/2015 11:35 AM, Markus Metzger wrote:
>
> > +# make sure $line matches the full expected output per thread.
> > +# and let's hope that GDB never mixes the output from different threads.
> > +#
> > +# this is quite fragile, mostly because the prompt appears somewhere in
> > +# the middle of the output.
> > +proc gdb_cont_to { threads cmd line nthreads } {
> > + global gdb_prompt
> > + set full_cmd "thread apply $threads $cmd"
> > + set prompt_seen 0
> > +
> > + send_gdb "$full_cmd\n"
> > +
> > + for {set i 0} {$i < $nthreads} {incr i} {
> > + set test "$full_cmd: thread $i"
> > +
> > + # check for the prompt. it may be in front of one of the lines we
> > + # try to match.
> > + gdb_test_multiple "" "$test: check prompt" {
> > + -notransfer -re "$gdb_prompt " {
> > + set prompt_seen 1
> > + }
> > + }
> > +
>
> Hmmm. I'm not sure I'm missing some subtlety, but it seems to me
> that if you used -notransfer, then the prompt will still be in the buffer,
> and ...
>
> > + # check for the line. and for a typical error.
> > + gdb_test_multiple "" $test {
> > + -re "Cannot execute this command \[^\\\r\\\n\]* is running\." {
> > + fail $test
> > + }
> > + -re "$line\[^\\\r\\\n\]*\r\n" {
> > + pass $test
> > + }
> > + }
>
> ... thus this gdb_test_multiple can trip on it and issue a fail.
As far as I understand expect, the above gdb_test_multiple would
simply skip the $gdb_prompt at the beginning of the line.
That's why I'm trying to detect it with a separate gdb_test_multiple
above. I use -notransfer so I can still analyse the line for the expected
output.
> Wouldn't this instead work?
>
> gdb_test_multiple "" $test {
> -re "Cannot execute this command \[^\\\r\\\n\]* is running\." {
> fail $test
> }
> -re "$line\[^\\\r\\\n\]*\r\n" {
> pass $test
> }
> -re "$gdb_prompt " {
> set prompt_seen 1
> exp_continue
> }
> }
Wouldn't the 1st or 2nd pattern skip any $gdb_prompt before the pattern?
For the "Cannot execute..." pattern, I could add "^" but this will be difficult
for the $line pattern.
Does the 3rd pattern consume just the $gdb_prompt or the entire line?
This non-stop testing is quite difficult. I also have not found too many
examples when I searched for "non-stop".
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] 45+ messages in thread
* RE: [PATCH 09/17] btrace: resume all requested threads
2015-09-09 12:06 ` Pedro Alves
@ 2015-09-09 13:06 ` Metzger, Markus T
0 siblings, 0 replies; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-09 13:06 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> -----Original Message-----
> From: Pedro Alves [mailto:palves@redhat.com]
> Sent: Wednesday, September 9, 2015 2:06 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH 09/17] btrace: resume all requested threads
>
> On 09/09/2015 11:35 AM, Markus Metzger wrote:
> > + /* For non-stop targets... */
>
> ITYM "for all-stop". Might be worth an audit for other
> all-stop / non-stop flips. I think I saw a "stop-all" typo
> somewhere else in the series, but I can't find it right now...
Found it. There was one in a commit message and one in
another comment.
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] 45+ messages in thread
* Re: [PATCH 13/17] btrace: non-stop
2015-09-09 12:20 ` Metzger, Markus T
@ 2015-09-09 13:47 ` Pedro Alves
2015-09-09 14:10 ` Metzger, Markus T
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2015-09-09 13:47 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: gdb-patches
On 09/09/2015 01:20 PM, Metzger, Markus T wrote:
>> -----Original Message-----
>> From: Pedro Alves [mailto:palves@redhat.com]
>> Sent: Wednesday, September 9, 2015 1:54 PM
>> To: Metzger, Markus T
>> Cc: gdb-patches@sourceware.org
>> Subject: Re: [PATCH 13/17] btrace: non-stop
>>
>> On 09/09/2015 11:35 AM, Markus Metzger wrote:
>>
>>> +# make sure $line matches the full expected output per thread.
>>> +# and let's hope that GDB never mixes the output from different threads.
>>> +#
>>> +# this is quite fragile, mostly because the prompt appears somewhere in
>>> +# the middle of the output.
>>> +proc gdb_cont_to { threads cmd line nthreads } {
>>> + global gdb_prompt
>>> + set full_cmd "thread apply $threads $cmd"
>>> + set prompt_seen 0
>>> +
>>> + send_gdb "$full_cmd\n"
>>> +
>>> + for {set i 0} {$i < $nthreads} {incr i} {
>>> + set test "$full_cmd: thread $i"
>>> +
>>> + # check for the prompt. it may be in front of one of the lines we
>>> + # try to match.
>>> + gdb_test_multiple "" "$test: check prompt" {
>>> + -notransfer -re "$gdb_prompt " {
>>> + set prompt_seen 1
>>> + }
>>> + }
>>> +
>>
>> Hmmm. I'm not sure I'm missing some subtlety, but it seems to me
>> that if you used -notransfer, then the prompt will still be in the buffer,
>> and ...
>>
>>> + # check for the line. and for a typical error.
>>> + gdb_test_multiple "" $test {
>>> + -re "Cannot execute this command \[^\\\r\\\n\]* is running\." {
>>> + fail $test
>>> + }
>>> + -re "$line\[^\\\r\\\n\]*\r\n" {
>>> + pass $test
>>> + }
>>> + }
>>
>> ... thus this gdb_test_multiple can trip on it and issue a fail.
>
> As far as I understand expect, the above gdb_test_multiple would
> simply skip the $gdb_prompt at the beginning of the line.
Only if the buffer already holds enough data for the regex to match.
Expect reads data in chunks and puts it in the buffer, and then tries
a match. If nothing matches, it fetches more data, and retries matching.
On an on, until a timeout. So say $line is
[multi_line \
"No more reverse-execution history\." \
"\[^\\\r\\\n\]*" \
"\[^\\\r\\\n\]*" \
]
It sometimes will happen that the expect buffer has:
"$gdb_prompt\r\n...No more reverse-exe"
Because that doesn't match any of the regexs you have, gdb_test_multiple's
internal regex for the prompt matches, and issues a FAIL.
Try "make check-read1". It may well be it catches this.
>
> That's why I'm trying to detect it with a separate gdb_test_multiple
> above. I use -notransfer so I can still analyse the line for the expected
> output.
>
>
>> Wouldn't this instead work?
>>
>> gdb_test_multiple "" $test {
>> -re "Cannot execute this command \[^\\\r\\\n\]* is running\." {
>> fail $test
>> }
>> -re "$line\[^\\\r\\\n\]*\r\n" {
>> pass $test
>> }
>> -re "$gdb_prompt " {
>> set prompt_seen 1
>> exp_continue
>> }
>> }
>
> Wouldn't the 1st or 2nd pattern skip any $gdb_prompt before the pattern?
Yes. Is that a problem? Don't we always get another prompt after that error?
> For the "Cannot execute..." pattern, I could add "^" but this will be difficult
> for the $line pattern.
>
> Does the 3rd pattern consume just the $gdb_prompt or the entire line?
Consumes everything up to the prompt. Whatever follows is left in the buffer.
> This non-stop testing is quite difficult. I also have not found too many
> examples when I searched for "non-stop".
Could you push the series to a branch somewhere? The easiest would be
a users/ branch in the master repo.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-09 10:36 ` [PATCH 17/17] infrun: scheduler-locking reverse Markus Metzger
@ 2015-09-09 13:54 ` Pedro Alves
2015-09-12 19:43 ` Jan Kratochvil
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2015-09-09 13:54 UTC (permalink / raw)
To: Markus Metzger; +Cc: gdb-patches
On 09/09/2015 11:35 AM, Markus Metzger wrote:
> Record targets behave as if scheduler-locking were on during replay/reverse
> execution. Add a new scheduler-locking option "reverse" to make this implicit
> behaviour explicit. It behaves like "on" during reverse/replay execution and
> like "off" during normal execution.
>
> 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.
Hmm. The code looks fine. But I should point out that if a user
has "schedlock step" in their gdbinit, they'll miss this. Fedora's gdb
actually currently defaults to schedlock=step.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 00/17] record btrace: non-stop and ASNS
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
` (16 preceding siblings ...)
2015-09-09 10:36 ` [PATCH 02/17] btrace: support to_stop Markus Metzger
@ 2015-09-09 13:56 ` Pedro Alves
17 siblings, 0 replies; 45+ messages in thread
From: Pedro Alves @ 2015-09-09 13:56 UTC (permalink / raw)
To: Markus Metzger; +Cc: gdb-patches
On 09/09/2015 11:34 AM, Markus Metzger wrote:
> 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).
Thank you very much for all this! I sent a couple comments in specific
patches, but it all looks pretty good to me.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 13/17] btrace: non-stop
2015-09-09 13:47 ` Pedro Alves
@ 2015-09-09 14:10 ` Metzger, Markus T
2015-09-09 14:51 ` Pedro Alves
0 siblings, 1 reply; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-09 14:10 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> -----Original Message-----
> From: Pedro Alves [mailto:palves@redhat.com]
> Sent: Wednesday, September 9, 2015 3:47 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH 13/17] btrace: non-stop
>
> On 09/09/2015 01:20 PM, Metzger, Markus T wrote:
> >> -----Original Message-----
> >> From: Pedro Alves [mailto:palves@redhat.com]
> >> Sent: Wednesday, September 9, 2015 1:54 PM
> >> To: Metzger, Markus T
> >> Cc: gdb-patches@sourceware.org
> >> Subject: Re: [PATCH 13/17] btrace: non-stop
> >>
> >> On 09/09/2015 11:35 AM, Markus Metzger wrote:
> >>
> >>> +# make sure $line matches the full expected output per thread.
> >>> +# and let's hope that GDB never mixes the output from different
> threads.
> >>> +#
> >>> +# this is quite fragile, mostly because the prompt appears somewhere
> in
> >>> +# the middle of the output.
> >>> +proc gdb_cont_to { threads cmd line nthreads } {
> >>> + global gdb_prompt
> >>> + set full_cmd "thread apply $threads $cmd"
> >>> + set prompt_seen 0
> >>> +
> >>> + send_gdb "$full_cmd\n"
> >>> +
> >>> + for {set i 0} {$i < $nthreads} {incr i} {
> >>> + set test "$full_cmd: thread $i"
> >>> +
> >>> + # check for the prompt. it may be in front of one of the lines we
> >>> + # try to match.
> >>> + gdb_test_multiple "" "$test: check prompt" {
> >>> + -notransfer -re "$gdb_prompt " {
> >>> + set prompt_seen 1
> >>> + }
> >>> + }
> >>> +
> >>
> >> Hmmm. I'm not sure I'm missing some subtlety, but it seems to me
> >> that if you used -notransfer, then the prompt will still be in the buffer,
> >> and ...
> >>
> >>> + # check for the line. and for a typical error.
> >>> + gdb_test_multiple "" $test {
> >>> + -re "Cannot execute this command \[^\\\r\\\n\]* is running\." {
> >>> + fail $test
> >>> + }
> >>> + -re "$line\[^\\\r\\\n\]*\r\n" {
> >>> + pass $test
> >>> + }
> >>> + }
> >>
> >> ... thus this gdb_test_multiple can trip on it and issue a fail.
> >
> > As far as I understand expect, the above gdb_test_multiple would
> > simply skip the $gdb_prompt at the beginning of the line.
>
> Only if the buffer already holds enough data for the regex to match.
> Expect reads data in chunks and puts it in the buffer, and then tries
> a match. If nothing matches, it fetches more data, and retries matching.
> On an on, until a timeout. So say $line is
>
> [multi_line \
> "No more reverse-execution history\." \
> "\[^\\\r\\\n\]*" \
> "\[^\\\r\\\n\]*" \
> ]
>
> It sometimes will happen that the expect buffer has:
>
> "$gdb_prompt\r\n...No more reverse-exe"
>
> Because that doesn't match any of the regexs you have, gdb_test_multiple's
> internal regex for the prompt matches, and issues a FAIL.
> Try "make check-read1". It may well be it catches this.
It doesn't; "make check-read1" runs without fails. With my version as well
as with your version. Both also catch errors if I revert one of the patches.
Btw, the output is not "$gdb_prompt\r\n...No more reverse-exe"
but "$gdb_prompt No more reverse-exe". The $gdb_prompt simply
precedes some other output.
> > That's why I'm trying to detect it with a separate gdb_test_multiple
> > above. I use -notransfer so I can still analyse the line for the expected
> > output.
> >
> >
> >> Wouldn't this instead work?
> >>
> >> gdb_test_multiple "" $test {
> >> -re "Cannot execute this command \[^\\\r\\\n\]* is running\." {
> >> fail $test
> >> }
> >> -re "$line\[^\\\r\\\n\]*\r\n" {
> >> pass $test
> >> }
> >> -re "$gdb_prompt " {
> >> set prompt_seen 1
> >> exp_continue
> >> }
> >> }
> >
> > Wouldn't the 1st or 2nd pattern skip any $gdb_prompt before the pattern?
>
> Yes. Is that a problem? Don't we always get another prompt after that
> error?
No, we don't. We have a single prompt that appears somewhere in the output.
(gdb) thread apply all continue
Thread 1 (Thread 0x7ffff7fcc740 (LWP 22139)):
Continuing.
[New Thread 0x7ffff74fb700 (LWP 22143)]
Breakpoint 2, test (arg=0x0) at gdb.btrace/non-stop.c:27
27 i = 0; /* bp.1 */
PASS: gdb.btrace/non-stop.exp: thread apply all continue: thread 0
(gdb)
Breakpoint 2, test (arg=0x0) at gdb.btrace/non-stop.c:27
27 i = 0; /* bp.1 */
PASS: gdb.btrace/non-stop.exp: thread apply all continue: thread 1
record btrace
Sometimes, the prompt appears on the same line as some other output.
So far, I have only seen it at the beginning of a line.
That's what makes it so difficult. The test needs to read past the prompt.
> > For the "Cannot execute..." pattern, I could add "^" but this will be difficult
> > for the $line pattern.
> >
> > Does the 3rd pattern consume just the $gdb_prompt or the entire line?
>
> Consumes everything up to the prompt. Whatever follows is left in the
> buffer.
Then putting the 3rd line first should work.
> > This non-stop testing is quite difficult. I also have not found too many
> > examples when I searched for "non-stop".
>
> Could you push the series to a branch somewhere? The easiest would be
> a users/ branch in the master repo.
OK. This is temporary. I have not followed the discussion. Can I force-push
and remove such a user branch?
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] 45+ messages in thread
* Re: [PATCH 13/17] btrace: non-stop
2015-09-09 14:10 ` Metzger, Markus T
@ 2015-09-09 14:51 ` Pedro Alves
2015-09-10 7:49 ` Metzger, Markus T
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2015-09-09 14:51 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: gdb-patches
On 09/09/2015 03:08 PM, Metzger, Markus T wrote:
>>>
>>> Wouldn't the 1st or 2nd pattern skip any $gdb_prompt before the pattern?
>>
>> Yes. Is that a problem? Don't we always get another prompt after that
>> error?
>
> No, we don't. We have a single prompt that appears somewhere in the output.
>
> (gdb) thread apply all continue
That seems to be root of the problem. That'll do a synchronous
continue on each thread, one by one. I think that what you want
is instead:
(gdb) thread apply all continue&
And that way you get a single prompt before any breakpoint is hit.
> OK. This is temporary. I have not followed the discussion. Can I force-push
> and remove such a user branch?
I don't think you can force-push today, but you can delete branches, so the
usual workaround of doing delete+push to emulate force-push works fine.
(Myself, I only use the user branches in the master repo to hand off series for
review and testing convenience, and do development / backup elsewhere.)
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 13/17] btrace: non-stop
2015-09-09 14:51 ` Pedro Alves
@ 2015-09-10 7:49 ` Metzger, Markus T
2015-09-10 11:05 ` Pedro Alves
0 siblings, 1 reply; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-10 7:49 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] On Behalf Of Pedro Alves
> Sent: Wednesday, September 9, 2015 4:51 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH 13/17] btrace: non-stop
>
> On 09/09/2015 03:08 PM, Metzger, Markus T wrote:
>
> >>>
> >>> Wouldn't the 1st or 2nd pattern skip any $gdb_prompt before the
> pattern?
> >>
> >> Yes. Is that a problem? Don't we always get another prompt after that
> >> error?
> >
> > No, we don't. We have a single prompt that appears somewhere in the
> output.
> >
> > (gdb) thread apply all continue
>
> That seems to be root of the problem. That'll do a synchronous
> continue on each thread, one by one. I think that what you want
> is instead:
>
> (gdb) thread apply all continue&
>
> And that way you get a single prompt before any breakpoint is hit.
That seems to be the case. I'm still getting the error I'm checking for before
the prompt, though, and my test will run into a timeout.
thread apply all reverse-stepi 4 &
Thread 2 (Thread 0x7ffff74fb700 (LWP 70895)):
Thread 1 (Thread 0x7ffff7fcc740 (LWP 70891)):
Cannot execute this command while the selected thread is running.
(gdb) PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all reverse-stepi 4: prompt
0x0000000000400671 28 for (; i < 10; ++i) global += i; /* loop */
PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all reverse-stepi 4: thread 0
FAIL: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all reverse-stepi 4: thread 1 (timeout)
A failing run might take a bit longer, but that should be it.
I changed the test, removed the "Cannot execute ..." check, and pushed the
series into users/mmetzger/btrace-non-stop.
Regards,
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] 45+ messages in thread
* Re: [PATCH 13/17] btrace: non-stop
2015-09-10 7:49 ` Metzger, Markus T
@ 2015-09-10 11:05 ` Pedro Alves
2015-09-10 11:19 ` Metzger, Markus T
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2015-09-10 11:05 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: gdb-patches
On 09/10/2015 08:47 AM, Metzger, Markus T wrote:
> That seems to be the case. I'm still getting the error I'm checking for before
> the prompt, though, and my test will run into a timeout.
>
> thread apply all reverse-stepi 4 &
>
> Thread 2 (Thread 0x7ffff74fb700 (LWP 70895)):
>
> Thread 1 (Thread 0x7ffff7fcc740 (LWP 70891)):
> Cannot execute this command while the selected thread is running.
> (gdb) PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all reverse-stepi 4: prompt
> 0x0000000000400671 28 for (; i < 10; ++i) global += i; /* loop */
> PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all reverse-stepi 4: thread 0
> FAIL: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all reverse-stepi 4: thread 1 (timeout)
>
> A failing run might take a bit longer, but that should be it.
Odd. I'm running the test now for over 20 minutes, and it doesn't ever fail.
Before I ran it against gdbserver for 10 minutes, never failed.
This is with an i7-2620M; I hacked linux-btrace.c:intel_supports_bts to
enable btrace.
If you put an "info threads" just before that reverse-stepi, does it
show thread 1 as "(running)"? I wonder if the problem happened
sooner / above in the log, and you're seeing a consequence.
A "set debug infrun 1" log will likely help.
>
> I changed the test, removed the "Cannot execute ..." check, and pushed the
> series into users/mmetzger/btrace-non-stop.
This looks good to me. The comments above gdb_cont_to are stale though.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 13/17] btrace: non-stop
2015-09-10 11:05 ` Pedro Alves
@ 2015-09-10 11:19 ` Metzger, Markus T
2015-09-10 11:32 ` Pedro Alves
0 siblings, 1 reply; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-10 11:19 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> -----Original Message-----
> From: Pedro Alves [mailto:palves@redhat.com]
> Sent: Thursday, September 10, 2015 1:05 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH 13/17] btrace: non-stop
>
> On 09/10/2015 08:47 AM, Metzger, Markus T wrote:
>
> > That seems to be the case. I'm still getting the error I'm checking for before
> > the prompt, though, and my test will run into a timeout.
> >
> > thread apply all reverse-stepi 4 &
> >
> > Thread 2 (Thread 0x7ffff74fb700 (LWP 70895)):
> >
> > Thread 1 (Thread 0x7ffff7fcc740 (LWP 70891)):
> > Cannot execute this command while the selected thread is running.
> > (gdb) PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply
> all reverse-stepi 4: prompt
> > 0x0000000000400671 28 for (; i < 10; ++i) global += i; /* loop */
> > PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all
> reverse-stepi 4: thread 0
> > FAIL: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all
> reverse-stepi 4: thread 1 (timeout)
> >
> > A failing run might take a bit longer, but that should be it.
>
> Odd. I'm running the test now for over 20 minutes, and it doesn't ever fail.
> Before I ran it against gdbserver for 10 minutes, never failed.
> This is with an i7-2620M; I hacked linux-btrace.c:intel_supports_bts to
> enable btrace.
I reverted one of the patches to trigger the error. I wanted to see if
the test catches it. The full series should run without error, of course.
This was meant to demonstrate that the error message precedes the
prompt.
> This looks good to me. The comments above gdb_cont_to are stale though.
Thanks. Will update.
Regards,
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] 45+ messages in thread
* Re: [PATCH 13/17] btrace: non-stop
2015-09-10 11:19 ` Metzger, Markus T
@ 2015-09-10 11:32 ` Pedro Alves
2015-09-10 11:37 ` Metzger, Markus T
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2015-09-10 11:32 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: gdb-patches
On 09/10/2015 12:19 PM, Metzger, Markus T wrote:
>> -----Original Message-----
>> From: Pedro Alves [mailto:palves@redhat.com]
>> Sent: Thursday, September 10, 2015 1:05 PM
>> To: Metzger, Markus T
>> Cc: gdb-patches@sourceware.org
>> Subject: Re: [PATCH 13/17] btrace: non-stop
>>
>> On 09/10/2015 08:47 AM, Metzger, Markus T wrote:
>>
>>> That seems to be the case. I'm still getting the error I'm checking for before
>>> the prompt, though, and my test will run into a timeout.
>>>
>>> thread apply all reverse-stepi 4 &
>>>
>>> Thread 2 (Thread 0x7ffff74fb700 (LWP 70895)):
>>>
>>> Thread 1 (Thread 0x7ffff7fcc740 (LWP 70891)):
>>> Cannot execute this command while the selected thread is running.
>>> (gdb) PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply
>> all reverse-stepi 4: prompt
>>> 0x0000000000400671 28 for (; i < 10; ++i) global += i; /* loop */
>>> PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all
>> reverse-stepi 4: thread 0
>>> FAIL: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all
>> reverse-stepi 4: thread 1 (timeout)
>>>
>>> A failing run might take a bit longer, but that should be it.
>>
>> Odd. I'm running the test now for over 20 minutes, and it doesn't ever fail.
>> Before I ran it against gdbserver for 10 minutes, never failed.
>> This is with an i7-2620M; I hacked linux-btrace.c:intel_supports_bts to
>> enable btrace.
>
> I reverted one of the patches to trigger the error. I wanted to see if
> the test catches it. The full series should run without error, of course.
>
> This was meant to demonstrate that the error message precedes the
> prompt.
Ah, I had totally misunderstood it! I thought you were saying that a
failing run took a bit long to trigger, so I left it running for a
while. In fact, I still had it running. :-)
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 13/17] btrace: non-stop
2015-09-10 11:32 ` Pedro Alves
@ 2015-09-10 11:37 ` Metzger, Markus T
2015-09-10 12:48 ` Pedro Alves
0 siblings, 1 reply; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-10 11:37 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> -----Original Message-----
> From: Pedro Alves [mailto:palves@redhat.com]
> Sent: Thursday, September 10, 2015 1:33 PM
> To: Metzger, Markus T
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH 13/17] btrace: non-stop
>
> On 09/10/2015 12:19 PM, Metzger, Markus T wrote:
> >> -----Original Message-----
> >> From: Pedro Alves [mailto:palves@redhat.com]
> >> Sent: Thursday, September 10, 2015 1:05 PM
> >> To: Metzger, Markus T
> >> Cc: gdb-patches@sourceware.org
> >> Subject: Re: [PATCH 13/17] btrace: non-stop
> >>
> >> On 09/10/2015 08:47 AM, Metzger, Markus T wrote:
> >>
> >>> That seems to be the case. I'm still getting the error I'm checking for
> before
> >>> the prompt, though, and my test will run into a timeout.
> >>>
> >>> thread apply all reverse-stepi 4 &
> >>>
> >>> Thread 2 (Thread 0x7ffff74fb700 (LWP 70895)):
> >>>
> >>> Thread 1 (Thread 0x7ffff7fcc740 (LWP 70891)):
> >>> Cannot execute this command while the selected thread is running.
> >>> (gdb) PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply
> >> all reverse-stepi 4: prompt
> >>> 0x0000000000400671 28 for (; i < 10; ++i) global += i; /* loop */
> >>> PASS: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all
> >> reverse-stepi 4: thread 0
> >>> FAIL: gdb.btrace/non-stop.exp: reverse-step: all: thread apply all
> >> reverse-stepi 4: thread 1 (timeout)
> >>>
> >>> A failing run might take a bit longer, but that should be it.
> >>
> >> Odd. I'm running the test now for over 20 minutes, and it doesn't ever
> fail.
> >> Before I ran it against gdbserver for 10 minutes, never failed.
> >> This is with an i7-2620M; I hacked linux-btrace.c:intel_supports_bts to
> >> enable btrace.
> >
> > I reverted one of the patches to trigger the error. I wanted to see if
> > the test catches it. The full series should run without error, of course.
> >
> > This was meant to demonstrate that the error message precedes the
> > prompt.
>
> Ah, I had totally misunderstood it! I thought you were saying that a
> failing run took a bit long to trigger, so I left it running for a
> while. In fact, I still had it running. :-)
I meant that when a test fails, we are now waiting for the timeout.
Before, we caught the error message. So running the test might take
longer if there are fails.
I forgot to mention that you need to revert one of the preceding
patches to trigger a fail;-)
Regards,
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] 45+ messages in thread
* Re: [PATCH 13/17] btrace: non-stop
2015-09-10 11:37 ` Metzger, Markus T
@ 2015-09-10 12:48 ` Pedro Alves
0 siblings, 0 replies; 45+ messages in thread
From: Pedro Alves @ 2015-09-10 12:48 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: gdb-patches
On 09/10/2015 12:37 PM, Metzger, Markus T wrote:
>> Ah, I had totally misunderstood it! I thought you were saying that a
>> failing run took a bit long to trigger, so I left it running for a
>> while. In fact, I still had it running. :-)
>
> I meant that when a test fails, we are now waiting for the timeout.
> Before, we caught the error message. So running the test might take
> longer if there are fails.
Gotcha. I suggest only worrying about timeouts if/when we regress
at some point and decide that we need to xfail/kfail then.
>
> I forgot to mention that you need to revert one of the preceding
> patches to trigger a fail;-)
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-09 13:54 ` Pedro Alves
@ 2015-09-12 19:43 ` Jan Kratochvil
2015-09-15 9:29 ` Metzger, Markus T
0 siblings, 1 reply; 45+ messages in thread
From: Jan Kratochvil @ 2015-09-12 19:43 UTC (permalink / raw)
To: Pedro Alves; +Cc: Markus Metzger, gdb-patches
On Wed, 09 Sep 2015 15:54:26 +0200, Pedro Alves wrote:
> On 09/09/2015 11:35 AM, Markus Metzger wrote:
> > Record targets behave as if scheduler-locking were on during replay/reverse
> > execution. Add a new scheduler-locking option "reverse" to make this implicit
> > behaviour explicit. It behaves like "on" during reverse/replay execution and
> > like "off" during normal execution.
> >
> > 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.
>
> Hmm. The code looks fine. But I should point out that if a user
> has "schedlock step" in their gdbinit, they'll miss this. Fedora's gdb
> actually currently defaults to schedlock=step.
Thanks for bringing it up. I would have hard time mergin this patch's:
-static const char *scheduler_mode = schedlock_off;
+static const char *scheduler_mode = schedlock_reverse;
with
http://pkgs.fedoraproject.org/cgit/gdb.git/tree/gdb-6.6-scheduler_locking-step-is-default.patch
-static const char *scheduler_mode = schedlock_off;
+static const char *scheduler_mode = schedlock_step;
My guess is there could be a new setting "set reverse-scheduler-locking" also
with "off/step/on" as it seems to me "step" also makes sense for the scheduler
locking in reverse mode.
Or better "set reverse-scheduler-locking" with "off/on" where "on" would
behave for reverse mode as "step" if "set scheduler-locking" is set to "step".
I do not mind which way but I do not find the current user interface great.
Thanks,
Jan
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-12 19:43 ` Jan Kratochvil
@ 2015-09-15 9:29 ` Metzger, Markus T
2015-09-15 17:19 ` Jan Kratochvil
0 siblings, 1 reply; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-15 9:29 UTC (permalink / raw)
To: Jan Kratochvil, Pedro Alves; +Cc: gdb-patches
> -----Original Message-----
> From: Jan Kratochvil [mailto:jan.kratochvil@redhat.com]
> Sent: Saturday, September 12, 2015 9:44 PM
> To: Pedro Alves
> Cc: Metzger, Markus T; gdb-patches@sourceware.org
> Subject: Re: [PATCH 17/17] infrun: scheduler-locking reverse
Hello Jan,
> Thanks for bringing it up. I would have hard time mergin this patch's:
> -static const char *scheduler_mode = schedlock_off;
> +static const char *scheduler_mode = schedlock_reverse;
> with
> http://pkgs.fedoraproject.org/cgit/gdb.git/tree/gdb-6.6-scheduler_locking-
> step-is-default.patch
> -static const char *scheduler_mode = schedlock_off;
> +static const char *scheduler_mode = schedlock_step;
I don't believe that we need to preserve the current behaviour. If Fedora
defaults to schedlock_step, why not also for record targets?
It could be seen as bug-fix that record targets did not honour scheduler-locking.
The same holds for mainline, of course. But the new mode is much closer to
schedlock_step than it is to schedlock_off.
> My guess is there could be a new setting "set reverse-scheduler-locking" also
> with "off/step/on" as it seems to me "step" also makes sense for the
> scheduler
> locking in reverse mode.
This would allow us to set different scheduler-locking modes for reverse/replay
execution and for normal debugging. While this adds flexibility, I'm not sure it is
actually needed.
I really only added the new mode because I did not want to change the default
behaviour completely. Over time, I think we may want to deprecate it, even
though schedlock_off isn't very useful with the usually quite short execution
history. Maybe mainline will default to schedlock_step one day, as well?
Regards,
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] 45+ messages in thread
* Re: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-15 9:29 ` Metzger, Markus T
@ 2015-09-15 17:19 ` Jan Kratochvil
2015-09-16 7:59 ` Metzger, Markus T
0 siblings, 1 reply; 45+ messages in thread
From: Jan Kratochvil @ 2015-09-15 17:19 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: Pedro Alves, gdb-patches
Hello Markus,
On Tue, 15 Sep 2015 11:28:36 +0200, Metzger, Markus T wrote:
> > Thanks for bringing it up. I would have hard time mergin this patch's:
> > -static const char *scheduler_mode = schedlock_off;
> > +static const char *scheduler_mode = schedlock_reverse;
> > with
> > http://pkgs.fedoraproject.org/cgit/gdb.git/tree/gdb-6.6-scheduler_locking-
> > step-is-default.patch
> > -static const char *scheduler_mode = schedlock_off;
> > +static const char *scheduler_mode = schedlock_step;
>
> I don't believe that we need to preserve the current behaviour. If Fedora
> defaults to schedlock_step, why not also for record targets?
Yes, I would find logical that during "reverse-step" on Fedora the scheduler
locking is also turned on. But I do not see how to achieve it with your
patch. If I put there:
static const char *scheduler_mode = schedlock_step;
then during "reverse-*" commands there will be no scheduler locking.
If I put there:
static const char *scheduler_mode = schedlock_reverse;
then during forward "step" there will be no locking which would be
a regression for Fedora.
> It could be seen as bug-fix that record targets did not honour scheduler-locking.
I agree.
> The same holds for mainline, of course. But the new mode is much closer to
> schedlock_step than it is to schedlock_off.
Maybe. But when I make the default "schedlock_reverse" then it will regress
Fedora's forward "step".
> > My guess is there could be a new setting "set reverse-scheduler-locking" also
> > with "off/step/on" as it seems to me "step" also makes sense for the
> > scheduler locking in reverse mode.
>
> This would allow us to set different scheduler-locking modes for reverse/replay
> execution and for normal debugging. While this adds flexibility, I'm not sure it is
> actually needed.
I agree. It allows all the combinations to be set although some of the
combinations do not make much sense.
> I really only added the new mode because I did not want to change the default
> behaviour completely. Over time, I think we may want to deprecate it, even
> though schedlock_off isn't very useful with the usually quite short execution
> history. Maybe mainline will default to schedlock_step one day, as well?
But how to make the schedlock_step default while still benefiting from your
patch?
If I/we make schedlock_step the default then this code of your patch gets
disabled:
+ else if ((scheduler_mode == schedlock_reverse)
+ && ((execution_direction == EXEC_REVERSE)
+ || target_record_is_replaying (minus_one_ptid)))
+ {
+ /* User-settable 'scheduler' mode requires solo thread resume during
+ reverse/replay stepping. */
+ resume_ptid = inferior_ptid;
+ }
Here I feel just some misunderstanding.
The patch seems to me needing some update so that both schedlock_step and
schedlock_reverse can be the default at once.
Thanks,
Jan
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-15 17:19 ` Jan Kratochvil
@ 2015-09-16 7:59 ` Metzger, Markus T
2015-09-16 12:44 ` Metzger, Markus T
` (2 more replies)
0 siblings, 3 replies; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-16 7:59 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: Pedro Alves, gdb-patches
> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] On Behalf Of Jan Kratochvil
> Sent: Tuesday, September 15, 2015 7:20 PM
Hello Jan,
> On Tue, 15 Sep 2015 11:28:36 +0200, Metzger, Markus T wrote:
> > > Thanks for bringing it up. I would have hard time mergin this patch's:
> > > -static const char *scheduler_mode = schedlock_off;
> > > +static const char *scheduler_mode = schedlock_reverse;
> > > with
> > > http://pkgs.fedoraproject.org/cgit/gdb.git/tree/gdb-6.6-
> scheduler_locking-
> > > step-is-default.patch
> > > -static const char *scheduler_mode = schedlock_off;
> > > +static const char *scheduler_mode = schedlock_step;
> >
> > I don't believe that we need to preserve the current behaviour. If Fedora
> > defaults to schedlock_step, why not also for record targets?
>
> Yes, I would find logical that during "reverse-step" on Fedora the scheduler
> locking is also turned on. But I do not see how to achieve it with your
> patch. If I put there:
> static const char *scheduler_mode = schedlock_step;
> then during "reverse-*" commands there will be no scheduler locking.
That's a bug.
Record btrace still has some code that implements an implicit scheduler-
locking on during reverse/replay execution for all-stop targets. With Pedro's
ASNS patch, scheduler-locking should be honoured.
We could also make record btrace honour scheduler-locking for (soon legacy) all-
stop targets. The current implementation applies the same stepping command
to all threads matching the argument PTID:
ALL_NON_EXITED_THREADS (tp)
if (ptid_match (tp->ptid, ptid))
record_btrace_resume_thread (tp, flag);
I think what we want instead is to apply the requested stepping command to
INFERIOR_PTID and the corresponding continue command to all other threads
matching PTID. Is that correct?
We wouldn't even need to check for non-stop mode or distinguish between
non-stop and all-stop targets. Infrun should take care of all that.
What if INFERIOR_PTID does not match the argument PTID? Is that an internal
error? Or would we only resume the argument PTID in this case? What if it is
a process and not a single thread?
Record full doesn't really support multi-threading so scheduler-locking doesn't
apply.
> > The same holds for mainline, of course. But the new mode is much closer
> to
> > schedlock_step than it is to schedlock_off.
>
> Maybe. But when I make the default "schedlock_reverse" then it will
> regress
> Fedora's forward "step".
Mainline will default to schedlock_reverse to maintain the current behaviour.
Fedora will continue to default to schedlock_step and record btrace will now
behave correctly on (reverse-)continue commands (the current series doesn't
since the underlying target is still all-stop). It should already do the right thing
for (reverse-)step/next/finish commands.
> > I really only added the new mode because I did not want to change the
> default
> > behaviour completely. Over time, I think we may want to deprecate it,
> even
> > though schedlock_off isn't very useful with the usually quite short
> execution
> > history. Maybe mainline will default to schedlock_step one day, as well?
>
> But how to make the schedlock_step default while still benefiting from your
> patch?
The goal is to have record btrace honour scheduler-locking. This patch is trying
to do this without changing the current default behaviour by making the current
behaviour a new scheduler-locking mode.
> If I/we make schedlock_step the default then this code of your patch gets
> disabled:
>
> + else if ((scheduler_mode == schedlock_reverse)
> + && ((execution_direction == EXEC_REVERSE)
> + || target_record_is_replaying (minus_one_ptid)))
> + {
> + /* User-settable 'scheduler' mode requires solo thread resume during
> + reverse/replay stepping. */
> + resume_ptid = inferior_ptid;
> + }
Yes. But the code above this in infrun.c then applies:
else if ((scheduler_mode == schedlock_on)
|| (scheduler_mode == schedlock_step && step))
{
/* User-settable 'scheduler' mode requires solo thread
resume. */
resume_ptid = inferior_ptid;
}
Regards,
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] 45+ messages in thread
* RE: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-16 7:59 ` Metzger, Markus T
@ 2015-09-16 12:44 ` Metzger, Markus T
2015-09-16 13:23 ` Pedro Alves
2015-09-16 13:21 ` Pedro Alves
2015-09-17 8:39 ` Jan Kratochvil
2 siblings, 1 reply; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-16 12:44 UTC (permalink / raw)
To: Jan Kratochvil, Pedro Alves; +Cc: gdb-patches
> -----Original Message-----
> From: Metzger, Markus T
> Sent: Wednesday, September 16, 2015 9:59 AM
> To: Jan Kratochvil
> Cc: Pedro Alves; gdb-patches@sourceware.org
> Subject: RE: [PATCH 17/17] infrun: scheduler-locking reverse
Hello Jan, Pedro,
> We could also make record btrace honour scheduler-locking for (soon legacy)
> all-stop targets.
How about something like this? See also users/mmetzger/btrace-non-stop.
I'm going to send this in v3 of the non-stop series once the name of the new
scheduler-locking mode has been decided.
commit 6b8b0c23b57890cf0b8023b2b7a40bd3abf10758
Author: Markus Metzger <markus.t.metzger@intel.com>
Date: Wed Sep 16 09:05:22 2015 +0200
btrace: honour scheduler-locking for all-stop targets
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.
This assumes that inferior_ptid matches the argument ptid. If it doesn't,
behave as if the target were non-stop and apply the move command to all
threads matching the argument ptid.
This should make record btrace honour scheduler-locking.
Signed-off-by: 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 reverse.
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index b8e6466..057f2f9 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1880,33 +1880,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
@@ -1916,20 +1901,42 @@ 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 () && 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..249d075 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,159 @@ 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
+ }
+ }
}
-# 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_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
+ }
+ }
}
-# 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_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
+ }
+ }
}
-# 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\..*"
- }
+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
+ }
}
-# 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\..*"
- }
+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
+ }
+ }
}
+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
+ }
+}
+
+with_test_prefix "schedlock-reverse" {
+ gdb_test_no_output "set scheduler-locking reverse"
+
+ test_navigate
+ test_step
+ test_cont
+ test_rstep
+ test_goto_end
+}
+
+with_test_prefix "schedlock-on" {
+ gdb_test_no_output "set scheduler-locking on"
+
+ test_navigate
+ test_step
+ test_cont
+ test_rstep
+ test_goto_end
+}
+
+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 reverse and off
+ gdb_test_no_output "set scheduler-locking reverse"
+
+ 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
+ }
}
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] 45+ messages in thread
* Re: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-16 7:59 ` Metzger, Markus T
2015-09-16 12:44 ` Metzger, Markus T
@ 2015-09-16 13:21 ` Pedro Alves
2015-09-17 8:39 ` Jan Kratochvil
2 siblings, 0 replies; 45+ messages in thread
From: Pedro Alves @ 2015-09-16 13:21 UTC (permalink / raw)
To: Metzger, Markus T, Jan Kratochvil; +Cc: gdb-patches
On 09/16/2015 08:59 AM, Metzger, Markus T wrote:
> What if INFERIOR_PTID does not match the argument PTID? Is that an internal
> error?
It always matches.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-16 12:44 ` Metzger, Markus T
@ 2015-09-16 13:23 ` Pedro Alves
0 siblings, 0 replies; 45+ messages in thread
From: Pedro Alves @ 2015-09-16 13:23 UTC (permalink / raw)
To: Metzger, Markus T, Jan Kratochvil; +Cc: gdb-patches
On 09/16/2015 01:44 PM, Metzger, Markus T wrote:
> + For all-stop targets, we only step INFERIOR_PTID and continue others. */
> + if (!target_is_non_stop_p () && ptid_match (inferior_ptid, ptid))
> + {
I'd remove that ptid_match.
> +with_test_prefix "schedlock-reverse" {
> + gdb_test_no_output "set scheduler-locking reverse"
> +
> + test_navigate
> + test_step
> + test_cont
> + test_rstep
> + test_goto_end
> +}
> +
> +with_test_prefix "schedlock-on" {
> + gdb_test_no_output "set scheduler-locking on"
> +
> + test_navigate
> + test_step
> + test_cont
> + test_rstep
> + test_goto_end
> +}
> +
> +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
> +}
You can fold all these using foreach. E.g.,
foreach schedlock {"reverse" "on" "step"} {
with_test_prefix "schedlock-$schedlock" {
gdb_test_no_output "set scheduler-locking $schedlock"
test_navigate
test_step
test_cont_all
test_rstep
test_goto_end
}
}
Otherwise LGTM.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-16 7:59 ` Metzger, Markus T
2015-09-16 12:44 ` Metzger, Markus T
2015-09-16 13:21 ` Pedro Alves
@ 2015-09-17 8:39 ` Jan Kratochvil
2015-09-17 8:48 ` Metzger, Markus T
2 siblings, 1 reply; 45+ messages in thread
From: Jan Kratochvil @ 2015-09-17 8:39 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: Pedro Alves, gdb-patches
Hello Markus,
On Wed, 16 Sep 2015 09:59:23 +0200, Metzger, Markus T wrote:
> > If I/we make schedlock_step the default then this code of your patch gets
> > disabled:
> >
> > + else if ((scheduler_mode == schedlock_reverse)
> > + && ((execution_direction == EXEC_REVERSE)
> > + || target_record_is_replaying (minus_one_ptid)))
> > + {
> > + /* User-settable 'scheduler' mode requires solo thread resume during
> > + reverse/replay stepping. */
> > + resume_ptid = inferior_ptid;
> > + }
>
> Yes. But the code above this in infrun.c then applies:
>
> else if ((scheduler_mode == schedlock_on)
> || (scheduler_mode == schedlock_step && step))
> {
> /* User-settable 'scheduler' mode requires solo thread
> resume. */
> resume_ptid = inferior_ptid;
> }
OK, I get it now. I misunderstood it all despite word by word the new
description is right. I would suggest changing the proposed:
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\
reverse == scheduler locked during reverse/replay execution.\n\
to:
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 and reverse/replay execution.\n\
step == scheduler locked during stepping commands (step, next, stepi, nexti).\n\
This applies to both normal and reverse/replay execution.\n\
reverse == scheduler fully locked only during reverse/replay execution.\n\
And even gdb.texinfo somehow accordingly.
Thanks,
Jan
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-17 8:39 ` Jan Kratochvil
@ 2015-09-17 8:48 ` Metzger, Markus T
2015-09-17 10:11 ` Eli Zaretskii
0 siblings, 1 reply; 45+ messages in thread
From: Metzger, Markus T @ 2015-09-17 8:48 UTC (permalink / raw)
To: Jan Kratochvil, Eli Zaretskii (eliz@gnu.org); +Cc: Pedro Alves, gdb-patches
> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] On Behalf Of Jan Kratochvil
> Sent: Thursday, September 17, 2015 10:39 AM
Hello Jan, Eli,
> OK, I get it now. I misunderstood it all despite word by word the new
> description is right. I would suggest changing the proposed:
>
> 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\
> reverse == scheduler locked during reverse/replay execution.\n\
>
> to:
>
> 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 and reverse/replay execution.\n\
> step == scheduler locked during stepping commands (step, next, stepi,
> nexti).\n\
> This applies to both normal and reverse/replay execution.\n\
> reverse == scheduler fully locked only during reverse/replay execution.\n\
>
> And even gdb.texinfo somehow accordingly.
Fine with me. Eli, are you OK with the wording?
I already changed "reverse" into "replay" as discussed in a parallel thread.
I'm also using the terms "replay mode" and "record mode". I'm fine to change
them back into "reverse/replay execution" and "normal execution", which might
be clearer if you have not read the Record manual section.
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] 45+ messages in thread
* Re: [PATCH 17/17] infrun: scheduler-locking reverse
2015-09-17 8:48 ` Metzger, Markus T
@ 2015-09-17 10:11 ` Eli Zaretskii
0 siblings, 0 replies; 45+ messages in thread
From: Eli Zaretskii @ 2015-09-17 10:11 UTC (permalink / raw)
To: Metzger, Markus T; +Cc: jan.kratochvil, palves, gdb-patches
> From: "Metzger, Markus T" <markus.t.metzger@intel.com>
> CC: Pedro Alves <palves@redhat.com>, "gdb-patches@sourceware.org"
> <gdb-patches@sourceware.org>
> Date: Thu, 17 Sep 2015 08:47:28 +0000
>
> > 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\
> > reverse == scheduler locked during reverse/replay execution.\n\
> >
> > to:
> >
> > 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 and reverse/replay execution.\n\
> > step == scheduler locked during stepping commands (step, next, stepi,
> > nexti).\n\
> > This applies to both normal and reverse/replay execution.\n\
> > reverse == scheduler fully locked only during reverse/replay execution.\n\
> >
> > And even gdb.texinfo somehow accordingly.
>
> Fine with me. Eli, are you OK with the wording?
>
> I already changed "reverse" into "replay" as discussed in a parallel thread.
Assuming the "reverse" value above will become "replay", yes, I'm fine
with this wording.
> I'm also using the terms "replay mode" and "record mode". I'm fine to change
> them back into "reverse/replay execution" and "normal execution", which might
> be clearer if you have not read the Record manual section.
"Record mode" and "replay mode" are fine with me.
^ permalink raw reply [flat|nested] 45+ messages in thread
end of thread, other threads:[~2015-09-17 10:11 UTC | newest]
Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-09 10:36 [PATCH 00/17] record btrace: non-stop and ASNS Markus Metzger
2015-09-09 10:35 ` [PATCH 08/17] btrace: lock-step Markus Metzger
2015-09-09 10:35 ` [PATCH 10/17] btrace: temporarily set inferior_ptid in record_btrace_start_replaying Markus Metzger
2015-09-09 10:35 ` [PATCH 12/17] infrun: switch to NO_HISTORY thread Markus Metzger
2015-09-09 10:35 ` [PATCH 05/17] btrace: split record_btrace_step_thread Markus Metzger
2015-09-09 10:35 ` [PATCH 11/17] btrace: async Markus Metzger
2015-09-09 10:35 ` [PATCH 01/17] btrace: fix non-stop check in to_wait Markus Metzger
2015-09-09 10:35 ` [PATCH 15/17] btrace: allow full memory and register access for non-replaying threads Markus Metzger
2015-09-09 11:57 ` Pedro Alves
2015-09-09 10:35 ` [PATCH 03/17] btrace: improve stepping debugging Markus Metzger
2015-09-09 10:35 ` [PATCH 04/17] btrace: extract the breakpoint check from record_btrace_step_thread Markus Metzger
2015-09-09 10:35 ` [PATCH 14/17] target, record: add PTID argument to to_record_is_replaying Markus Metzger
2015-09-09 10:36 ` [PATCH 07/17] btrace: add missing NO_HISTORY Markus Metzger
2015-09-09 10:36 ` [PATCH 06/17] btrace: move breakpoint checking into stepping functions Markus Metzger
2015-09-09 10:36 ` [PATCH 09/17] btrace: resume all requested threads Markus Metzger
2015-09-09 12:06 ` Pedro Alves
2015-09-09 13:06 ` Metzger, Markus T
2015-09-09 10:36 ` [PATCH 17/17] infrun: scheduler-locking reverse Markus Metzger
2015-09-09 13:54 ` Pedro Alves
2015-09-12 19:43 ` Jan Kratochvil
2015-09-15 9:29 ` Metzger, Markus T
2015-09-15 17:19 ` Jan Kratochvil
2015-09-16 7:59 ` Metzger, Markus T
2015-09-16 12:44 ` Metzger, Markus T
2015-09-16 13:23 ` Pedro Alves
2015-09-16 13:21 ` Pedro Alves
2015-09-17 8:39 ` Jan Kratochvil
2015-09-17 8:48 ` Metzger, Markus T
2015-09-17 10:11 ` Eli Zaretskii
2015-09-09 10:36 ` [PATCH 16/17] target: add to_record_stop_replaying target method Markus Metzger
2015-09-09 11:59 ` Pedro Alves
2015-09-09 10:36 ` [PATCH 13/17] btrace: non-stop Markus Metzger
2015-09-09 11:54 ` Pedro Alves
2015-09-09 12:20 ` Metzger, Markus T
2015-09-09 13:47 ` Pedro Alves
2015-09-09 14:10 ` Metzger, Markus T
2015-09-09 14:51 ` Pedro Alves
2015-09-10 7:49 ` Metzger, Markus T
2015-09-10 11:05 ` Pedro Alves
2015-09-10 11:19 ` Metzger, Markus T
2015-09-10 11:32 ` Pedro Alves
2015-09-10 11:37 ` Metzger, Markus T
2015-09-10 12:48 ` Pedro Alves
2015-09-09 10:36 ` [PATCH 02/17] btrace: support to_stop Markus Metzger
2015-09-09 13:56 ` [PATCH 00/17] record btrace: non-stop and ASNS Pedro Alves
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).