* [PATCH 0/2] Two Ada task improvements
@ 2021-11-04 17:37 Tom Tromey
2021-11-04 17:37 ` [PATCH 1/2] Add "task" keyword to the "watch" command Tom Tromey
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Tom Tromey @ 2021-11-04 17:37 UTC (permalink / raw)
To: gdb-patches
This short series improves Ada task support in gdb.
The first patch adds task-specific watchpoints. The second patch adds
a "task apply" command, based on "thread apply".
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] Add "task" keyword to the "watch" command
2021-11-04 17:37 [PATCH 0/2] Two Ada task improvements Tom Tromey
@ 2021-11-04 17:37 ` Tom Tromey
2021-11-04 18:48 ` Eli Zaretskii
2021-11-04 17:37 ` [PATCH 2/2] Implement 'task apply' Tom Tromey
2021-12-02 15:57 ` [PATCH 0/2] Two Ada task improvements Tom Tromey
2 siblings, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2021-11-04 17:37 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
Breakpoints in gdb can be made specific to an Ada task using the
"task" qualifier. This patch applies this same idea to watchpoints.
---
gdb/NEWS | 3 +
gdb/breakpoint.c | 12 ++++
gdb/doc/gdb.texinfo | 5 +-
gdb/testsuite/gdb.ada/task_watch.exp | 83 ++++++++++++++++++++++++
gdb/testsuite/gdb.ada/task_watch/foo.adb | 73 +++++++++++++++++++++
5 files changed, 175 insertions(+), 1 deletion(-)
create mode 100644 gdb/testsuite/gdb.ada/task_watch.exp
create mode 100644 gdb/testsuite/gdb.ada/task_watch/foo.adb
diff --git a/gdb/NEWS b/gdb/NEWS
index 9e950d2f80d..b6331d5585f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -24,6 +24,9 @@ show varsize-limit
These are now deprecated aliases for "set max-value-size" and
"show max-value-size".
+watch [...] task ID
+ Watchpoints can now be restricted to a specific Ada task.
+
maint set internal-error backtrace on|off
maint show internal-error backtrace
maint set internal-warning backtrace on|off
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 4ec60f334a2..c17eb01a3d9 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -10557,6 +10557,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
the hardware watchpoint. */
bool use_mask = false;
CORE_ADDR mask = 0;
+ int task = 0;
/* Make sure that we actually have parameters to parse. */
if (arg != NULL && arg[0] != '\0')
@@ -10612,6 +10613,16 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
thread = thr->global_num;
}
+ else if (toklen == 4 && startswith (tok, "task"))
+ {
+ char *tmp;
+
+ task = strtol (value_start, &tmp, 0);
+ if (tmp == value_start)
+ error (_("Junk after task keyword."));
+ if (!valid_task_id (task))
+ error (_("Unknown task %d."), task);
+ }
else if (toklen == 4 && startswith (tok, "mask"))
{
/* We've found a "mask" token, which means the user wants to
@@ -10785,6 +10796,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
init_raw_breakpoint_without_location (w.get (), NULL, bp_type,
&watchpoint_breakpoint_ops);
w->thread = thread;
+ w->task = task;
w->disposition = disp_donttouch;
w->pspace = current_program_space;
w->exp = std::move (exp);
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 308a97aeb82..b2bb079785e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -4862,7 +4862,7 @@ slow down the running of your program.
@table @code
@kindex watch
-@item watch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{thread-id}@r{]} @r{[}mask @var{maskvalue}@r{]}
+@item watch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{thread-id}@r{]} @r{[}mask @var{maskvalue}@r{]} @r{[}task @var{task-id}@r{]}
Set a watchpoint for an expression. @value{GDBN} will break when the
expression @var{expr} is written into by the program and its value
changes. The simplest (and the most popular) use of this command is
@@ -4879,6 +4879,9 @@ change the value of @var{expr}, @value{GDBN} will not break. Note
that watchpoints restricted to a single thread in this way only work
with Hardware Watchpoints.
+Similarly, if the @code{task} argument is given, then the watchpoint
+will be specific to the indicated Ada task (@pxref{Ada Tasks}).
+
Ordinarily a watchpoint respects the scope of variables in @var{expr}
(see below). The @code{-location} argument tells @value{GDBN} to
instead watch the memory referred to by @var{expr}. In this case,
diff --git a/gdb/testsuite/gdb.ada/task_watch.exp b/gdb/testsuite/gdb.ada/task_watch.exp
new file mode 100644
index 00000000000..fc276ef5f0e
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/task_watch.exp
@@ -0,0 +1,83 @@
+# Copyright 2009-2021 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 task-specific watchpoints.
+
+load_lib "ada.exp"
+
+if { [skip_ada_tests] } { return -1 }
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
+ return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP_HERE" ${testdir}/foo.adb]
+runto "foo.adb:$bp_location"
+
+# Make sure that all tasks appear in the "info tasks" listing, and
+# that the active task is the environment task.
+gdb_test "info tasks" \
+ [join {" +ID +TID P-ID Pri State +Name" \
+ "\\* +1 .* main_task" \
+ " +2 .* task_list\\(1\\)" \
+ " +3 .* task_list\\(2\\)" \
+ " +4 .* task_list\\(3\\)"} \
+ "\r\n"] \
+ "info tasks before inserting breakpoint"
+
+# Insert a watchpoint that should stop only if task 3 stops, and
+# extract its number.
+set bp_number -1
+set test "watch -location value task 3"
+gdb_test_multiple $test $test {
+ -re "atchpoint ($decimal): -location value\r\n$gdb_prompt $" {
+ set bp_number $expect_out(1,string)
+ pass $test
+ }
+}
+
+if {$bp_number < 0} {
+ return
+}
+
+# Continue to that watchpoint. Task 2 should hit it first, and GDB
+# is expected to ignore that hit and resume the execution. Only then
+# task 3 will hit our watchpoint, and GDB is expected to stop at that
+# point. Also make sure that GDB reports the correct watchpoint number.
+gdb_test "continue" \
+ ".* hit .*atchpoint $bp_number: -location value.*Old value = 1.*New value = 2.*" \
+ "continue to watchpoint"
+
+# Check that it is indeed task 3 that hit the watchpoint by checking
+# which is the active task.
+gdb_test "info tasks" \
+ [join {" +ID +TID P-ID Pri State +Name" \
+ " +1 .* main_task" \
+ " +2 .* task_list\\(1\\)" \
+ "\\* +3 .* task_list\\(2\\)" \
+ " +4 .* task_list\\(3\\)"} \
+ "\r\n"] \
+ "info tasks after hitting watchpoint"
+
+# Now, resume the execution and make sure that GDB does not stop when
+# task 4 hits the watchpoint. Continuing thus results in our program
+# running to completion.
+set bp_location [gdb_get_line_number "STOP_HERE_2" ${testdir}/foo.adb]
+gdb_breakpoint foo.adb:$bp_location
+gdb_continue_to_breakpoint second ".*foo.adb:$bp_location.*null; -- STOP_HERE_2"
diff --git a/gdb/testsuite/gdb.ada/task_watch/foo.adb b/gdb/testsuite/gdb.ada/task_watch/foo.adb
new file mode 100644
index 00000000000..f3540ec05c7
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/task_watch/foo.adb
@@ -0,0 +1,73 @@
+-- Copyright 2009-2021 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/>.
+
+procedure Foo is
+
+ Value : Integer := 0;
+
+ task type Caller is
+ entry Initialize;
+ entry Call_Break_Me;
+ entry Finalize;
+ end Caller;
+ type Caller_Ptr is access Caller;
+
+ procedure Break_Me is
+ begin
+ Value := Value + 1;
+ end Break_Me;
+
+ task body Caller is
+ begin
+ accept Initialize do
+ null;
+ end Initialize;
+ accept Call_Break_Me do
+ Break_Me;
+ end Call_Break_Me;
+ accept Finalize do
+ null;
+ end Finalize;
+ end Caller;
+
+ Task_List : array (1 .. 3) of Caller_Ptr;
+
+begin
+
+ -- Start all our tasks, and call the "Initialize" entry to make
+ -- sure all of them have now been started. We call that entry
+ -- immediately after having created the task in order to make sure
+ -- that we wait for that task to be created before we try to create
+ -- another one. That way, we know that the order in our Task_List
+ -- corresponds to the order in the GNAT runtime.
+ for J in Task_List'Range loop
+ Task_List (J) := new Caller;
+ Task_List (J).Initialize;
+ end loop;
+
+ -- Next, call their Call_Break_Me entry of each task, using the same
+ -- order as the order used to create them.
+ for J in Task_List'Range loop -- STOP_HERE
+ Task_List (J).Call_Break_Me;
+ end loop;
+
+ -- And finally, let all the tasks die...
+ for J in Task_List'Range loop
+ Task_List (J).Finalize;
+ end loop;
+
+ null; -- STOP_HERE_2
+
+end Foo;
--
2.31.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] Implement 'task apply'
2021-11-04 17:37 [PATCH 0/2] Two Ada task improvements Tom Tromey
2021-11-04 17:37 ` [PATCH 1/2] Add "task" keyword to the "watch" command Tom Tromey
@ 2021-11-04 17:37 ` Tom Tromey
2021-11-04 18:52 ` Eli Zaretskii
2021-12-02 15:57 ` [PATCH 0/2] Two Ada task improvements Tom Tromey
2 siblings, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2021-11-04 17:37 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
This adds a 'task apply' command, which is the Ada tasking analogue of
'thread apply'. Unlike 'thread apply', it doesn't offer the
'ascending' flag; but otherwise it's essentially the same.
---
gdb/NEWS | 3 +
gdb/ada-tasks.c | 204 ++++++++++++++++++++++++++++-
gdb/doc/gdb.texinfo | 35 +++++
gdb/gdbthread.h | 17 +++
gdb/testsuite/gdb.ada/rdv_wait.exp | 5 +
gdb/thread.c | 31 ++---
6 files changed, 277 insertions(+), 18 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index b6331d5585f..3ae65b17f07 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -24,6 +24,9 @@ show varsize-limit
These are now deprecated aliases for "set max-value-size" and
"show max-value-size".
+task apply [all | TASK-IDS...] [FLAG]... COMMAND
+ Like "thread apply", but applies COMMAND to Ada tasks.
+
watch [...] task ID
Watchpoints can now be restricted to a specific Ada task.
diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
index 32fbc14f703..d3ff1e2df64 100644
--- a/gdb/ada-tasks.c
+++ b/gdb/ada-tasks.c
@@ -1472,6 +1472,163 @@ ada_tasks_new_objfile_observer (struct objfile *objfile)
ada_tasks_invalidate_inferior_data (inf);
}
+/* The qcs command line flags for the "task apply" commands. Keep
+ this in sync with the "frame apply" commands. */
+
+using qcs_flag_option_def
+ = gdb::option::flag_option_def<qcs_flags>;
+
+static const gdb::option::option_def task_qcs_flags_option_defs[] = {
+ qcs_flag_option_def {
+ "q", [] (qcs_flags *opt) { return &opt->quiet; },
+ N_("Disables printing the task information."),
+ },
+
+ qcs_flag_option_def {
+ "c", [] (qcs_flags *opt) { return &opt->cont; },
+ N_("Print any error raised by COMMAND and continue."),
+ },
+
+ qcs_flag_option_def {
+ "s", [] (qcs_flags *opt) { return &opt->silent; },
+ N_("Silently ignore any errors or empty output produced by COMMAND."),
+ },
+};
+
+/* Create an option_def_group for the "task apply all" options, with
+ FLAGS as context. */
+
+static inline std::array<gdb::option::option_def_group, 1>
+make_task_apply_all_options_def_group (qcs_flags *flags)
+{
+ return {{
+ { {task_qcs_flags_option_defs}, flags },
+ }};
+}
+
+/* Create an option_def_group for the "task apply" options, with
+ FLAGS as context. */
+
+static inline gdb::option::option_def_group
+make_task_apply_options_def_group (qcs_flags *flags)
+{
+ return {{task_qcs_flags_option_defs}, flags};
+}
+
+/* Implementation of 'task apply all'. */
+
+static void
+task_apply_all_command (const char *cmd, int from_tty)
+{
+ qcs_flags flags;
+
+ auto group = make_task_apply_all_options_def_group (&flags);
+ gdb::option::process_options
+ (&cmd, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group);
+
+ validate_flags_qcs ("task apply all", &flags);
+
+ if (cmd == nullptr || *cmd == '\0')
+ error (_("Please specify a command at the end of 'task apply all'"));
+
+ update_thread_list ();
+ ada_build_task_list ();
+
+ inferior *inf = current_inferior ();
+ struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf);
+
+ /* Save a copy of the thread list and increment each thread's
+ refcount while executing the command in the context of each
+ thread, in case the command affects this. */
+ std::vector<std::pair<int, thread_info_ref>> thr_list_cpy;
+
+ for (int i = 1; i <= data->task_list.size (); ++i)
+ {
+ ada_task_info &task = data->task_list[i - 1];
+ if (!ada_task_is_alive (&task))
+ continue;
+
+ thread_info *tp = find_thread_ptid (inf, task.ptid);
+ if (tp == nullptr)
+ warning (_("Unable to compute thread ID for task %s.\n"
+ "Cannot switch to this task."),
+ task_to_str (i, &task).c_str ());
+ else
+ thr_list_cpy.emplace_back (i, thread_info_ref::new_reference (tp));
+ }
+
+ scoped_restore_current_thread restore_thread;
+
+ for (const auto &info : thr_list_cpy)
+ if (switch_to_thread_if_alive (info.second.get ()))
+ thread_try_catch_cmd (info.second.get (), info.first, cmd,
+ from_tty, flags);
+}
+
+/* Implementation of 'task apply'. */
+
+static void
+task_apply_command (const char *tidlist, int from_tty)
+{
+
+ if (tidlist == nullptr || *tidlist == '\0')
+ error (_("Please specify a task ID list"));
+
+ update_thread_list ();
+ ada_build_task_list ();
+
+ inferior *inf = current_inferior ();
+ struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf);
+
+ /* Save a copy of the thread list and increment each thread's
+ refcount while executing the command in the context of each
+ thread, in case the command affects this. */
+ std::vector<std::pair<int, thread_info_ref>> thr_list_cpy;
+
+ number_or_range_parser parser (tidlist);
+ while (!parser.finished ())
+ {
+ int num = parser.get_number ();
+
+ if (num < 1 || num - 1 >= data->task_list.size ())
+ warning (_("no Ada Task with number %d"), num);
+ else
+ {
+ ada_task_info &task = data->task_list[num - 1];
+ if (!ada_task_is_alive (&task))
+ continue;
+
+ thread_info *tp = find_thread_ptid (inf, task.ptid);
+ if (tp == nullptr)
+ warning (_("Unable to compute thread ID for task %s.\n"
+ "Cannot switch to this task."),
+ task_to_str (num, &task).c_str ());
+ else
+ thr_list_cpy.emplace_back (num,
+ thread_info_ref::new_reference (tp));
+ }
+ }
+
+ qcs_flags flags;
+ const char *cmd = parser.cur_tok ();
+
+ auto group = make_task_apply_options_def_group (&flags);
+ gdb::option::process_options
+ (&cmd, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group);
+
+ validate_flags_qcs ("task apply", &flags);
+
+ if (*cmd == '\0')
+ error (_("Please specify a command following the task ID list"));
+
+ scoped_restore_current_thread restore_thread;
+
+ for (const auto &info : thr_list_cpy)
+ if (switch_to_thread_if_alive (info.second.get ()))
+ thread_try_catch_cmd (info.second.get (), info.first, cmd,
+ from_tty, flags);
+}
+
void _initialize_tasks ();
void
_initialize_tasks ()
@@ -1482,11 +1639,52 @@ _initialize_tasks ()
gdb::observers::new_objfile.attach (ada_tasks_new_objfile_observer,
"ada-tasks");
+ static struct cmd_list_element *task_cmd_list;
+ static struct cmd_list_element *task_apply_list;
+
+
/* Some new commands provided by this module. */
add_info ("tasks", info_tasks_command,
_("Provide information about all known Ada tasks."));
- add_cmd ("task", class_run, task_command,
- _("Use this command to switch between Ada tasks.\n\
+
+ add_prefix_cmd ("task", class_run, task_command,
+ _("Use this command to switch between Ada tasks.\n\
Without argument, this command simply prints the current task ID."),
- &cmdlist);
+ &task_cmd_list, 1, &cmdlist);
+
+#define TASK_APPLY_OPTION_HELP "\
+Prints per-inferior task number followed by COMMAND output.\n\
+\n\
+By default, an error raised during the execution of COMMAND\n\
+aborts \"task apply\".\n\
+\n\
+Options:\n\
+%OPTIONS%"
+
+ static const auto task_apply_opts
+ = make_task_apply_options_def_group (nullptr);
+
+ static std::string task_apply_help = gdb::option::build_help (_("\
+Apply a command to a list of tasks.\n\
+Usage: task apply ID... [OPTION]... COMMAND\n\
+ID is a space-separated list of IDs of tasks to apply COMMAND on.\n"
+TASK_APPLY_OPTION_HELP), task_apply_opts);
+
+ add_prefix_cmd ("apply", class_run,
+ task_apply_command,
+ task_apply_help.c_str (),
+ &task_apply_list, 1,
+ &task_cmd_list);
+
+ static const auto task_apply_all_opts
+ = make_task_apply_all_options_def_group (nullptr);
+
+ static std::string task_apply_all_help = gdb::option::build_help (_("\
+Apply a command to all tasks in the current inferior.\n\
+\n\
+Usage: task apply all [OPTION]... COMMAND\n"
+TASK_APPLY_OPTION_HELP), task_apply_all_opts);
+
+ add_cmd ("all", class_run, task_apply_all_command,
+ task_apply_all_help.c_str (), &task_apply_list);
}
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b2bb079785e..5aad4436cb7 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18539,6 +18539,41 @@ from the current task to the given task.
#4 0x804aacc in un () at un.adb:5
@end smallexample
+@item task apply [@var{task-id-list} | all] [@var{flag}]@dots{} @var{command}
+The @code{task apply} command is the Ada tasking analogue of
+@code{thread apply} (@pxref{Threads}). It allows you to apply the
+named @var{command} to one or more tasks. Specify the tasks that you
+want affected using a list of task IDs, or specify @code{all} to apply
+to all tasks.
+
+The @var{flag} arguments control what output to produce and how to
+handle errors raised when applying @var{command} to a task.
+@var{flag} must start with a @code{-} directly followed by one letter
+in @code{qcs}. If several flags are provided, they must be given
+individually, such as @code{-c -q}.
+
+By default, @value{GDBN} displays some task information before the
+output produced by @var{command}, and an error raised during the
+execution of a @var{command} will abort @code{task apply}. The
+following flags can be used to fine-tune this behavior:
+
+@table @code
+@item -c
+The flag @code{-c}, which stands for @samp{continue}, causes any
+errors in @var{command} to be displayed, and the execution of
+@code{task apply} then continues.
+@item -s
+The flag @code{-s}, which stands for @samp{silent}, causes any errors
+or empty output produced by a @var{command} to be silently ignored.
+That is, the execution continues, but the task information and errors
+are not printed.
+@item -q
+The flag @code{-q} (@samp{quiet}) disables printing the task
+information.
+@end table
+
+Flags @code{-c} and @code{-s} cannot be used together.
+
@item break @var{location} task @var{taskno}
@itemx break @var{location} task @var{taskno} if @dots{}
@cindex breakpoints and tasks, in Ada
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index bd8d1a2952f..2fbf8f92cb9 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -975,4 +975,21 @@ extern void thread_select (const char *tidstr, class thread_info *thr);
target to get the name. May return nullptr. */
extern const char *thread_name (thread_info *thread);
+/* Switch to thread TP if it is alive. Returns true if successfully
+ switched, false otherwise. */
+
+extern bool switch_to_thread_if_alive (thread_info *thr);
+
+/* Assuming that THR is the current thread, execute CMD.
+ If ADA_TASK is not empty, it is the Ada task ID, and will
+ be printed instead of the thread information.
+ FLAGS.QUIET controls the printing of the thread information.
+ FLAGS.CONT and FLAGS.SILENT control how to handle errors. Can throw an
+ exception if !FLAGS.SILENT and !FLAGS.CONT and CMD fails. */
+
+extern void thread_try_catch_cmd (thread_info *thr,
+ gdb::optional<int> ada_task,
+ const char *cmd, int from_tty,
+ const qcs_flags &flags);
+
#endif /* GDBTHREAD_H */
diff --git a/gdb/testsuite/gdb.ada/rdv_wait.exp b/gdb/testsuite/gdb.ada/rdv_wait.exp
index 602443567a7..821adef4b1a 100644
--- a/gdb/testsuite/gdb.ada/rdv_wait.exp
+++ b/gdb/testsuite/gdb.ada/rdv_wait.exp
@@ -35,3 +35,8 @@ runto "break_me"
gdb_test "task 2" \
[join {"\\\[Switching to task 2 \"mit\"\\\].*" \
".*foo\\.t \\(.*\\).*foo\\.adb:.*"} ""]
+
+gdb_test "task apply 1 -q frame" ".*pck\\.break_me.*"
+
+gdb_test "task apply all frame" \
+ "Task ID 1:.*pck\\.break_me.*Task ID 2:.*"
diff --git a/gdb/thread.c b/gdb/thread.c
index ee9f05325cd..6c792eccb8f 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -662,10 +662,9 @@ thread_alive (thread_info *tp)
return target_thread_alive (tp->ptid);
}
-/* Switch to thread TP if it is alive. Returns true if successfully
- switched, false otherwise. */
+/* See gdbthreads.h. */
-static bool
+bool
switch_to_thread_if_alive (thread_info *thr)
{
scoped_restore_current_thread restore_thread;
@@ -1428,23 +1427,25 @@ tp_array_compar_descending (const thread_info_ref &a, const thread_info_ref &b)
return (a->per_inf_num > b->per_inf_num);
}
-/* Assuming that THR is the current thread, execute CMD.
- FLAGS.QUIET controls the printing of the thread information.
- FLAGS.CONT and FLAGS.SILENT control how to handle errors. Can throw an
- exception if !FLAGS.SILENT and !FLAGS.CONT and CMD fails. */
+/* See gdbthread.h. */
-static void
-thr_try_catch_cmd (thread_info *thr, const char *cmd, int from_tty,
- const qcs_flags &flags)
+void
+thread_try_catch_cmd (thread_info *thr, gdb::optional<int> ada_task,
+ const char *cmd, int from_tty,
+ const qcs_flags &flags)
{
gdb_assert (is_current_thread (thr));
/* The thread header is computed before running the command since
the command can change the inferior, which is not permitted
by thread_target_id_str. */
- std::string thr_header =
- string_printf (_("\nThread %s (%s):\n"), print_thread_id (thr),
- thread_target_id_str (thr).c_str ());
+ std::string thr_header;
+ if (ada_task.has_value ())
+ thr_header = string_printf (_("\nTask ID %d:\n"), *ada_task);
+ else
+ thr_header = string_printf (_("\nThread %s (%s):\n"),
+ print_thread_id (thr),
+ thread_target_id_str (thr).c_str ());
try
{
@@ -1576,7 +1577,7 @@ thread_apply_all_command (const char *cmd, int from_tty)
for (thread_info_ref &thr : thr_list_cpy)
if (switch_to_thread_if_alive (thr.get ()))
- thr_try_catch_cmd (thr.get (), cmd, from_tty, flags);
+ thread_try_catch_cmd (thr.get (), {}, cmd, from_tty, flags);
}
}
@@ -1738,7 +1739,7 @@ thread_apply_command (const char *tidlist, int from_tty)
continue;
}
- thr_try_catch_cmd (tp, cmd, from_tty, flags);
+ thread_try_catch_cmd (tp, {}, cmd, from_tty, flags);
}
}
--
2.31.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] Add "task" keyword to the "watch" command
2021-11-04 17:37 ` [PATCH 1/2] Add "task" keyword to the "watch" command Tom Tromey
@ 2021-11-04 18:48 ` Eli Zaretskii
0 siblings, 0 replies; 6+ messages in thread
From: Eli Zaretskii @ 2021-11-04 18:48 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
> Date: Thu, 4 Nov 2021 11:37:50 -0600
> From: Tom Tromey via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Tom Tromey <tromey@adacore.com>
>
> Breakpoints in gdb can be made specific to an Ada task using the
> "task" qualifier. This patch applies this same idea to watchpoints.
> ---
> gdb/NEWS | 3 +
> gdb/breakpoint.c | 12 ++++
> gdb/doc/gdb.texinfo | 5 +-
> gdb/testsuite/gdb.ada/task_watch.exp | 83 ++++++++++++++++++++++++
> gdb/testsuite/gdb.ada/task_watch/foo.adb | 73 +++++++++++++++++++++
> 5 files changed, 175 insertions(+), 1 deletion(-)
> create mode 100644 gdb/testsuite/gdb.ada/task_watch.exp
> create mode 100644 gdb/testsuite/gdb.ada/task_watch/foo.adb
Thanks, the documentation parts are okay.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] Implement 'task apply'
2021-11-04 17:37 ` [PATCH 2/2] Implement 'task apply' Tom Tromey
@ 2021-11-04 18:52 ` Eli Zaretskii
0 siblings, 0 replies; 6+ messages in thread
From: Eli Zaretskii @ 2021-11-04 18:52 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
> Date: Thu, 4 Nov 2021 11:37:51 -0600
> From: Tom Tromey via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Tom Tromey <tromey@adacore.com>
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index b6331d5585f..3ae65b17f07 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
This part is OK.
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
This is also okay, with one comment:
> +The @var{flag} arguments control what output to produce and how to
> +handle errors raised when applying @var{command} to a task.
> +@var{flag} must start with a @code{-} directly followed by one letter
> +in @code{qcs}. If several flags are provided, they must be given
> +individually, such as @code{-c -q}.
> +
> +By default, @value{GDBN} displays some task information before the
> +output produced by @var{command}, and an error raised during the
> +execution of a @var{command} will abort @code{task apply}. The
> +following flags can be used to fine-tune this behavior:
There seems to be some redundancy between these two paragraphs. Given
the detailed description that follows the second paragraph, I wonder
whether the first one is at all needed.
Thanks.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] Two Ada task improvements
2021-11-04 17:37 [PATCH 0/2] Two Ada task improvements Tom Tromey
2021-11-04 17:37 ` [PATCH 1/2] Add "task" keyword to the "watch" command Tom Tromey
2021-11-04 17:37 ` [PATCH 2/2] Implement 'task apply' Tom Tromey
@ 2021-12-02 15:57 ` Tom Tromey
2 siblings, 0 replies; 6+ messages in thread
From: Tom Tromey @ 2021-12-02 15:57 UTC (permalink / raw)
To: Tom Tromey via Gdb-patches; +Cc: Tom Tromey
>>>>> "Tom" == Tom Tromey via Gdb-patches <gdb-patches@sourceware.org> writes:
Tom> This short series improves Ada task support in gdb.
Tom> The first patch adds task-specific watchpoints. The second patch adds
Tom> a "task apply" command, based on "thread apply".
I'm checking this in now.
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-12-02 15:57 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-04 17:37 [PATCH 0/2] Two Ada task improvements Tom Tromey
2021-11-04 17:37 ` [PATCH 1/2] Add "task" keyword to the "watch" command Tom Tromey
2021-11-04 18:48 ` Eli Zaretskii
2021-11-04 17:37 ` [PATCH 2/2] Implement 'task apply' Tom Tromey
2021-11-04 18:52 ` Eli Zaretskii
2021-12-02 15:57 ` [PATCH 0/2] Two Ada task improvements Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).