From patchwork Fri Dec 29 10:42:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Natalia Saiapova X-Patchwork-Id: 83001 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E4A303858408 for ; Fri, 29 Dec 2023 10:45:01 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.100]) by sourceware.org (Postfix) with ESMTPS id D136D3858C41 for ; Fri, 29 Dec 2023 10:43:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D136D3858C41 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D136D3858C41 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=134.134.136.100 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703846602; cv=none; b=WEX92E8MMKdn9LzZd+A1LPEzcPr0rpxl2hfAXk45JMZ8WxDziVBHOfQWGiMiLBKzuB+2R6QBsehlULGdRiYbr+ms6AhxRF2R0XhXA7+xXQPHhty7BDNRUKO+rFrQCA3atdIKZxEnKzy5mA2Vxtn2c2v2f50+TZ1JmtAOJ3Fbj2w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703846602; c=relaxed/simple; bh=rlAmW/FJZ+Mx8ZqCBrbRQcrQmzokFBxSeTfbNv5OJNE=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=iggM6P4Nqkbl+E4vvhPOrCOuOwYVpsGoaJMJQVkREN9zJDiIpqRq3d5CzX3yddVIJUIXqmAZHnaGIRydIcfqskSHZ4e7MtttKtQdEWVYUKML/LQnHYbR/qVVh0NLX79zTfQQO9RvQ9nQvqpnumMYfOsSdp78oUdumMdm6sUer3o= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1703846596; x=1735382596; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rlAmW/FJZ+Mx8ZqCBrbRQcrQmzokFBxSeTfbNv5OJNE=; b=EJ6xKru0bz5qeVn9pJix+qwxYebUTAD0EaK/oxqqfoDmk9Ya/xuDU35Z EizT7yprO9XLNf0zlAj+OnEnCVQvx4tPmJm8XEzCm/2W7Is0Sq8BnAV59 AJQh9fJKppy55oR4VuDWudbTbAQ+OuZEWKS06xvhNWUiqn4bQDr7CDTPn RfMDfHTHWfKygUKR1Ugv53sEMJ7FTAgWxwJAB+OZXJYULkxV/O7AoE4+S mjVjaTlifMRJUupdJWPZlNNjRQP3kqARE8N3K8nlQDk6DaDYHTBSU6YV5 cPa+YBRpKmxZs5qKHRJr1Pl42WxTfs5X13yTu7ZiTG+QXjl4Mtn4uyKbc w==; X-IronPort-AV: E=McAfee;i="6600,9927,10937"; a="463052616" X-IronPort-AV: E=Sophos;i="6.04,314,1695711600"; d="scan'208";a="463052616" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2023 02:43:15 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10937"; a="782281328" X-IronPort-AV: E=Sophos;i="6.04,314,1695711600"; d="scan'208";a="782281328" Received: from unknown (HELO localhost) ([10.211.177.238]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 29 Dec 2023 02:43:14 -0800 From: Natalia Saiapova To: gdb-patches@sourceware.org Cc: tankut.baris.aktemur@intel.com Subject: [PATCH 5/6] gdb: add commands to control scheduler locking. Date: Fri, 29 Dec 2023 10:42:01 +0000 Message-Id: <20231229104202.7878-6-natalia.saiapova@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231229104202.7878-1-natalia.saiapova@intel.com> References: <20231229104202.7878-1-natalia.saiapova@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-13.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org In this patch, we introduce new command options for set/show scheduler locking. New options give the user finer control over the scheduler. Introduce set scheduler-locking show scheduler-locking For example, with these commands a user can get a combined scheduler locking for stepping commands during the normal execution and for all commands in replay mode. The existing scheduler-locking settings still exist and work as shortcuts. set scheduler-locking step is equivalent to set scheduler-locking replay run off set scheduler-locking replay step on set scheduler-locking run off set scheduler-locking step on set scheduler-locking on is equivalent to set scheduler-locking replay run on set scheduler-locking replay step on set scheduler-locking run on set scheduler-locking step on set scheduler-locking replay is equivalent to set scheduler-locking replay run on set scheduler-locking replay step on set scheduler-locking run off set scheduler-locking step off set scheduler-locking off is equivalent to set scheduler-locking replay run off set scheduler-locking replay step off set scheduler-locking run off set scheduler-locking step off This is bound to the structure we introduced in the previous commit: gdb: change the internal representation of scheduler locking. To introduce it under scheduler-locking I had to change the way the show command works. (gdb) show scheduler-locking scheduler-locking replay run: "on" Scheduler locking for non-stepping commands is "on" during replay mode. scheduler-locking replay step: "on" Scheduler locking for stepping commands is "on" during replay mode. scheduler-locking run: "off" Scheduler locking for non-stepping commands is "off" during normal execution. scheduler-locking step: "off" Scheduler locking for stepping commands is "off" during normal execution. (gdb) show scheduler-locking replay scheduler-locking replay run: "on" Scheduler locking for non-stepping commands is "on" during replay mode. scheduler-locking replay step: "on" Scheduler locking for stepping commands is "on" during replay mode. (gdb) show scheduler-locking replay step "on" Scheduler locking for stepping commands is "on" during replay mode. (gdb) show scheduler-locking run "off" Scheduler locking for non-stepping commands is "off" during normal execution. Note, there is a small inconsistency with the "set scheduler-locking step". If we did not keep the older way of setting the scheduler locking, command set scheduler-locking step would be the same as set scheduler-locking step on while to be backward compatible, we have it as set scheduler-locking step on set scheduler-locking replay step on Reviewed-By: Eli Zaretskii --- gdb/NEWS | 17 ++ gdb/doc/gdb.texinfo | 61 ++++- gdb/infrun.c | 220 ++++++++++++++---- .../gdb.mi/user-selected-context-sync.exp | 20 +- .../gdb.threads/hand-call-in-threads.exp | 8 +- .../multiple-successive-infcall.exp | 5 +- gdb/testsuite/gdb.threads/schedlock.exp | 79 ++++++- gdb/testsuite/lib/gdb.exp | 53 ++++- 8 files changed, 367 insertions(+), 96 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 4358494a6b6..bdbbadacb89 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -18,6 +18,23 @@ disassemble * New commands +set scheduler-locking replay run | replay step | run | step (on|off) +show scheduler-locking (replay run | replay step | run | step) + Extend the scheduler locking settings with a set of set/show + commands, which can be used individually to control the scheduler during + various commands. + 'replay run' -- when on, the scheduler is locked during non-stepping + commands in replay mode. + 'replay step' -- when on, the scheduler is locked during stepping + commands in replay mode. + 'run' -- when on, the scheduler is locked during non-stepping commands + in normal mode. + 'step' -- when on, the scheduler is locked during stepping commands + in normal mode. + The older scheduler locking settings can be used as shortcuts, their behavior + is not changed. + The output of "show scheduler-locking" has changed to support the new settings. + info missing-debug-handler List all the registered missing debug handlers. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 42a91235661..0560b9a5ea7 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -7110,22 +7110,56 @@ On some OSes, you can modify @value{GDBN}'s default behavior by locking the OS scheduler to allow only a single thread to run. @table @code -@item set scheduler-locking @var{mode} -@cindex scheduler-locking + +@item set scheduler-locking @var{type} [@code{on}|@code{off}] +@cindex scheduler locking type +@cindex lock scheduler +Set the scheduler locking settings. It applies to normal execution, +record mode, and replay mode. The scheduler locking can be set separately +for stepping and non-stepping commands. + +@table @code +@item replay run +When @code{on} the scheduler is locked for non-stepping commands during +replay mode. For commands like @samp{continue}, @samp{until}, @samp{finish}, +or expression evaluation only the current thread may run. + +@item replay step +When @code{on} the scheduler is locked for stepping commands during replay +mode. This mode optimizes for single-stepping; only the current thread is +resumed while you are stepping, so that the focus of debugging does not change +unexpectedly. + +@item run +When @code{on} the scheduler is locked for non-stepping commands during +normal execution and record modes. For commands like @samp{continue}, +@samp{until}, @samp{finish}, or expression evaluation only the current +thread may run. + +@item step +When @code{on} the scheduler is locked for stepping commands during +normal execution and record modes. This mode optimizes for single-stepping; +only the current thread is resumed while you are stepping, so that the focus +of debugging does not change unexpectedly. + +@end table + +@item set scheduler-locking @var{shortcut-mode} @cindex scheduler locking mode @cindex lock scheduler -Set the scheduler locking mode. It applies to normal execution, -record mode, and replay mode. @var{mode} can be one of -the following: +One can choose to not set the scheduler locking settings individually but use +the following predefined shortcut modes. @table @code @item off -There is no locking and any thread may run at any time. +There is no locking and any thread may run at any time. This is equivalent to +setting all options to @code{off}. @item on -Only the current thread may run when the inferior is resumed. New +Only the current thread may run when the inferior is resumed. New threads created by the resumed thread are held stopped at their entry -point, before they execute any instruction. +point, before they execute any instruction. This is +equivalent to setting all options to @code{on}. @item step Behaves like @code{on} when stepping, and @code{off} otherwise. @@ -7140,9 +7174,18 @@ another thread hits a breakpoint during its timeslice, @value{GDBN} does not change the current thread away from the thread that you are debugging. +This is equivalent to set @samp{scheduler-locking step} and +@samp{scheduler-locking replay step} to @code{on}, while other settings +are @code{off}. + @item replay Behaves like @code{on} in replay mode, and @code{off} in either record mode or during normal execution. This is the default mode. + +This is equivalent to set @samp{scheduler-locking replay run} and +@samp{scheduler-locking replay step} to @code{on}, while other settings +are @code{off}. + @end table @item show scheduler-locking @@ -33949,7 +33992,7 @@ the end or beginning of a replay log if one is being used. @end itemize In all-stop mode (@pxref{All-Stop Mode}), may resume only one thread, or all threads, depending on the -value of the @samp{scheduler-locking} variable. If @samp{--all} is +value of the @samp{scheduler-locking} variables. If @samp{--all} is specified, all threads (in all inferiors) will be resumed. The @samp{--all} option is ignored in all-stop mode. If the @samp{--thread-group} options is specified, then all threads in that thread group are resumed. diff --git a/gdb/infrun.c b/gdb/infrun.c index f70f615abf8..daf8cecd601 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -77,6 +77,7 @@ #include "extension.h" #include "disasm.h" #include "interps.h" +#include "cli/cli-decode.h" /* Prototypes for local functions */ @@ -116,6 +117,12 @@ struct schedlock_options; static bool schedlock_applies_to_opts (const schedlock_options &opts, bool step); +/* Command lists for the scheduler locking. */ +static cmd_list_element *schedlock_set_cmdlist; +static cmd_list_element *schedlock_show_cmdlist; +static cmd_list_element *schedlock_set_replay_cmdlist; +static cmd_list_element *schedlock_show_replay_cmdlist; + /* Asynchronous signal handler registered as event loop source for when we have pending events ready to be passed to the core. */ static struct async_event_handler *infrun_async_inferior_event_token; @@ -2348,7 +2355,8 @@ struct schedlock_options operator bool () const { return value; } const char *c_str () const { return value ? "on" : "off"; } - /* Set new value. Return true, if the value has changed. */ + /* Set new value. Return true, if the value has changed. + Also notifies the observer, if the value has changed. */ bool set (bool new_value); }; @@ -2375,6 +2383,8 @@ schedlock_options::option::set (bool new_value) if (value != new_value) { value = new_value; + std::string param_name = "scheduler-locking " + name; + interps_notify_param_changed (param_name.c_str (), c_str ()); return true; } @@ -2395,15 +2405,6 @@ static const char schedlock_off[] = "off"; static const char schedlock_on[] = "on"; static const char schedlock_step[] = "step"; static const char schedlock_replay[] = "replay"; -static const char *const scheduler_enums[] = { - schedlock_off, - schedlock_on, - schedlock_step, - schedlock_replay, - nullptr -}; - -static const char *scheduler_mode = schedlock_replay; schedlock schedlock {{{"run", false}, {"step", false}}, {{"replay run", true}, {"replay step", true}}}; @@ -2424,35 +2425,89 @@ set_schedlock_shortcut_option (const char *shortcut) /* Check that we got a valid shortcut option. */ gdb_assert (is_on || is_step || is_replay || is_off); - schedlock.normal.run.set (is_on); - schedlock.normal.step.set (is_on || is_step); - schedlock.replay.run.set (is_on || is_replay); - schedlock.replay.step.set (is_on || is_replay || is_step); + bool any_changed = schedlock.normal.run.set (is_on); + any_changed = schedlock.normal.step.set (is_on || is_step) || any_changed; + any_changed = schedlock.replay.run.set (is_on || is_replay) || any_changed; + any_changed = schedlock.replay.step.set (is_on || is_replay || is_step) + || any_changed; + + /* If at least one parameter has changed, notify the observer + in the old-fashioned way. */ + if (any_changed) + interps_notify_param_changed ("scheduler-locking", shortcut); } +/* Default callback for set methods of scheduler locking options. + Checks that the scheduler locking is supported. + If no, it reverts all options to "off" and throws an error. */ + static void -show_scheduler_mode (struct ui_file *file, int from_tty, - struct cmd_list_element *c, const char *value) +set_schedlock_callback (const char *args, int from_tty, cmd_list_element *c) { - gdb_printf (file, - _("Mode for locking scheduler " - "during execution is \"%s\".\n"), - value); + if (target_can_lock_scheduler ()) + return; + + /* Set scheduler locking off and error out. */ + set_schedlock_shortcut_option (schedlock_off); + error (_("Target '%s' cannot support this command."), target_shortname ()); } +/* Support for shortcut schedlock options: "on", "off", "step", "replay". */ + static void -set_schedlock_func (const char *args, int from_tty, struct cmd_list_element *c) +set_schedlock_step (const char *args, int from_tty, cmd_list_element *c) { - if (!target_can_lock_scheduler ()) - { - scheduler_mode = schedlock_off; - /* Set scheduler locking off. */ - set_schedlock_shortcut_option (schedlock_off); - error (_("Target '%s' cannot support this command."), - target_shortname ()); - } + if (!args || !*args) + set_schedlock_shortcut_option (schedlock_step); + set_schedlock_callback (args, from_tty, nullptr); +} + +static void +set_schedlock_replay (const char *args, int from_tty) +{ + set_schedlock_shortcut_option (schedlock_replay); + set_schedlock_callback (args, from_tty, nullptr); +} - set_schedlock_shortcut_option (scheduler_mode); +static void +set_schedlock_on (const char *args, int from_tty) +{ + set_schedlock_shortcut_option (schedlock_on); + set_schedlock_callback (args, from_tty, nullptr); +} + +static void +set_schedlock_off (const char *args, int from_tty) +{ + set_schedlock_shortcut_option (schedlock_off); + set_schedlock_callback (args, from_tty, nullptr); +} + +/* Default method to show a single option of scheduler locking. */ + +static void +show_schedlock_option (ui_file *file, int from_tty, + cmd_list_element *c, const char *value) +{ + gdb_assert (c->prefix != nullptr); + const char *mode; + if (strcmp (c->prefix->name, "replay") == 0) + mode = "replay mode"; + else if (strcmp (c->prefix->name, "scheduler-locking") == 0) + mode = "normal execution"; + else + gdb_assert_not_reached ("Unexpected command prefix."); + + const char *type; + if (strcmp (c->name, "step") == 0) + type = "stepping commands"; + else if (strcmp (c->name, "run") == 0) + type = "non-stepping commands"; + else + gdb_assert_not_reached ("Unexpected command name."); + + gdb_printf (file, _("\"%s\"\tScheduler locking for %s is " + "\"%s\" during the %s.\n"), value, type, value, mode); } /* True if execution commands resume all threads of all processes by @@ -8354,14 +8409,6 @@ switch_back_to_stepped_thread (struct execution_control_state *ecs) return true; } - /* If scheduler locking applies even if not stepping, there's no - need to walk over threads. Above we've checked whether the - 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_to_thread (ecs->event_thread)) - return false; - /* Otherwise, we no longer expect a trap in the current thread. Clear the trap_expected flag before switching back -- this is what keep_going does as well, if we call it. */ @@ -10652,21 +10699,92 @@ By default, the debugger will use the same inferior."), show_follow_exec_mode_string, &setlist, &showlist); - add_setshow_enum_cmd ("scheduler-locking", class_run, - 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\ - This applies to both normal execution and replay mode.\n\ -step == scheduler locked during stepping commands (step, next, stepi, nexti).\n\ - In this mode, other threads may run during other commands.\n\ - This applies to both normal execution and replay mode.\n\ -replay == scheduler locked in replay mode and unlocked during normal execution."), - set_schedlock_func, /* traps on target vector */ - show_scheduler_mode, + /* Commands for set/show scheduler-locking. */ + + add_setshow_prefix_cmd ("scheduler-locking", class_run, _("\ +Scheduler locking settings.\n\ +Configure scheduler locking settings in various conditions."), _("\ +Show scheduler locking settings in various conditions."), + &schedlock_set_cmdlist, + &schedlock_show_cmdlist, &setlist, &showlist); + add_setshow_boolean_cmd ("run", class_run, &schedlock.normal.run.value, _("\ +Scheduler locking for non-stepping commands during normal execution."), _("\ +Show scheduler locking for non-stepping commands during normal execution."), + _("\ +Controls scheduler locking for non-stepping commands during normal execution.\n\ +Commands include continue, until, finish. The setting does not affect \ +stepping."), + set_schedlock_callback, + show_schedlock_option, + &schedlock_set_cmdlist, + &schedlock_show_cmdlist); + + add_setshow_boolean_cmd ("step", class_run, &schedlock.normal.step.value, _("\ +Scheduler locking for stepping commands. W/o arguments locks the scheduler \ +for stepping."), _("\ +Show scheduler locking for stepping commands during normal execution."), _("\ +If argument \"on\" or \"off\", sets scheduler locking behavior for stepping\n\ +commands only during normal execution.\n\ +Commands include step, next, stepi, nexti."), + set_schedlock_step, + show_schedlock_option, + &schedlock_set_cmdlist, + &schedlock_show_cmdlist); + + /* Commands for set/show scheduler-locking in replay mode. + The base command adds support for the shortcut + set scheduler-locking replay + command. */ + + add_setshow_prefix_cmd ("replay", class_run, _("\ +Scheduler locking settings for replay mode.\n\ +Configure scheduler locking in various conditions such as during continuing\n\ +or stepping."), +("Show scheduler locking in replay mode."), + &schedlock_set_replay_cmdlist, + &schedlock_show_replay_cmdlist, + &schedlock_set_cmdlist, + &schedlock_show_cmdlist); + add_prefix_cmd ("replay", class_run, set_schedlock_replay, _("\ +Scheduler locking settings for replay mode. \ +W/o arguments completely locks the scheduler in replay mode."), + &schedlock_set_replay_cmdlist, + 0, &schedlock_set_cmdlist); + + add_setshow_boolean_cmd ("run", class_run, &schedlock.replay.run.value, _("\ +Set scheduler locking for non-stepping commands in replay mode."), _("\ +Show scheduler locking for non-stepping commands in replay mode."), _("\ +Controls scheduler locking for non-stepping commands in replay mode.\n\ +Commands include continue, until, finish. The setting does not affect \ +stepping."), + set_schedlock_callback, + show_schedlock_option, + &schedlock_set_replay_cmdlist, + &schedlock_show_replay_cmdlist); + + add_setshow_boolean_cmd ("step", class_run, &schedlock.replay.step.value, _("\ +Set scheduler locking for stepping commands in replay mode."), _("\ +Show scheduler locking for stepping commands in replay mode."), _("\ +Controls scheduler locking for stepping commands in replay mode.\n\ +Commands include step, next, stepi, nexti."), + set_schedlock_callback, + show_schedlock_option, + &schedlock_set_replay_cmdlist, + &schedlock_show_replay_cmdlist); + +/* Commands "set scheduler-locking on" and "set scheduler-locking off" + are provided for backward compatibility. */ + c = add_cmd ("on", class_run, set_schedlock_on, _("\ +[Shortcut] Full locking (no thread except the current thread may run).\n\ +This applies to both normal execution and replay mode."), + &schedlock_set_cmdlist); + + c = add_cmd ("off", class_run, set_schedlock_off, _("\ +[Shortcut] No locking (threads may preempt at any time)."), + &schedlock_set_cmdlist); + add_setshow_boolean_cmd ("schedule-multiple", class_run, &sched_multi, _("\ Set mode for resuming threads of all processes."), _("\ Show mode for resuming threads of all processes."), _("\ diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp index 4889c31aff3..625a47fb745 100644 --- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp +++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp @@ -255,17 +255,12 @@ proc make_cli_in_mi_re { command cli_in_mi_mode mode event inf cli_thread # Return the current value of the "scheduler-locking" parameter. proc show_scheduler_locking { } { - global gdb_prompt - global expect_out - - set any "\[^\r\n\]*" - set test "show scheduler-locking" - gdb_test_multiple $test $test { - -re ".*Mode for locking scheduler during execution is \"(${any})\".\r\n$gdb_prompt " { - pass $test - return $expect_out(1,string) - } + set schedlock [get_scheduler_locking $test] + + if {$schedlock ne "unknown"} { + pass $test + return $schedlock } error "Couldn't get current scheduler-locking value." @@ -342,7 +337,10 @@ proc test_continue_to_start { mode inf } { } # Restore scheduler-locking to its original value. - gdb_test_no_output "set scheduler-locking $previous_schedlock_val" + gdb_test_no_output "set scheduler-locking replay run [lindex $previous_schedlock_val 0]" + gdb_test_no_output "set scheduler-locking replay step [lindex $previous_schedlock_val 1]" + gdb_test_no_output "set scheduler-locking run [lindex $previous_schedlock_val 2]" + gdb_test_no_output "set scheduler-locking step [lindex $previous_schedlock_val 3]" } else { # $mode == "non-stop" # Put a thread-specific breakpoint for thread 2 of the current # inferior. We don't put a breakpoint for thread 3, since we diff --git a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp index 58039ddd30e..d18254910db 100644 --- a/gdb/testsuite/gdb.threads/hand-call-in-threads.exp +++ b/gdb/testsuite/gdb.threads/hand-call-in-threads.exp @@ -68,7 +68,9 @@ gdb_test "continue" \ # Before we start making hand function calls, turn on scheduler locking. gdb_test_no_output "set scheduler-locking on" "enable scheduler locking" -gdb_test "show scheduler-locking" ".* locking scheduler .* is \"on\"." "show scheduler locking on" +set test "show scheduler-locking on" +gdb_assert {[get_scheduler_locking $test {"on" "on" "on" "on"}] ne "unknown"} \ + $test # Now hand-call a function in each thread, having the function # stop without returning. @@ -139,7 +141,9 @@ gdb_test_multiple "maint print dummy-frames" "all dummies popped" { # Before we resume the full program, turn off scheduler locking. gdb_test_no_output "set scheduler-locking off" "disable scheduler locking" -gdb_test "show scheduler-locking" ".* locking scheduler .* is \"off\"." "show scheduler locking off" +set test "show scheduler-locking off" +gdb_assert {[get_scheduler_locking $test {"off" "off" "off" "off"}] ne "unknown"} \ + $test # Continue one last time, the program should exit normally. # diff --git a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp index bd037a02674..69e750fea44 100644 --- a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp +++ b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp @@ -49,8 +49,9 @@ foreach_with_prefix thread {5 4 3} { gdb_breakpoint [gdb_get_line_number "testmarker01"] gdb_continue_to_breakpoint "testmarker01" gdb_test_no_output "set scheduler-locking on" -gdb_test "show scheduler-locking" \ - "Mode for locking scheduler during execution is \"on\"." +set test "show scheduler-locking" +gdb_assert {[get_scheduler_locking $test {"on" "on" "on" "on"}] ne "unknown"} \ + $test foreach_with_prefix thread {5 4 3 2 1} { gdb_test "thread ${thread}" "Switching to .*" diff --git a/gdb/testsuite/gdb.threads/schedlock.exp b/gdb/testsuite/gdb.threads/schedlock.exp index 3c60f6b3478..cf11fd3a0a0 100644 --- a/gdb/testsuite/gdb.threads/schedlock.exp +++ b/gdb/testsuite/gdb.threads/schedlock.exp @@ -94,7 +94,8 @@ proc get_current_thread { description } { # Make sure we're stopped in the loop, in one of the non-main threads. proc goto_loop { msg } { - gdb_breakpoint [concat [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"] + global srcfile + gdb_breakpoint [concat "$srcfile:" [gdb_get_line_number "schedlock.exp: main loop"] " if arg != 0"] set test "return to loop" if {$msg != ""} { @@ -264,16 +265,21 @@ with_test_prefix "schedlock=on: cmd=continue" { } # Test stepping/nexting with different modes of scheduler locking. -proc test_step { schedlock cmd call_function } { +# Do scheduler-locking off setting before the test if PRESET_SCHEDLOCK_OFF is 1. +# LOCKED defines whether we expect the thread to be locked. If -1, then +# determine it first. +proc test_step { schedlock cmd call_function { preset_schedlock_off 1 } { locked -1 } } { global NUM - gdb_test_no_output "set scheduler-locking off" + if {$preset_schedlock_off} { + gdb_test_no_output "set scheduler-locking off" + } goto_loop "" set curthread [get_current_thread "before"] # No need to set to off again. This avoids a duplicate message. - if {$schedlock != "off"} { + if {$preset_schedlock_off && $schedlock != "off"} { gdb_test_no_output "set scheduler-locking $schedlock" } @@ -284,16 +290,17 @@ proc test_step { schedlock cmd call_function } { step_ten_loops $cmd - if { $schedlock == "on" || $schedlock == "step" } { - set locked 1 - } else { - set locked 0 + if { $locked == -1 } { + if { $schedlock == "on" || $schedlock == "step"} { + set locked 1 + } else { + set locked 0 + } } - check_result $cmd $curthread $before_args $locked } -# Test stepping/nexting with different modes of scheduler locking. +# Test stepping/nexting with different shortcut modes of scheduler locking. foreach schedlock {"off" "step" "on"} { with_test_prefix "schedlock=$schedlock" { with_test_prefix "cmd=step" { @@ -312,3 +319,55 @@ foreach schedlock {"off" "step" "on"} { } } } + +proc test_schedlock_opts {run step} { + set test "show scheduler-locking" + if {[get_scheduler_locking $test [list "off" "off" $run $step]] eq "unknown"} { + fail $test + } else { + pass $test + } + + set locked 0 + if {$step eq "on"} { + set locked 1 + } + + # Stepping tests. + with_test_prefix "cmd=step" { + test_step "" "step" 0 0 $locked + } + with_test_prefix "cmd=next" { + foreach call_function {0 1} { + with_test_prefix "call_function=$call_function" { + test_step "" "next" $call_function 0 $locked + } + } + } + + # Continuing tests. + set locked 0 + if {$run eq "on"} { + set locked 1 + } + with_test_prefix "cmd=continue" { + # Use whichever we stopped in. + set curthread [get_current_thread "before"] + set cont_args [get_args "before"] + my_continue "continue" + check_result "continue" $curthread $cont_args $locked + } +} + +gdb_test_no_output "set scheduler-locking off" + +# Test different options of scheduler locking. +foreach run {"off" "on"} { + foreach step {"off" "on"} { + with_test_prefix "run=$run step=$step" { + gdb_test_no_output "set scheduler-locking run $run" + gdb_test_no_output "set scheduler-locking step $step" + test_schedlock_opts $run $step + } + } +} diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index eb8f6998b1e..a7c85c2b20a 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -8565,6 +8565,42 @@ gdb_caching_proc gdb_target_symbol_prefix {} { return $prefix } +proc get_scheduler_locking {{test ""} {expected ""}} { + global gdb_prompt + if {$test eq ""} { + set test "reading current scheduler-locking mode" + } + + set any "\[^\r\n\]+" + set on_off "\(?:on|off\)" + + set i [expr 4 - [llength $expected]] + while {$i > 0} { + incr i -1 + lappend expected $on_off + } + set schedlock_regex \ + [multi_line \ + "${any}replay run: +\"\([lindex $expected 0]\)\"${any}non-stepping${any}replay${any}" \ + "${any}replay step: +\"\([lindex $expected 1]\)\"${any}stepping${any}replay${any}" \ + "${any}run: +\"\([lindex $expected 2]\)\"${any}non-stepping${any}normal execution${any}" \ + "${any}step: +\"\([lindex $expected 3]\)\"${any}stepping${any}normal execution${any}"] + + set current_schedule_locking_mode "unknown" + gdb_test_multiple "show scheduler-locking" $test { + -re -wrap $schedlock_regex { + set current_schedule_locking_mode \ + [list $expect_out(1,string) \ + $expect_out(2,string) \ + $expect_out(3,string) \ + $expect_out(4,string)] + } + -re -wrap "" {} + timeout {} + } + return $current_schedule_locking_mode +} + # Return 1 if target supports scheduler locking, otherwise return 0. gdb_caching_proc target_supports_scheduler_locking {} { @@ -8586,21 +8622,16 @@ gdb_caching_proc target_supports_scheduler_locking {} { set current_schedule_locking_mode "" set test "reading current scheduler-locking mode" - gdb_test_multiple "show scheduler-locking" $test { - -re "Mode for locking scheduler during execution is \"(\[\^\"\]*)\".*$gdb_prompt" { - set current_schedule_locking_mode $expect_out(1,string) - } - -re "$gdb_prompt $" { - set supports_schedule_locking 0 - } - timeout { - set supports_schedule_locking 0 - } + set current_schedule_locking_mode [get_scheduler_locking $test] + if { $current_scheduler_locking eq "unknown" } { + set supports_schedule_locking 0 } if { $supports_schedule_locking == -1 } { set test "checking for scheduler-locking support" - gdb_test_multiple "set scheduler-locking $current_schedule_locking_mode" $test { + + # Try to set scheduler-locking run. + gdb_test_multiple "set scheduler-locking run [lindex $current_schedule_locking_mode 0]" $test { -re "Target '\[^'\]+' cannot support this command\..*$gdb_prompt $" { set supports_schedule_locking 0 }