[RFA/doco] Document task-specific breakpoints

Joel Brobecker
2009-03-25T21:46:13Z

[-- Attachment #1: Type: text/plain, Size: 299 bytes --]

Hello,

As promised when I sent the code patches for task-specific breakpoints,
here is the associated documentation.

2009-03-25 Joel Brobecker <brobecker@adacore.com>

* gdb.texinfo (Ada Tasks): Add documentation about task-specific
breakpoints.

OK to commit?

Thanks,
--
Joel

[-- Attachment #2: task-tc.diff --]
[-- Type: text/x-diff, Size: 5480 bytes --]

diff --git a/gdb/testsuite/gdb.ada/tasks.exp b/gdb/testsuite/gdb.ada/tasks.exp
new file mode 100644
index 0000000..e5d9f92
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/tasks.exp
@@ -0,0 +1,79 @@
+# Copyright 2009 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/>.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+load_lib "ada.exp"
+
+set testdir "tasks"
+set testfile "${testdir}/foo"
+set srcfile ${srcdir}/${subdir}/${testfile}.adb
+set binfile ${objdir}/${subdir}/${testfile}
+
+file mkdir ${objdir}/${subdir}/${testdir}
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+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"
+
+# Now, insert a breakpoint that should stop only if task 3 stops.
+gdb_test "break break_me task 3" "Breakpoint .* at .*"
+
+# Continue to that breakpoint. 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 breakpoint, and GDB is expected to stop at that
+# point.
+gdb_test "continue" \
+ ".*Breakpoint.*, foo.break_me \\(\\).*" \
+ "continue to breakpoint"
+
+# Check that it is indeed task 3 that hit the breakpoint 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 breakpoint"
+
+# Now, resume the execution and make sure that GDB does not stop when
+# task 4 hits the breakpoint. Continuing thus results in our program
+# running to completion.
+gdb_test "continue" \
+ ".*Program exited normally\..*" \
+ "continue until end of program"
+
diff --git a/gdb/testsuite/gdb.ada/tasks/foo.adb b/gdb/testsuite/gdb.ada/tasks/foo.adb
new file mode 100644
index 0000000..edf66be
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/tasks/foo.adb
@@ -0,0 +1,68 @@
+-- Copyright 2009 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
+
+ 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
+ null;
+ 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;
+end Foo;