From patchwork Wed Sep 16 12:44:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Metzger, Markus T" X-Patchwork-Id: 8722 Received: (qmail 64339 invoked by alias); 16 Sep 2015 12:44:28 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 64327 invoked by uid 89); 16 Sep 2015 12:44:27 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mga02.intel.com Received: from mga02.intel.com (HELO mga02.intel.com) (134.134.136.20) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 16 Sep 2015 12:44:25 +0000 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 16 Sep 2015 05:44:22 -0700 X-ExtLoop1: 1 Received: from irsmsx109.ger.corp.intel.com ([163.33.3.23]) by orsmga002.jf.intel.com with ESMTP; 16 Sep 2015 05:44:20 -0700 Received: from irsmsx155.ger.corp.intel.com (163.33.192.3) by IRSMSX109.ger.corp.intel.com (163.33.3.23) with Microsoft SMTP Server (TLS) id 14.3.224.2; Wed, 16 Sep 2015 13:44:19 +0100 Received: from irsmsx104.ger.corp.intel.com ([169.254.5.201]) by irsmsx155.ger.corp.intel.com ([169.254.14.184]) with mapi id 14.03.0224.002; Wed, 16 Sep 2015 13:44:19 +0100 From: "Metzger, Markus T" To: Jan Kratochvil , Pedro Alves CC: "gdb-patches@sourceware.org" Subject: RE: [PATCH 17/17] infrun: scheduler-locking reverse Date: Wed, 16 Sep 2015 12:44:18 +0000 Message-ID: References: <1441794909-32718-1-git-send-email-markus.t.metzger@intel.com> <1441794909-32718-18-git-send-email-markus.t.metzger@intel.com> <55F03A12.80307@redhat.com> <20150912194344.GA7575@host1.jankratochvil.net> <20150915171931.GA2056@host1.jankratochvil.net> In-Reply-To: MIME-Version: 1.0 X-IsSubscribed: yes > -----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 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 gdb/ * record-btrace.c (record_btrace_resume): Honour scheduler-locking. testsuite/ * gdb.btrace/multi-thread-step.exp: Test scheduler-locking on, step, and reverse. 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 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 + } }