From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 69443 invoked by alias); 17 Sep 2015 14:10:26 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 68259 invoked by uid 89); 17 Sep 2015 14:10:13 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL,BAYES_00,KAM_LAZY_DOMAIN_SECURITY,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mga11.intel.com Received: from mga11.intel.com (HELO mga11.intel.com) (192.55.52.93) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 17 Sep 2015 14:10:09 +0000 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP; 17 Sep 2015 07:09:59 -0700 X-ExtLoop1: 1 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by fmsmga001.fm.intel.com with ESMTP; 17 Sep 2015 07:09:58 -0700 Received: from ulvlx001.iul.intel.com (ulvlx001.iul.intel.com [172.28.207.17]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id t8HE9vip001560; Thu, 17 Sep 2015 15:09:57 +0100 Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id t8HE9v3G001632; Thu, 17 Sep 2015 16:09:57 +0200 Received: (from mmetzger@localhost) by ulvlx001.iul.intel.com with œ id t8HE9uNf001628; Thu, 17 Sep 2015 16:09:57 +0200 From: Markus Metzger To: palves@redhat.com Cc: gdb-patches@sourceware.org Subject: [PATCH v3 19/19] btrace: honour scheduler-locking for all-stop targets Date: Thu, 17 Sep 2015 14:10:00 -0000 Message-Id: <1442498990-1222-20-git-send-email-markus.t.metzger@intel.com> In-Reply-To: <1442498990-1222-1-git-send-email-markus.t.metzger@intel.com> References: <1442498990-1222-1-git-send-email-markus.t.metzger@intel.com> X-IsSubscribed: yes X-SW-Source: 2015-09/txt/msg00419.txt.bz2 In all-stop mode, record btrace maintains the old behaviour of an implicit scheduler-locking on. Now that we added a scheduler-locking mode to model this old behaviour, we don't need the respective code in record btrace anymore. Remove it. For all-stop targets, step inferior_ptid and continue other threads matching the argument ptid. Assert that inferior_ptid matches the argument ptid. This should make record btrace honour scheduler-locking. 2015-09-17 Markus Metzger gdb/ * record-btrace.c (record_btrace_resume): Honour scheduler-locking. testsuite/ * gdb.btrace/multi-thread-step.exp: Test scheduler-locking on, step, and replay. --- gdb/record-btrace.c | 57 +++--- gdb/testsuite/gdb.btrace/multi-thread-step.exp | 233 +++++++++++++++++-------- 2 files changed, 192 insertions(+), 98 deletions(-) diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index 42195d1..d14e6cf 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -1888,33 +1888,18 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step, enum gdb_signal signal) { struct thread_info *tp; - enum btrace_thread_flag flag; - ptid_t orig_ptid; + enum btrace_thread_flag flag, cflag; DEBUG ("resume %s: %s%s", target_pid_to_str (ptid), execution_direction == EXEC_REVERSE ? "reverse-" : "", step ? "step" : "cont"); - orig_ptid = ptid; - /* Store the execution direction of the last resume. If there is more than one to_resume call, we have to rely on infrun to not change the execution direction in-between. */ record_btrace_resume_exec_dir = execution_direction; - /* For all-stop targets we pick the current thread when asked to resume an - entire process or everything. */ - if (!target_is_non_stop_p ()) - { - if (ptid_equal (minus_one_ptid, ptid) || ptid_is_pid (ptid)) - ptid = inferior_ptid; - - tp = find_thread_ptid (ptid); - if (tp == NULL) - error (_("Cannot find thread to resume.")); - } - /* As long as we're not replaying, just forward the request. For non-stop targets this means that no thread is replaying. In order to @@ -1924,20 +1909,44 @@ record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step, && !record_btrace_is_replaying (ops, minus_one_ptid)) { ops = ops->beneath; - return ops->to_resume (ops, orig_ptid, step, signal); + return ops->to_resume (ops, ptid, step, signal); } /* Compute the btrace thread flag for the requested move. */ - if (step == 0) - flag = execution_direction == EXEC_REVERSE ? BTHR_RCONT : BTHR_CONT; + if (execution_direction == EXEC_REVERSE) + { + flag = step == 0 ? BTHR_RCONT : BTHR_RSTEP; + cflag = BTHR_RCONT; + } else - flag = execution_direction == EXEC_REVERSE ? BTHR_RSTEP : BTHR_STEP; + { + flag = step == 0 ? BTHR_CONT : BTHR_STEP; + cflag = BTHR_CONT; + } /* We just indicate the resume intent here. The actual stepping happens in - record_btrace_wait below. */ - ALL_NON_EXITED_THREADS (tp) - if (ptid_match (tp->ptid, ptid)) - record_btrace_resume_thread (tp, flag); + record_btrace_wait below. + + For all-stop targets, we only step INFERIOR_PTID and continue others. */ + if (!target_is_non_stop_p ()) + { + gdb_assert (ptid_match (inferior_ptid, ptid)); + + ALL_NON_EXITED_THREADS (tp) + if (ptid_match (tp->ptid, ptid)) + { + if (ptid_match (tp->ptid, inferior_ptid)) + record_btrace_resume_thread (tp, flag); + else + record_btrace_resume_thread (tp, cflag); + } + } + else + { + ALL_NON_EXITED_THREADS (tp) + if (ptid_match (tp->ptid, ptid)) + record_btrace_resume_thread (tp, flag); + } /* Async support. */ if (target_can_async_p ()) diff --git a/gdb/testsuite/gdb.btrace/multi-thread-step.exp b/gdb/testsuite/gdb.btrace/multi-thread-step.exp index 2295f71..c8f55d0 100644 --- a/gdb/testsuite/gdb.btrace/multi-thread-step.exp +++ b/gdb/testsuite/gdb.btrace/multi-thread-step.exp @@ -37,9 +37,29 @@ set bp_2 [gdb_get_line_number "bp.2" $srcfile] set bp_3 [gdb_get_line_number "bp.3" $srcfile] proc gdb_cont_to_line { line } { - gdb_breakpoint $line - gdb_continue_to_breakpoint "cont to $line" ".*$line\r\n.*" - delete_breakpoints + gdb_breakpoint $line + gdb_continue_to_breakpoint "cont to $line" ".*$line\r\n.*" + delete_breakpoints +} + +proc check_replay_insn { thread insn } { + gdb_test "thread apply $thread info record" \ + "Replay in progress\. At instruction $insn\." +} + +proc check_not_replaying { thread } { + global gdb_prompt + + set test "thread $thread not replaying" + + gdb_test_multiple "thread apply $thread info record" $test { + -re "Replay in progress" { + fail $test + } + -re "$gdb_prompt $" { + pass $test + } + } } # trace the code between the two breakpoints @@ -50,86 +70,151 @@ gdb_test "info threads" ".*" gdb_test_no_output "record btrace" gdb_cont_to_line $srcfile:$bp_2 -# navigate in the trace history for both threads -with_test_prefix "navigate" { - gdb_test "thread 1" ".*" - with_test_prefix "thread 1" { - gdb_test "record goto begin" ".*" - gdb_test "info record" ".*Replay in progress\. At instruction 1\." - } - gdb_test "thread 2" ".*" - with_test_prefix "thread 2" { - gdb_test "record goto begin" ".*" - gdb_test "info record" ".*Replay in progress\. At instruction 1\." - } +proc test_navigate {} { + with_test_prefix "navigate" { + gdb_test "thread 1" ".*" + with_test_prefix "thread 1" { + gdb_test "record goto begin" ".*" + + check_replay_insn 1 1 + check_not_replaying 2 + } + gdb_test "thread 2" ".*" + with_test_prefix "thread 2" { + gdb_test "record goto begin" ".*" + + check_replay_insn 1 1 + check_replay_insn 2 1 + } + } +} + +proc test_step {} { + with_test_prefix "step" { + gdb_test "thread 1" ".*" + with_test_prefix "thread 1" { + gdb_test "stepi" ".*" + + check_replay_insn 1 2 + check_replay_insn 2 1 + } + gdb_test "thread 2" ".*" + with_test_prefix "thread 2" { + gdb_test "stepi" ".*" + + check_replay_insn 1 2 + check_replay_insn 2 2 + } + } +} + +proc test_cont {} { + with_test_prefix "cont" { + gdb_test "thread 1" ".*" + with_test_prefix "thread 1" { + gdb_test "continue" "No more reverse-execution history.*" + + check_not_replaying 1 + check_replay_insn 2 2 + } + gdb_test "thread 2" ".*" + with_test_prefix "thread 2" { + gdb_test "continue" "No more reverse-execution history.*" + + check_not_replaying 1 + check_not_replaying 2 + } + } } -# step both threads -with_test_prefix "step" { - gdb_test "thread 1" ".*" - with_test_prefix "thread 1" { - gdb_test "info record" ".*Replay in progress\. At instruction 1\." - gdb_test "stepi" ".*" - gdb_test "info record" ".*Replay in progress\. At instruction 2\." - } - gdb_test "thread 2" ".*" - with_test_prefix "thread 2" { - gdb_test "info record" ".*Replay in progress\. At instruction 1\." - gdb_test "stepi" ".*" - gdb_test "info record" ".*Replay in progress\. At instruction 2\." - } +proc test_cont_all {} { + with_test_prefix "cont-all" { + gdb_test "continue" "No more reverse-execution history.*" + + # this works because we're lock-stepping threads that executed exactly + # the same code starting from the same instruction. + + check_not_replaying 1 + check_not_replaying 2 + } +} + +proc test_rstep {} { + with_test_prefix "reverse-step" { + gdb_test "thread apply all record goto 3" + + gdb_test "thread 1" ".*" + with_test_prefix "thread 1" { + gdb_test "reverse-stepi" ".*" + + check_replay_insn 1 2 + check_replay_insn 2 3 + } + gdb_test "thread 2" ".*" + with_test_prefix "thread 2" { + gdb_test "reverse-stepi" ".*" + + check_replay_insn 1 2 + check_replay_insn 2 2 + } + } } -# run to the end of the history for both threads -with_test_prefix "cont" { - gdb_test "thread 1" ".*" - with_test_prefix "thread 1" { - gdb_test "info record" ".*Replay in progress\. At instruction 2\." - gdb_test "continue" "No more reverse-execution history.*" - } - gdb_test "thread 2" ".*" - with_test_prefix "thread 2" { - gdb_test "info record" ".*Replay in progress\. At instruction 2\." - gdb_test "continue" "No more reverse-execution history.*" - } +proc test_goto_end {} { + with_test_prefix "goto-end" { + gdb_test "thread apply all record goto end" + + check_not_replaying 1 + check_not_replaying 2 + } } -# reverse-step both threads -with_test_prefix "reverse-step" { - gdb_test "thread 1" ".*" - with_test_prefix "thread 1" { - gdb_test "reverse-stepi" ".*" - gdb_test "info record" ".*Replay in progress\..*" - } - gdb_test "thread 2" ".*" - with_test_prefix "thread 2" { - gdb_test "reverse-stepi" ".*" - gdb_test "info record" ".*Replay in progress\..*" - } +foreach schedlock { "replay" "on" } { + with_test_prefix "schedlock-$schedlock" { + gdb_test_no_output "set scheduler-locking $schedlock" + + test_navigate + test_step + test_cont + test_rstep + test_goto_end + } } -# both threads are still replaying -with_test_prefix "check" { - gdb_test "thread 1" ".*" - with_test_prefix "thread 1" { - gdb_test "info record" ".*Replay in progress\..*" - } - gdb_test "thread 2" ".*" - with_test_prefix "thread 2" { - gdb_test "info record" ".*Replay in progress\..*" - } +with_test_prefix "schedlock-step" { + gdb_test_no_output "set scheduler-locking step" + + test_navigate + test_step + test_cont_all + test_rstep + test_goto_end } +# schedlock-off is difficult to test since we can't really say where the other +# thread will be when the resumed thread stops. + # navigate back into the history for thread 1 and continue thread 2 -with_test_prefix "cont" { - gdb_test "thread 1" ".*" - with_test_prefix "thread 1" { - gdb_test "record goto begin" ".*" - gdb_test "info record" ".*Replay in progress\. At instruction 1\." - } - gdb_test "thread 2" ".*" - with_test_prefix "thread 2" { - gdb_test "record goto end" ".*" - gdb_cont_to_line $srcfile:$bp_3 - } +with_test_prefix "cont-to-end" { + # this test only works for scheduler-locking replay + gdb_test_no_output "set scheduler-locking replay" + + gdb_test "thread 1" ".*" + with_test_prefix "thread 1" { + gdb_test "record goto begin" ".*" + + check_replay_insn 1 1 + } + gdb_test "thread 2" ".*" + with_test_prefix "thread 2" { + gdb_test "record goto end" ".*" + + check_not_replaying 2 + + # if we reach the breakpoint, thread 2 terminated... + gdb_cont_to_line $srcfile:$bp_3 + + # and thread 1 stopped replaying + check_not_replaying 1 + } } -- 1.8.3.1