diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/infrun.c | 59 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c | 65 | ||||
-rw-r--r-- | gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp | 62 |
5 files changed, 143 insertions, 56 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4370e13..18244d2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2014-03-20 Pedro Alves <palves@redhat.com> + + * infrun.c (previous_inferior_ptid): Adjust comment. + (deferred_step_ptid): Delete. + (infrun_thread_ptid_changed, prepare_to_proceed) + (init_wait_for_inferior): Adjust. + (handle_signal_stop): Delete deferred_step_ptid handling. + 2014-03-18 Jan Kratochvil <jan.kratochvil@redhat.com> PR gdb/15358 diff --git a/gdb/infrun.c b/gdb/infrun.c index fe5d88b..f189a86 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -127,9 +127,9 @@ show_step_stop_if_no_debug (struct ui_file *file, int from_tty, int sync_execution = 0; -/* wait_for_inferior and normal_stop use this to notify the user - when the inferior stopped in a different thread than it had been - running in. */ +/* proceed and normal_stop use this to notify the user when the + inferior stopped in a different thread than it had been running + in. */ static ptid_t previous_inferior_ptid; @@ -977,14 +977,6 @@ static CORE_ADDR singlestep_pc; static ptid_t saved_singlestep_ptid; static int stepping_past_singlestep_breakpoint; -/* If not equal to null_ptid, this means that after stepping over breakpoint - is finished, we need to switch to deferred_step_ptid, and step it. - - The use case is when one thread has hit a breakpoint, and then the user - has switched to another thread and issued 'step'. We need to step over - breakpoint in the thread which hit the breakpoint, but then continue - stepping the thread user has selected. */ -static ptid_t deferred_step_ptid; /* Displaced stepping. */ @@ -1583,9 +1575,6 @@ infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid) if (ptid_equal (singlestep_ptid, old_ptid)) singlestep_ptid = new_ptid; - if (ptid_equal (deferred_step_ptid, old_ptid)) - deferred_step_ptid = new_ptid; - for (displaced = displaced_step_inferior_states; displaced; displaced = displaced->next) @@ -2103,10 +2092,6 @@ prepare_to_proceed (int step) if (breakpoint_here_p (get_regcache_aspace (regcache), regcache_read_pc (regcache))) { - /* If stepping, remember current thread to switch back to. */ - if (step) - deferred_step_ptid = inferior_ptid; - /* Switch back to WAIT_PID thread. */ switch_to_thread (wait_ptid); @@ -2380,7 +2365,6 @@ init_wait_for_inferior (void) clear_proceed_status (); stepping_past_singlestep_breakpoint = 0; - deferred_step_ptid = null_ptid; target_last_wait_ptid = minus_one_ptid; @@ -3918,43 +3902,6 @@ handle_signal_stop (struct execution_control_state *ecs) } } - if (!ptid_equal (deferred_step_ptid, null_ptid)) - { - /* In non-stop mode, there's never a deferred_step_ptid set. */ - gdb_assert (!non_stop); - - /* If we stopped for some other reason than single-stepping, ignore - the fact that we were supposed to switch back. */ - if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP) - { - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, - "infrun: handling deferred step\n"); - - /* Pull the single step breakpoints out of the target. */ - if (singlestep_breakpoints_inserted_p) - { - if (!ptid_equal (ecs->ptid, inferior_ptid)) - context_switch (ecs->ptid); - remove_single_step_breakpoints (); - singlestep_breakpoints_inserted_p = 0; - } - - ecs->event_thread->control.trap_expected = 0; - - context_switch (deferred_step_ptid); - deferred_step_ptid = null_ptid; - /* Suppress spurious "Switching to ..." message. */ - previous_inferior_ptid = inferior_ptid; - - resume (1, GDB_SIGNAL_0); - prepare_to_wait (ecs); - return; - } - - deferred_step_ptid = null_ptid; - } - /* See if a thread hit a thread-specific breakpoint that was meant for another thread. If so, then step that thread past the breakpoint, and continue it. */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 88fd3ea..1986747 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-03-20 Pedro Alves <palves@redhat.com> + + * gdb.threads/step-over-lands-on-breakpoint.c: New file. + * gdb.threads/step-over-lands-on-breakpoint.exp: New file. + 2014-03-19 Pedro Alves <palves@redhat.com> * gdb.base/async.exp: Remove early return. diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c new file mode 100644 index 0000000..882ae82 --- /dev/null +++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.c @@ -0,0 +1,65 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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> +#include <unistd.h> +#include <stdlib.h> + +pthread_barrier_t barrier; +pthread_t child_thread; + +volatile unsigned int counter = 1; + +void * +child_function (void *arg) +{ + pthread_barrier_wait (&barrier); + + while (counter > 0) + { + counter++; + + asm (" nop"); /* set breakpoint child here */ + asm (" nop"); /* set breakpoint after step-over here */ + usleep (1); + } + + pthread_exit (NULL); +} + +static int +wait_threads (void) +{ + return 1; /* in wait_threads */ +} + +int +main () +{ + int res; + long i; + + pthread_barrier_init (&barrier, NULL, 2); + + res = pthread_create (&child_thread, NULL, child_function, NULL); + pthread_barrier_wait (&barrier); + wait_threads (); /* set wait-thread breakpoint here */ + + pthread_join (child_thread, NULL); + + exit (EXIT_SUCCESS); +} diff --git a/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp new file mode 100644 index 0000000..c17b346 --- /dev/null +++ b/gdb/testsuite/gdb.threads/step-over-lands-on-breakpoint.exp @@ -0,0 +1,62 @@ +# Copyright (C) 2014 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/>. + +# Test that when a step-over lands on a breakpoint, that breakpoint +# hit is reported. + +standard_testfile +set executable ${testfile} + +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ + executable [list debug "incdir=${objdir}"]] != "" } { + return -1 +} + +# Cover both stepping and non-stepping execution commands. +foreach command {"step" "next" "continue" } { + with_test_prefix $command { + clean_restart $executable + + if ![runto_main] { + continue + } + + gdb_breakpoint [gdb_get_line_number "set wait-thread breakpoint here"] + gdb_continue_to_breakpoint "run to wait-thread breakpoint" + gdb_test "info threads" "2 .*\\\* 1.*" "info threads shows all threads" + + gdb_test_no_output "set scheduler-locking on" + + delete_breakpoints + + gdb_breakpoint [gdb_get_line_number "set breakpoint child here"] + gdb_test "thread 2" "Switching to .*" + gdb_continue_to_breakpoint "run to breakpoint in thread 2" + gdb_test "p counter = 0" " = 0" "unbreak loop in thread 2" + + # Set a breakpoint exactly where the step-over will land. + gdb_breakpoint [gdb_get_line_number "breakpoint after step-over here"] + + # Switch back to thread 1 and disable scheduler locking. + gdb_test "thread 1" "Switching to .*" + gdb_test_no_output "set scheduler-locking off" + + # Thread 2 is still stopped at a breakpoint that needs to be + # stepped over before proceeding thread 1. However, right + # where the step-over lands there's another breakpoint + # installed, which should trap and be reported to the user. + gdb_test "$command" "step-over here.*" + } +} |