* [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only
@ 2015-03-11 14:40 Pedro Alves
2015-03-11 14:40 ` [PATCH 1/4] No longer handle negative 'step' in 'proceed' Pedro Alves
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Pedro Alves @ 2015-03-11 14:40 UTC (permalink / raw)
To: gdb-patches
Currently, "set scheduler-locking step" is a bit odd. The manual
documents it as being optimized for stepping, so that focus of
debugging does not change unexpectedly, but then it says that
sometimes other threads may run, and thus focus may indeed change
unexpectedly... A user can then be excused to get confused and wonder
why does GDB behave like this.
I don't think a user should have to know about details of how "next"
or whatever other run control command is implemented internally to
understand when does the "scheduler-locking step" setting take effect.
Thus this series makes "set scheduler-locking step" hold threads
depending on whether the _command_ the user entered was a stepping
command [step/stepi/next/nexti], or not. More details in patch #3.
The rest of the series is related groundwork and cleaning up.
Tested on x86_64 Fedora 20, native and gdbserver.
Pedro Alves (4):
No longer handle negative 'step' in 'proceed'
Make step_start_function be per thread
Make "set scheduler-locking step" depend on user intention, only
Remove 'step' parameters from 'proceed' and 'resume'
gdb/breakpoint.c | 2 +-
gdb/doc/gdb.texinfo | 5 +-
gdb/gdbthread.h | 8 ++
gdb/infcall.c | 2 +-
gdb/infcmd.c | 38 +++++----
gdb/infrun.c | 139 ++++++++++++++++----------------
gdb/infrun.h | 4 +-
gdb/mi/mi-main.c | 2 +-
gdb/testsuite/gdb.threads/schedlock.exp | 11 ++-
gdb/windows-nat.c | 2 +-
10 files changed, 114 insertions(+), 99 deletions(-)
--
1.9.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/4] Make step_start_function be per thread
2015-03-11 14:40 [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
` (2 preceding siblings ...)
2015-03-11 14:40 ` [PATCH 4/4] Remove 'step' parameters from 'proceed' and 'resume' Pedro Alves
@ 2015-03-11 14:40 ` Pedro Alves
2015-03-24 18:07 ` [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
4 siblings, 0 replies; 9+ messages in thread
From: Pedro Alves @ 2015-03-11 14:40 UTC (permalink / raw)
To: gdb-patches
I noticed that step_start_function is still a global, while it
obviously should be a per-thread field.
gdb/ChangeLog:
2015-03-11 Pedro Alves <palves@redhat.com>
* infrun.c (step_start_function): Delete and ...
* gdbthread.h (struct thread_control_state) <step_start_function>:
... now a field here.
* infrun.c (clear_proceed_status_thread): Clear the thread's
step_start_function.
(proceed, process_event_stop_test, print_stop_event): Adjust.
---
gdb/gdbthread.h | 3 +++
gdb/infrun.c | 12 +++++-------
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index e9ae47d..ce4f76f 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -73,6 +73,9 @@ struct thread_control_state
CORE_ADDR step_range_start; /* Inclusive */
CORE_ADDR step_range_end; /* Exclusive */
+ /* Function the thread was in as of last it started stepping. */
+ struct symbol *step_start_function;
+
/* If GDB issues a target step request, and this is nonzero, the
target should single-step this thread once, and then continue
single-stepping it without GDB core involvement as long as the
diff --git a/gdb/infrun.c b/gdb/infrun.c
index ed4ba79..be1cc74 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -326,10 +326,6 @@ update_signals_program_target (void)
static struct cmd_list_element *stop_command;
-/* Function inferior was in as of last step command. */
-
-static struct symbol *step_start_function;
-
/* Nonzero if we want to give control to the user when we're notified
of shared library events by the dynamic linker. */
int stop_on_solib_events;
@@ -2409,6 +2405,7 @@ clear_proceed_status_thread (struct thread_info *tp)
tp->control.step_frame_id = null_frame_id;
tp->control.step_stack_frame_id = null_frame_id;
tp->control.step_over_calls = STEP_OVER_UNDEBUGGABLE;
+ tp->control.step_start_function = NULL;
tp->stop_requested = 0;
tp->control.stop_step = 0;
@@ -2589,7 +2586,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
tp = inferior_thread ();
if (step)
- step_start_function = find_pc_function (pc);
+ tp->control.step_start_function = find_pc_function (pc);
/* Fill in with reasonable starting values. */
init_thread_stepping_state (tp);
@@ -5171,7 +5168,8 @@ process_event_stop_test (struct execution_control_state *ecs)
ecs->event_thread->control.step_stack_frame_id)
&& (!frame_id_eq (ecs->event_thread->control.step_stack_frame_id,
outer_frame_id)
- || step_start_function != find_pc_function (stop_pc))))
+ || (ecs->event_thread->control.step_start_function
+ != find_pc_function (stop_pc)))))
{
CORE_ADDR real_stop_pc;
@@ -6444,7 +6442,7 @@ print_stop_event (struct target_waitstatus *ws)
if (tp->control.stop_step
&& frame_id_eq (tp->control.step_frame_id,
get_frame_id (get_current_frame ()))
- && step_start_function == find_pc_function (stop_pc))
+ && tp->control.step_start_function == find_pc_function (stop_pc))
{
/* Finished step, just print source line. */
source_flag = SRC_LINE;
--
1.9.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/4] Make "set scheduler-locking step" depend on user intention, only
2015-03-11 14:40 [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
2015-03-11 14:40 ` [PATCH 1/4] No longer handle negative 'step' in 'proceed' Pedro Alves
@ 2015-03-11 14:40 ` Pedro Alves
2015-03-18 20:06 ` Pedro Alves
2015-10-22 7:21 ` Jan Kratochvil
2015-03-11 14:40 ` [PATCH 4/4] Remove 'step' parameters from 'proceed' and 'resume' Pedro Alves
` (2 subsequent siblings)
4 siblings, 2 replies; 9+ messages in thread
From: Pedro Alves @ 2015-03-11 14:40 UTC (permalink / raw)
To: gdb-patches
Currently, "set scheduler-locking step" is a bit odd. The manual
documents it as being optimized for stepping, so that focus of
debugging does not change unexpectedly, but then it says that
sometimes other threads may run, and thus focus may indeed change
unexpectedly... A user can then be excused to get confused and wonder
why does GDB behave like this.
I don't think a user should have to know about details of how "next"
or whatever other run control command is implemented internally to
understand when does the "scheduler-locking step" setting take effect.
This patch completes a transition that the code has been moving
towards for a while. It makes "set scheduler-locking step" hold
threads depending on whether the _command_ the user entered was a
stepping command [step/stepi/next/nexti], or not.
Before, GDB could end up locking threads even on "continue" if for
some reason run control decides a thread needs to be single stepped
(e.g., for a software watchpoint).
After, if a "continue" happens to need to single-step for some reason,
we won't lock threads (unless when stepping over a breakpoint,
naturally). And if a stepping command wants to continue a thread for
bit, like when skipping a function to a step-resume breakpoint, we'll
still lock threads, so focus of debugging doesn't change.
In order to make this work, we need to record in the thread structure
whether what set it running was a stepping command.
(A follow up patch will remove the "step" parameters of 'proceed' and 'resume')
FWIW, Fedora GDB, which defaults to "scheduler-locking step" (mainline
defaults to "off") carries a different patch that goes in this
direction as well.
Tested on x86_64 Fedora 20, native and gdbserver.
gdb/ChangeLog:
2015-03-11 Pedro Alves <palves@redhat.com>
* gdbthread.h (struct thread_control_state) <stepping_command>:
New field.
* infcmd.c (step_once): Pass step=1 to clear_proceed_status. Set
the thread's stepping_command field.
* infrun.c (resume): Check the thread's stepping_command flag to
determine which threads should be resumed. Rename 'entry_step'
local to user_step.
(clear_proceed_status_thread): Clear 'stepping_command'.
(schedlock_applies): Change parameter type to struct thread_info
pointer. Adjust.
(find_thread_needs_step_over): Remove 'step' parameter. Adjust.
(switch_back_to_stepped_thread): Adjust calls to
'schedlock_applies'.
(_initialize_infrun): Adjust "set scheduler-locking step" help.
gdb/testsuite/ChangeLog:
2015-03-11 Pedro Alves <palves@redhat.com>
* gdb.threads/schedlock.exp (test_step): No longer expect that
"set scheduler-locking step" with "next" over a function call runs
threads unlocked.
gdb/doc/ChangeLog:
2015-03-11 Pedro Alves <palves@redhat.com>
* gdb.texinfo (test_step) <set scheduler-locking step>: No longer
mention that threads may sometimes run unlocked.
---
gdb/doc/gdb.texinfo | 5 ++--
gdb/gdbthread.h | 5 ++++
gdb/infcmd.c | 3 ++-
gdb/infrun.c | 43 +++++++++++++++------------------
gdb/testsuite/gdb.threads/schedlock.exp | 11 ++++-----
5 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 4b76ce9..d0e99fd 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -5846,9 +5846,8 @@ current thread may run when the inferior is resumed. The @code{step}
mode optimizes for single-stepping; it prevents other threads
from preempting the current thread while you are stepping, so that
the focus of debugging does not change unexpectedly.
-Other threads only rarely (or never) get a chance to run
-when you step. They are more likely to run when you @samp{next} over a
-function call, and they are completely free to run when you use commands
+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.
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index ce4f76f..bb15717 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -138,6 +138,11 @@ struct thread_control_state
thread was resumed as a result of a command applied to some other
thread (e.g., "next" with scheduler-locking off). */
struct interp *command_interp;
+
+ /* Whether the command that started the thread was a stepping
+ command. This is used to decide whether "set scheduler-locking
+ step" behaves like "on" or "off". */
+ int stepping_command;
};
/* Inferior thread specific part of `struct infcall_suspend_state'.
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 0211b5d..eddbbff 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1047,7 +1047,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
THREAD is set. */
struct thread_info *tp = inferior_thread ();
- clear_proceed_status (!skip_subroutines);
+ clear_proceed_status (1);
set_step_frame ();
if (!single_inst)
@@ -1121,6 +1121,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
tp->control.step_over_calls = STEP_OVER_ALL;
tp->step_multi = (count > 1);
+ tp->control.stepping_command = 1;
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
/* For async targets, register a continuation to do any
diff --git a/gdb/infrun.c b/gdb/infrun.c
index be1cc74..9ad7480 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2038,7 +2038,6 @@ user_visible_resume_ptid (int step)
we get a SIGINT random_signal, but for remote debugging and perhaps
other targets, that's not true).
- STEP nonzero if we should step (zero to continue instead).
SIG is the signal to give the inferior (zero for none). */
void
resume (int step, enum gdb_signal sig)
@@ -2050,13 +2049,10 @@ resume (int step, enum gdb_signal sig)
CORE_ADDR pc = regcache_read_pc (regcache);
struct address_space *aspace = get_regcache_aspace (regcache);
ptid_t resume_ptid;
- /* From here on, this represents the caller's step vs continue
- request, while STEP represents what we'll actually request the
- target to do. STEP can decay from a step to a continue, if e.g.,
- we need to implement single-stepping with breakpoints (software
- single-step). When deciding whether "set scheduler-locking step"
- applies, it's the callers intention that counts. */
- const int entry_step = step;
+ /* This represents the user's step vs continue request. When
+ deciding whether "set scheduler-locking step" applies, it's the
+ user's intention that counts. */
+ const int user_step = tp->control.stepping_command;
tp->stepped_breakpoint = 0;
@@ -2165,7 +2161,7 @@ resume (int step, enum gdb_signal sig)
target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
/* ... and safe to let other threads run, according to
schedlock. */
- resume_ptid = user_visible_resume_ptid (entry_step);
+ resume_ptid = user_visible_resume_ptid (user_step);
target_resume (resume_ptid, 0, GDB_SIGNAL_0);
discard_cleanups (old_cleanups);
return;
@@ -2207,7 +2203,7 @@ resume (int step, enum gdb_signal sig)
Unless we're calling an inferior function, as in that
case we pretend the inferior doesn't run at all. */
if (!tp->control.in_infcall)
- set_running (user_visible_resume_ptid (entry_step), 1);
+ set_running (user_visible_resume_ptid (user_step), 1);
discard_cleanups (old_cleanups);
return;
}
@@ -2280,7 +2276,7 @@ resume (int step, enum gdb_signal sig)
/* Decide the set of threads to ask the target to resume. Start
by assuming everything will be resumed, than narrow the set
by applying increasingly restricting conditions. */
- resume_ptid = user_visible_resume_ptid (entry_step);
+ resume_ptid = user_visible_resume_ptid (user_step);
/* Even if RESUME_PTID is a wildcard, and we end up resuming less
(e.g., we might need to step over a breakpoint), from the
@@ -2413,6 +2409,7 @@ clear_proceed_status_thread (struct thread_info *tp)
tp->control.proceed_to_finish = 0;
tp->control.command_interp = NULL;
+ tp->control.stepping_command = 0;
/* Discard any remaining commands or status from previous stop. */
bpstat_clear (&tp->control.stop_bpstat);
@@ -2492,21 +2489,19 @@ thread_still_needs_step_over (struct thread_info *tp)
we're about to do a step/next-like command to a thread. */
static int
-schedlock_applies (int step)
+schedlock_applies (struct thread_info *tp)
{
return (scheduler_mode == schedlock_on
|| (scheduler_mode == schedlock_step
- && step));
+ && tp->control.stepping_command));
}
/* Look a thread other than EXCEPT that has previously reported a
breakpoint event, and thus needs a step-over in order to make
- progress. Returns NULL is none is found. STEP indicates whether
- we're about to step the current thread, in order to decide whether
- "set scheduler-locking step" applies. */
+ progress. Returns NULL is none is found. */
static struct thread_info *
-find_thread_needs_step_over (int step, struct thread_info *except)
+find_thread_needs_step_over (struct thread_info *except)
{
struct thread_info *tp, *current;
@@ -2517,7 +2512,7 @@ find_thread_needs_step_over (int step, struct thread_info *except)
/* If scheduler locking applies, we can avoid iterating over all
threads. */
- if (schedlock_applies (step))
+ if (schedlock_applies (except))
{
if (except != current
&& thread_still_needs_step_over (current))
@@ -2652,7 +2647,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
Look for a thread other than the current (TP) that reported a
breakpoint hit and hasn't been resumed yet since. */
- step_over = find_thread_needs_step_over (step, tp);
+ step_over = find_thread_needs_step_over (tp);
if (step_over != NULL)
{
if (debug_infrun)
@@ -5592,7 +5587,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
current thread is stepping. If some other thread not the
event thread is stepping, then it must be that scheduler
locking is not in effect. */
- if (schedlock_applies (0))
+ if (schedlock_applies (ecs->event_thread))
return 0;
/* Look for the stepping/nexting thread, and check if any other
@@ -5628,7 +5623,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
stepping, then scheduler locking can't be in effect,
otherwise we wouldn't have resumed the current event
thread in the first place. */
- gdb_assert (!schedlock_applies (currently_stepping (tp)));
+ gdb_assert (!schedlock_applies (tp));
stepping_thread = tp;
}
@@ -7875,9 +7870,9 @@ 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 every single-step operation.\n\
- In this mode, no other thread may run during a step command.\n\
- Other threads may run while stepping over a function call ('next')."),
+step == scheduler locked during stepping commands (step, next, stepi, nexti).\n\
+ In this mode, other threads may run with other commands.\n\
+ Other threads may run during other commands."),
set_schedlock_func, /* traps on target vector */
show_scheduler_mode,
&setlist, &showlist);
diff --git a/gdb/testsuite/gdb.threads/schedlock.exp b/gdb/testsuite/gdb.threads/schedlock.exp
index b47af77..54e847e 100644
--- a/gdb/testsuite/gdb.threads/schedlock.exp
+++ b/gdb/testsuite/gdb.threads/schedlock.exp
@@ -285,8 +285,7 @@ proc test_step { schedlock cmd call_function } {
step_ten_loops $cmd
- # "next" lets other threads run while stepping over functions.
- if { $schedlock == "on" || ($schedlock == "step" && !$call_function) } {
+ if { $schedlock == "on" || $schedlock == "step" } {
set locked 1
} else {
set locked 0
@@ -302,10 +301,10 @@ foreach schedlock {"off" "step" "on"} {
test_step $schedlock "step" 0
}
with_test_prefix "cmd=next" {
- # With "next", and schedlock "step", threads run unlocked
- # when stepping over a function call. This exercises both
- # with and without a function call. Without a function
- # call "next" should behave just like "step".
+ # In GDB <= 7.9, with schedlock "step", "next" would
+ # unlock threads when stepping over a function call. This
+ # exercises "next" with and without a function call. WRT
+ # "schedlock step", "next" should behave just like "step".
foreach call_function {0 1} {
with_test_prefix "call_function=$call_function" {
test_step $schedlock "next" $call_function
--
1.9.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/4] No longer handle negative 'step' in 'proceed'
2015-03-11 14:40 [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
@ 2015-03-11 14:40 ` Pedro Alves
2015-03-11 14:40 ` [PATCH 3/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Pedro Alves @ 2015-03-11 14:40 UTC (permalink / raw)
To: gdb-patches
Nothing ever passes a negative 'step' to proceed.
Gets rid of one of the few remaining stop_after_trap references.
gdb/ChangeLog
2015-03-11 Pedro Alves <palves@redhat.com>
* infrun.c (proceed): No longer handle negative step.
---
gdb/infrun.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 0f8f531..ed4ba79 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -2588,10 +2588,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
pc = regcache_read_pc (regcache);
tp = inferior_thread ();
- if (step > 0)
+ if (step)
step_start_function = find_pc_function (pc);
- if (step < 0)
- stop_after_trap = 1;
/* Fill in with reasonable starting values. */
init_thread_stepping_state (tp);
--
1.9.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/4] Remove 'step' parameters from 'proceed' and 'resume'
2015-03-11 14:40 [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
2015-03-11 14:40 ` [PATCH 1/4] No longer handle negative 'step' in 'proceed' Pedro Alves
2015-03-11 14:40 ` [PATCH 3/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
@ 2015-03-11 14:40 ` Pedro Alves
2015-03-11 14:40 ` [PATCH 2/4] Make step_start_function be per thread Pedro Alves
2015-03-24 18:07 ` [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
4 siblings, 0 replies; 9+ messages in thread
From: Pedro Alves @ 2015-03-11 14:40 UTC (permalink / raw)
To: gdb-patches
The "step" parameters of 'proceed' and 'resume' aren't really useful
as indication of whether run control wants to single-step the target,
as that information must already be retrievable from
currently_stepping. In fact, if currently_stepping disagrees with
whether we single-stepped the target, then things break. Thus instead
of having the same information in two places, this patch removes those
parameters.
Setting 'step_start_function' is the only user of proceed's 'step'
argument, other than passing the 'step' argument down to 'resume' and
debug log output. Move that instead to set_step_frame, where we
already set other related fields.
clear_proceed_status keeps its "step" parameter for now because it
needs to know which set of threads should have their state cleared,
and is called before the "stepping_command" flag is set.
Tested on x86_64 Fedora 20, native and gdbserver.
gdb/ChangeLog:
2015-03-11 Pedro Alves <palves@redhat.com>
* breakpoint.c (until_break_command): Adjust call to proceed.
* gdbthread.h (struct thread_control_state) <stepping_command>:
New field.
* infcall.c (run_inferior_call): Adjust call to proceed.
* infcmd.c (run_command_1, proceed_thread_callback, continue_1):
Adjust calls to proceed.
(set_step_frame): Set the current thread's step_start_function
here.
(step_once): Adjust calls to proceed.
(jump_command, signal_command, until_next_command)
(finish_backward, finish_forward, proceed_after_attach_callback)
(attach_command_post_wait): Adjust calls to proceed.
* infrun.c (proceed_after_vfork_done): Adjust call to proceed.
(do_target_resume): New function, factored out from ...
(resume): ... here. Remove 'step' parameter. Instead, check
currently_stepping to determine whether the thread should be
single-stepped.
(proceed): Remove 'step' parameter and don't set the thread's
step_start_function here. Adjust call to 'resume'.
(handle_inferior_event): Adjust calls to 'resume'.
(switch_back_to_stepped_thread): Use do_target_resume instead of
'resume'.
(keep_going): Adjust calls to 'resume'.
* infrun.h (proceed): Remove 'step' parameter.
(resume): Likewise.
* windows-nat.c (do_initial_windows_stuff): Adjust call to
'resume'.
* mi/mi-main.c (proceed_thread): Adjust call to 'proceed'.
---
gdb/breakpoint.c | 2 +-
gdb/infcall.c | 2 +-
gdb/infcmd.c | 35 +++++++++++++----------
gdb/infrun.c | 84 +++++++++++++++++++++++++++++++------------------------
gdb/infrun.h | 4 +--
gdb/mi/mi-main.c | 2 +-
gdb/windows-nat.c | 2 +-
7 files changed, 74 insertions(+), 57 deletions(-)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 923523e..b7d8da9 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -11917,7 +11917,7 @@ until_break_command (char *arg, int from_tty, int anywhere)
stack_frame_id, bp_until);
make_cleanup_delete_breakpoint (breakpoint);
- proceed (-1, GDB_SIGNAL_DEFAULT, 0);
+ proceed (-1, GDB_SIGNAL_DEFAULT);
/* If we are running asynchronously, and proceed call above has
actually managed to start the target, arrange for breakpoints to
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 705e377..26c64f6 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -405,7 +405,7 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc)
{
int was_sync = sync_execution;
- proceed (real_pc, GDB_SIGNAL_0, 0);
+ proceed (real_pc, GDB_SIGNAL_0);
/* Inferior function calls are always synchronous, even if the
target supports asynchronous execution. Do here what
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index eddbbff..1c70675 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -634,7 +634,7 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main)
/* Start the target running. Do not use -1 continuation as it would skip
breakpoint right at the entry point. */
- proceed (regcache_read_pc (get_current_regcache ()), GDB_SIGNAL_0, 0);
+ proceed (regcache_read_pc (get_current_regcache ()), GDB_SIGNAL_0);
/* Since there was no error, there's no need to finish the thread
states here. */
@@ -687,7 +687,7 @@ proceed_thread_callback (struct thread_info *thread, void *arg)
switch_to_thread (thread->ptid);
clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
return 0;
}
@@ -771,7 +771,7 @@ continue_1 (int all_threads)
ensure_valid_thread ();
ensure_not_running ();
clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
}
@@ -867,9 +867,14 @@ static void
set_step_frame (void)
{
struct symtab_and_line sal;
+ CORE_ADDR pc;
+ struct frame_info *frame = get_current_frame ();
+ struct thread_info *tp = inferior_thread ();
- find_frame_sal (get_current_frame (), &sal);
- set_step_info (get_current_frame (), sal);
+ find_frame_sal (frame, &sal);
+ set_step_info (frame, sal);
+ pc = get_frame_pc (frame);
+ tp->control.step_start_function = find_pc_function (pc);
}
/* Step until outside of current statement. */
@@ -1122,7 +1127,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
tp->step_multi = (count > 1);
tp->control.stepping_command = 1;
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
/* For async targets, register a continuation to do any
additional steps. For sync targets, the caller will handle
@@ -1229,7 +1234,7 @@ jump_command (char *arg, int from_tty)
}
clear_proceed_status (0);
- proceed (addr, GDB_SIGNAL_0, 0);
+ proceed (addr, GDB_SIGNAL_0);
}
\f
@@ -1342,7 +1347,7 @@ signal_command (char *signum_exp, int from_tty)
}
clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, oursig, 0);
+ proceed ((CORE_ADDR) -1, oursig);
}
/* Queue a signal to be delivered to the current thread. */
@@ -1462,7 +1467,7 @@ until_next_command (int from_tty)
set_longjmp_breakpoint (tp, get_frame_id (frame));
old_chain = make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
if (target_can_async_p () && is_running (inferior_ptid))
{
@@ -1746,14 +1751,14 @@ finish_backward (struct symbol *function)
insert_step_resume_breakpoint_at_sal (gdbarch,
sr_sal, null_frame_id);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
else
{
/* We're almost there -- we just need to back up by one more
single-step. */
tp->control.step_range_start = tp->control.step_range_end = 1;
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
}
@@ -1795,7 +1800,7 @@ finish_forward (struct symbol *function, struct frame_info *frame)
cargs->function = function;
add_continuation (tp, finish_command_continuation, cargs,
finish_command_continuation_free_arg);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
discard_cleanups (old_chain);
if (!target_can_async_p ())
@@ -1864,7 +1869,7 @@ finish_command (char *arg, int from_tty)
print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
}
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
return;
}
@@ -2454,7 +2459,7 @@ proceed_after_attach_callback (struct thread_info *thread,
{
switch_to_thread (thread->ptid);
clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
return 0;
@@ -2541,7 +2546,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
if (inferior_thread ()->suspend.stop_signal == GDB_SIGNAL_0)
{
clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
}
}
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 9ad7480..6e8f4f0 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -859,7 +859,7 @@ proceed_after_vfork_done (struct thread_info *thread,
switch_to_thread (thread->ptid);
clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
return 0;
@@ -2032,6 +2032,33 @@ user_visible_resume_ptid (int step)
return resume_ptid;
}
+/* Wrapper for target_resume, that handles infrun-specific
+ bookkeeping. */
+
+static void
+do_target_resume (ptid_t resume_ptid, int step, enum gdb_signal sig)
+{
+ struct thread_info *tp = inferior_thread ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* Avoid confusing the next resume, if the next stop/resume
+ happens to apply to another thread. */
+ tp->suspend.stop_signal = GDB_SIGNAL_0;
+
+ /* Advise target which signals may be handled silently. If we have
+ removed breakpoints because we are stepping over one (in any
+ thread), we need to receive all signals to avoid accidentally
+ skipping a breakpoint during execution of a signal handler. */
+ if (step_over_info_valid_p ())
+ target_pass_signals (0, NULL);
+ else
+ target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
+
+ target_resume (resume_ptid, step, sig);
+}
+
/* Resume the inferior, but allow a QUIT. This is useful if the user
wants to interrupt some lengthy single-stepping operation
(for child processes, the SIGINT goes to the inferior, and so
@@ -2040,7 +2067,7 @@ user_visible_resume_ptid (int step)
SIG is the signal to give the inferior (zero for none). */
void
-resume (int step, enum gdb_signal sig)
+resume (enum gdb_signal sig)
{
struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
struct regcache *regcache = get_current_regcache ();
@@ -2053,6 +2080,11 @@ resume (int step, enum gdb_signal sig)
deciding whether "set scheduler-locking step" applies, it's the
user's intention that counts. */
const int user_step = tp->control.stepping_command;
+ /* This represents what we'll actually request the target to do.
+ This can decay from a step to a continue, if e.g., we need to
+ implement single-stepping with breakpoints (software
+ single-step). */
+ int step = currently_stepping (tp);
tp->stepped_breakpoint = 0;
@@ -2355,24 +2387,7 @@ resume (int step, enum gdb_signal sig)
gdb_assert (pc_in_thread_step_range (pc, tp));
}
- /* Install inferior's terminal modes. */
- target_terminal_inferior ();
-
- /* Avoid confusing the next resume, if the next stop/resume
- happens to apply to another thread. */
- tp->suspend.stop_signal = GDB_SIGNAL_0;
-
- /* Advise target which signals may be handled silently. If we have
- removed breakpoints because we are stepping over one (in any
- thread), we need to receive all signals to avoid accidentally
- skipping a breakpoint during execution of a signal handler. */
- if (step_over_info_valid_p ())
- target_pass_signals (0, NULL);
- else
- target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
-
- target_resume (resume_ptid, step, sig);
-
+ do_target_resume (resume_ptid, step, sig);
discard_cleanups (old_cleanups);
}
\f
@@ -2551,7 +2566,7 @@ find_thread_needs_step_over (struct thread_info *except)
You should call clear_proceed_status before calling proceed. */
void
-proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
+proceed (CORE_ADDR addr, enum gdb_signal siggnal)
{
struct regcache *regcache;
struct gdbarch *gdbarch;
@@ -2580,9 +2595,6 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
pc = regcache_read_pc (regcache);
tp = inferior_thread ();
- if (step)
- tp->control.step_start_function = find_pc_function (pc);
-
/* Fill in with reasonable starting values. */
init_thread_stepping_state (tp);
@@ -2625,9 +2637,9 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
- "infrun: proceed (addr=%s, signal=%s, step=%d)\n",
+ "infrun: proceed (addr=%s, signal=%s)\n",
paddress (gdbarch, addr),
- gdb_signal_to_symbol_string (siggnal), step);
+ gdb_signal_to_symbol_string (siggnal));
if (non_stop)
/* In non-stop, each thread is handled individually. The context
@@ -2713,8 +2725,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
tp->prev_pc = regcache_read_pc (get_current_regcache ());
/* Resume inferior. */
- resume (tp->control.trap_expected || step || bpstat_should_step (),
- tp->suspend.stop_signal);
+ resume (tp->suspend.stop_signal);
/* Wait for it to stop (if not standalone)
and in any case decode why it stopped, and act accordingly. */
@@ -3815,7 +3826,7 @@ handle_inferior_event (struct execution_control_state *ecs)
addresses. Make sure new breakpoints are inserted. */
if (stop_soon == NO_STOP_QUIETLY)
insert_breakpoints ();
- resume (0, GDB_SIGNAL_0);
+ resume (GDB_SIGNAL_0);
prepare_to_wait (ecs);
return;
}
@@ -3839,7 +3850,7 @@ handle_inferior_event (struct execution_control_state *ecs)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SPURIOUS\n");
if (!ptid_equal (ecs->ptid, inferior_ptid))
context_switch (ecs->ptid);
- resume (0, GDB_SIGNAL_0);
+ resume (GDB_SIGNAL_0);
prepare_to_wait (ecs);
return;
@@ -5727,6 +5738,8 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
if (stop_pc != tp->prev_pc)
{
+ ptid_t resume_ptid;
+
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
"infrun: expected thread advanced also\n");
@@ -5742,9 +5755,10 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
insert_single_step_breakpoint (get_frame_arch (frame),
get_frame_address_space (frame),
stop_pc);
- ecs->event_thread->control.trap_expected = 1;
- resume (0, GDB_SIGNAL_0);
+ resume_ptid = user_visible_resume_ptid (tp->control.stepping_command);
+ do_target_resume (resume_ptid,
+ currently_stepping (tp), GDB_SIGNAL_0);
prepare_to_wait (ecs);
}
else
@@ -6191,8 +6205,7 @@ keep_going (struct execution_control_state *ecs)
are supposed to pass through to the inferior. Simply
continue. */
discard_cleanups (old_cleanups);
- resume (currently_stepping (ecs->event_thread),
- ecs->event_thread->suspend.stop_signal);
+ resume (ecs->event_thread->suspend.stop_signal);
}
else
{
@@ -6264,8 +6277,7 @@ keep_going (struct execution_control_state *ecs)
ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
discard_cleanups (old_cleanups);
- resume (currently_stepping (ecs->event_thread),
- ecs->event_thread->suspend.stop_signal);
+ resume (ecs->event_thread->suspend.stop_signal);
}
prepare_to_wait (ecs);
diff --git a/gdb/infrun.h b/gdb/infrun.h
index 7301807..ab97eea 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -88,11 +88,11 @@ extern void start_remote (int from_tty);
step/stepi command. */
extern void clear_proceed_status (int step);
-extern void proceed (CORE_ADDR, enum gdb_signal, int);
+extern void proceed (CORE_ADDR, enum gdb_signal);
/* The `resume' routine should only be called in special circumstances.
Normally, use `proceed', which handles a lot of bookkeeping. */
-extern void resume (int, enum gdb_signal);
+extern void resume (enum gdb_signal);
/* Return a ptid representing the set of threads that we will proceed,
in the perspective of the user/frontend. */
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index acbdb55..2733e80 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -252,7 +252,7 @@ proceed_thread (struct thread_info *thread, int pid)
switch_to_thread (thread->ptid);
clear_proceed_status (0);
- proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 0);
+ proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}
static int
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 42a6046..61d4842 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -1673,7 +1673,7 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
wait_for_inferior ();
tp = inferior_thread ();
if (tp->suspend.stop_signal != GDB_SIGNAL_TRAP)
- resume (0, tp->suspend.stop_signal);
+ resume (tp->suspend.stop_signal);
else
break;
}
--
1.9.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/4] Make "set scheduler-locking step" depend on user intention, only
2015-03-11 14:40 ` [PATCH 3/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
@ 2015-03-18 20:06 ` Pedro Alves
2015-03-18 20:22 ` Eli Zaretskii
2015-10-22 7:21 ` Jan Kratochvil
1 sibling, 1 reply; 9+ messages in thread
From: Pedro Alves @ 2015-03-18 20:06 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: GDB Patches
Hi Eli,
Looks like nobody disagreed with this, so far.
Does the documentation change look OK?
Thanks,
Pedro Alves
On 03/11/2015 02:39 PM, Pedro Alves wrote:
> Currently, "set scheduler-locking step" is a bit odd. The manual
> documents it as being optimized for stepping, so that focus of
> debugging does not change unexpectedly, but then it says that
> sometimes other threads may run, and thus focus may indeed change
> unexpectedly... A user can then be excused to get confused and wonder
> why does GDB behave like this.
>
> I don't think a user should have to know about details of how "next"
> or whatever other run control command is implemented internally to
> understand when does the "scheduler-locking step" setting take effect.
>
> This patch completes a transition that the code has been moving
> towards for a while. It makes "set scheduler-locking step" hold
> threads depending on whether the _command_ the user entered was a
> stepping command [step/stepi/next/nexti], or not.
>
> Before, GDB could end up locking threads even on "continue" if for
> some reason run control decides a thread needs to be single stepped
> (e.g., for a software watchpoint).
>
> After, if a "continue" happens to need to single-step for some reason,
> we won't lock threads (unless when stepping over a breakpoint,
> naturally). And if a stepping command wants to continue a thread for
> bit, like when skipping a function to a step-resume breakpoint, we'll
> still lock threads, so focus of debugging doesn't change.
>
> In order to make this work, we need to record in the thread structure
> whether what set it running was a stepping command.
>
> (A follow up patch will remove the "step" parameters of 'proceed' and 'resume')
>
> FWIW, Fedora GDB, which defaults to "scheduler-locking step" (mainline
> defaults to "off") carries a different patch that goes in this
> direction as well.
>
> Tested on x86_64 Fedora 20, native and gdbserver.
>
> gdb/ChangeLog:
> 2015-03-11 Pedro Alves <palves@redhat.com>
>
> * gdbthread.h (struct thread_control_state) <stepping_command>:
> New field.
> * infcmd.c (step_once): Pass step=1 to clear_proceed_status. Set
> the thread's stepping_command field.
> * infrun.c (resume): Check the thread's stepping_command flag to
> determine which threads should be resumed. Rename 'entry_step'
> local to user_step.
> (clear_proceed_status_thread): Clear 'stepping_command'.
> (schedlock_applies): Change parameter type to struct thread_info
> pointer. Adjust.
> (find_thread_needs_step_over): Remove 'step' parameter. Adjust.
> (switch_back_to_stepped_thread): Adjust calls to
> 'schedlock_applies'.
> (_initialize_infrun): Adjust "set scheduler-locking step" help.
>
> gdb/testsuite/ChangeLog:
> 2015-03-11 Pedro Alves <palves@redhat.com>
>
> * gdb.threads/schedlock.exp (test_step): No longer expect that
> "set scheduler-locking step" with "next" over a function call runs
> threads unlocked.
>
> gdb/doc/ChangeLog:
> 2015-03-11 Pedro Alves <palves@redhat.com>
>
> * gdb.texinfo (test_step) <set scheduler-locking step>: No longer
> mention that threads may sometimes run unlocked.
> ---
> gdb/doc/gdb.texinfo | 5 ++--
> gdb/gdbthread.h | 5 ++++
> gdb/infcmd.c | 3 ++-
> gdb/infrun.c | 43 +++++++++++++++------------------
> gdb/testsuite/gdb.threads/schedlock.exp | 11 ++++-----
> 5 files changed, 33 insertions(+), 34 deletions(-)
>
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 4b76ce9..d0e99fd 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -5846,9 +5846,8 @@ current thread may run when the inferior is resumed. The @code{step}
> mode optimizes for single-stepping; it prevents other threads
> from preempting the current thread while you are stepping, so that
> the focus of debugging does not change unexpectedly.
> -Other threads only rarely (or never) get a chance to run
> -when you step. They are more likely to run when you @samp{next} over a
> -function call, and they are completely free to run when you use commands
> +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.
> diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
> index ce4f76f..bb15717 100644
> --- a/gdb/gdbthread.h
> +++ b/gdb/gdbthread.h
> @@ -138,6 +138,11 @@ struct thread_control_state
> thread was resumed as a result of a command applied to some other
> thread (e.g., "next" with scheduler-locking off). */
> struct interp *command_interp;
> +
> + /* Whether the command that started the thread was a stepping
> + command. This is used to decide whether "set scheduler-locking
> + step" behaves like "on" or "off". */
> + int stepping_command;
> };
>
> /* Inferior thread specific part of `struct infcall_suspend_state'.
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 0211b5d..eddbbff 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1047,7 +1047,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
> THREAD is set. */
> struct thread_info *tp = inferior_thread ();
>
> - clear_proceed_status (!skip_subroutines);
> + clear_proceed_status (1);
> set_step_frame ();
>
> if (!single_inst)
> @@ -1121,6 +1121,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread)
> tp->control.step_over_calls = STEP_OVER_ALL;
>
> tp->step_multi = (count > 1);
> + tp->control.stepping_command = 1;
> proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT, 1);
>
> /* For async targets, register a continuation to do any
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index be1cc74..9ad7480 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -2038,7 +2038,6 @@ user_visible_resume_ptid (int step)
> we get a SIGINT random_signal, but for remote debugging and perhaps
> other targets, that's not true).
>
> - STEP nonzero if we should step (zero to continue instead).
> SIG is the signal to give the inferior (zero for none). */
> void
> resume (int step, enum gdb_signal sig)
> @@ -2050,13 +2049,10 @@ resume (int step, enum gdb_signal sig)
> CORE_ADDR pc = regcache_read_pc (regcache);
> struct address_space *aspace = get_regcache_aspace (regcache);
> ptid_t resume_ptid;
> - /* From here on, this represents the caller's step vs continue
> - request, while STEP represents what we'll actually request the
> - target to do. STEP can decay from a step to a continue, if e.g.,
> - we need to implement single-stepping with breakpoints (software
> - single-step). When deciding whether "set scheduler-locking step"
> - applies, it's the callers intention that counts. */
> - const int entry_step = step;
> + /* This represents the user's step vs continue request. When
> + deciding whether "set scheduler-locking step" applies, it's the
> + user's intention that counts. */
> + const int user_step = tp->control.stepping_command;
>
> tp->stepped_breakpoint = 0;
>
> @@ -2165,7 +2161,7 @@ resume (int step, enum gdb_signal sig)
> target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass);
> /* ... and safe to let other threads run, according to
> schedlock. */
> - resume_ptid = user_visible_resume_ptid (entry_step);
> + resume_ptid = user_visible_resume_ptid (user_step);
> target_resume (resume_ptid, 0, GDB_SIGNAL_0);
> discard_cleanups (old_cleanups);
> return;
> @@ -2207,7 +2203,7 @@ resume (int step, enum gdb_signal sig)
> Unless we're calling an inferior function, as in that
> case we pretend the inferior doesn't run at all. */
> if (!tp->control.in_infcall)
> - set_running (user_visible_resume_ptid (entry_step), 1);
> + set_running (user_visible_resume_ptid (user_step), 1);
> discard_cleanups (old_cleanups);
> return;
> }
> @@ -2280,7 +2276,7 @@ resume (int step, enum gdb_signal sig)
> /* Decide the set of threads to ask the target to resume. Start
> by assuming everything will be resumed, than narrow the set
> by applying increasingly restricting conditions. */
> - resume_ptid = user_visible_resume_ptid (entry_step);
> + resume_ptid = user_visible_resume_ptid (user_step);
>
> /* Even if RESUME_PTID is a wildcard, and we end up resuming less
> (e.g., we might need to step over a breakpoint), from the
> @@ -2413,6 +2409,7 @@ clear_proceed_status_thread (struct thread_info *tp)
> tp->control.proceed_to_finish = 0;
>
> tp->control.command_interp = NULL;
> + tp->control.stepping_command = 0;
>
> /* Discard any remaining commands or status from previous stop. */
> bpstat_clear (&tp->control.stop_bpstat);
> @@ -2492,21 +2489,19 @@ thread_still_needs_step_over (struct thread_info *tp)
> we're about to do a step/next-like command to a thread. */
>
> static int
> -schedlock_applies (int step)
> +schedlock_applies (struct thread_info *tp)
> {
> return (scheduler_mode == schedlock_on
> || (scheduler_mode == schedlock_step
> - && step));
> + && tp->control.stepping_command));
> }
>
> /* Look a thread other than EXCEPT that has previously reported a
> breakpoint event, and thus needs a step-over in order to make
> - progress. Returns NULL is none is found. STEP indicates whether
> - we're about to step the current thread, in order to decide whether
> - "set scheduler-locking step" applies. */
> + progress. Returns NULL is none is found. */
>
> static struct thread_info *
> -find_thread_needs_step_over (int step, struct thread_info *except)
> +find_thread_needs_step_over (struct thread_info *except)
> {
> struct thread_info *tp, *current;
>
> @@ -2517,7 +2512,7 @@ find_thread_needs_step_over (int step, struct thread_info *except)
>
> /* If scheduler locking applies, we can avoid iterating over all
> threads. */
> - if (schedlock_applies (step))
> + if (schedlock_applies (except))
> {
> if (except != current
> && thread_still_needs_step_over (current))
> @@ -2652,7 +2647,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step)
>
> Look for a thread other than the current (TP) that reported a
> breakpoint hit and hasn't been resumed yet since. */
> - step_over = find_thread_needs_step_over (step, tp);
> + step_over = find_thread_needs_step_over (tp);
> if (step_over != NULL)
> {
> if (debug_infrun)
> @@ -5592,7 +5587,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
> current thread is stepping. If some other thread not the
> event thread is stepping, then it must be that scheduler
> locking is not in effect. */
> - if (schedlock_applies (0))
> + if (schedlock_applies (ecs->event_thread))
> return 0;
>
> /* Look for the stepping/nexting thread, and check if any other
> @@ -5628,7 +5623,7 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs)
> stepping, then scheduler locking can't be in effect,
> otherwise we wouldn't have resumed the current event
> thread in the first place. */
> - gdb_assert (!schedlock_applies (currently_stepping (tp)));
> + gdb_assert (!schedlock_applies (tp));
>
> stepping_thread = tp;
> }
> @@ -7875,9 +7870,9 @@ 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 every single-step operation.\n\
> - In this mode, no other thread may run during a step command.\n\
> - Other threads may run while stepping over a function call ('next')."),
> +step == scheduler locked during stepping commands (step, next, stepi, nexti).\n\
> + In this mode, other threads may run with other commands.\n\
> + Other threads may run during other commands."),
> set_schedlock_func, /* traps on target vector */
> show_scheduler_mode,
> &setlist, &showlist);
> diff --git a/gdb/testsuite/gdb.threads/schedlock.exp b/gdb/testsuite/gdb.threads/schedlock.exp
> index b47af77..54e847e 100644
> --- a/gdb/testsuite/gdb.threads/schedlock.exp
> +++ b/gdb/testsuite/gdb.threads/schedlock.exp
> @@ -285,8 +285,7 @@ proc test_step { schedlock cmd call_function } {
>
> step_ten_loops $cmd
>
> - # "next" lets other threads run while stepping over functions.
> - if { $schedlock == "on" || ($schedlock == "step" && !$call_function) } {
> + if { $schedlock == "on" || $schedlock == "step" } {
> set locked 1
> } else {
> set locked 0
> @@ -302,10 +301,10 @@ foreach schedlock {"off" "step" "on"} {
> test_step $schedlock "step" 0
> }
> with_test_prefix "cmd=next" {
> - # With "next", and schedlock "step", threads run unlocked
> - # when stepping over a function call. This exercises both
> - # with and without a function call. Without a function
> - # call "next" should behave just like "step".
> + # In GDB <= 7.9, with schedlock "step", "next" would
> + # unlock threads when stepping over a function call. This
> + # exercises "next" with and without a function call. WRT
> + # "schedlock step", "next" should behave just like "step".
> foreach call_function {0 1} {
> with_test_prefix "call_function=$call_function" {
> test_step $schedlock "next" $call_function
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/4] Make "set scheduler-locking step" depend on user intention, only
2015-03-18 20:06 ` Pedro Alves
@ 2015-03-18 20:22 ` Eli Zaretskii
0 siblings, 0 replies; 9+ messages in thread
From: Eli Zaretskii @ 2015-03-18 20:22 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> Date: Wed, 18 Mar 2015 20:06:19 +0000
> From: Pedro Alves <palves@redhat.com>
> CC: GDB Patches <gdb-patches@sourceware.org>
>
> Hi Eli,
>
> Looks like nobody disagreed with this, so far.
>
> Does the documentation change look OK?
Yes, thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only
2015-03-11 14:40 [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
` (3 preceding siblings ...)
2015-03-11 14:40 ` [PATCH 2/4] Make step_start_function be per thread Pedro Alves
@ 2015-03-24 18:07 ` Pedro Alves
4 siblings, 0 replies; 9+ messages in thread
From: Pedro Alves @ 2015-03-24 18:07 UTC (permalink / raw)
To: gdb-patches
On 03/11/2015 02:39 PM, Pedro Alves wrote:
> Currently, "set scheduler-locking step" is a bit odd. The manual
> documents it as being optimized for stepping, so that focus of
> debugging does not change unexpectedly, but then it says that
> sometimes other threads may run, and thus focus may indeed change
> unexpectedly... A user can then be excused to get confused and wonder
> why does GDB behave like this.
>
> I don't think a user should have to know about details of how "next"
> or whatever other run control command is implemented internally to
> understand when does the "scheduler-locking step" setting take effect.
>
> Thus this series makes "set scheduler-locking step" hold threads
> depending on whether the _command_ the user entered was a stepping
> command [step/stepi/next/nexti], or not. More details in patch #3.
>
> The rest of the series is related groundwork and cleaning up.
>
> Tested on x86_64 Fedora 20, native and gdbserver.
I pushed this in now.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/4] Make "set scheduler-locking step" depend on user intention, only
2015-03-11 14:40 ` [PATCH 3/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
2015-03-18 20:06 ` Pedro Alves
@ 2015-10-22 7:21 ` Jan Kratochvil
1 sibling, 0 replies; 9+ messages in thread
From: Jan Kratochvil @ 2015-10-22 7:21 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
On Wed, 11 Mar 2015 15:39:57 +0100, Pedro Alves wrote:
> Currently, "set scheduler-locking step" is a bit odd. The manual
> documents it as being optimized for stepping, so that focus of
> debugging does not change unexpectedly, but then it says that
> sometimes other threads may run, and thus focus may indeed change
> unexpectedly... A user can then be excused to get confused and wonder
> why does GDB behave like this.
>
> I don't think a user should have to know about details of how "next"
> or whatever other run control command is implemented internally to
> understand when does the "scheduler-locking step" setting take effect.
>
> This patch completes a transition that the code has been moving
> towards for a while. It makes "set scheduler-locking step" hold
> threads depending on whether the _command_ the user entered was a
> stepping command [step/stepi/next/nexti], or not.
After some internal discussion making a note this can be considered a
regression from the user point of view.
LLDB by default locks the current thread if it keeps stepping inside the
current frame; but if it needs to run some other code it will run it with all
threads enabled.
This mostly matches what GDB did for the "set scheduler-locking step" mode -
AFAIK GDB ran all the threads for the parts which it was "continuing".
Which is also most convenient to be the default mode if one does not think much
about how one wants to step this time.
Jan
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-10-21 18:10 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-11 14:40 [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
2015-03-11 14:40 ` [PATCH 1/4] No longer handle negative 'step' in 'proceed' Pedro Alves
2015-03-11 14:40 ` [PATCH 3/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
2015-03-18 20:06 ` Pedro Alves
2015-03-18 20:22 ` Eli Zaretskii
2015-10-22 7:21 ` Jan Kratochvil
2015-03-11 14:40 ` [PATCH 4/4] Remove 'step' parameters from 'proceed' and 'resume' Pedro Alves
2015-03-11 14:40 ` [PATCH 2/4] Make step_start_function be per thread Pedro Alves
2015-03-24 18:07 ` [PATCH 0/4] Make "set scheduler-locking step" depend on user intention, only Pedro Alves
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox