Re: [PATCH] Per-inferior thread IDs

Pedro Alves
2015-12-17T13:17:18Z

On 12/15/2015 07:39 PM, Eli Zaretskii wrote:
>> From: Pedro Alves <palves@redhat.com>
>> Date: Tue, 15 Dec 2015 19:05:16 +0000
>>
>> +See @xref{Convenience Vars,, Convenience Variables}, for general
>
> Either "See @ref" or just "@xref" (which will produce "See").

Good catch, thanks. I copied that mistake from the $_thread documentation.
Also, I realized that $_thread was not documented in the Convenience Vars
node. I fixed that now, and also mentioned the new $_inferior/$_gthread
variables there.

>
> Other than that, the documentation parts are OK, with one comment: it
> seems confusing to talk about "per-inferior ID" when evidently you
> refer to the 2.3 form of the thread ID. Can we find some other term
> for this ID?

You're right. How about per-inferior number to refer to the number
in the inferior, and use thread ID to generically refer to the
inferior num + thread num pair?

I'm now calling the expanded "inf-num.thr-num" thread ID form
the "qualified" thread ID.

See updated doc patch below. I found other places that talked about
thread number and updated them to say thread ID instead.
E.g., the "thread @var{threadno}" command now says "thread @var{thread-id}".

I think it's much less confusing now.

diff --git c/gdb/NEWS w/gdb/NEWS
index 9ca7f49..b4ff971 100644
--- c/gdb/NEWS
+++ w/gdb/NEWS
@@ -3,6 +3,45 @@

*** Changes since GDB 7.10

+* Per-inferior thread numbers
+
+ Thread numbers are now per inferior instead of global. If you're
+ debugging multiple inferiors, GDB displays thread IDs using an
+ expanded INF_NUM.THR_NUM form. For example:
+
+ (gdb) info threads
+ Id Target Id Frame
+ 1.1 Thread 0x7ffff7fc2740 (LWP 8155) (running)
+ 1.2 Thread 0x7ffff7fc1700 (LWP 8168) (running)
+ * 2.1 Thread 0x7ffff7fc2740 (LWP 8157) (running)
+ 2.2 Thread 0x7ffff7fc1700 (LWP 8190) (running)
+
+ Commands that accept thread IDs now accept the qualified form as
+ well:
+
+ (gdb) thread 2.1
+ [Switching to thread 2.1 (Thread 0x7ffff7fc2740 (LWP 8157))] (running)
+ (gdb)
+
+ As consequence, thread numbers as visible in the $_thread
+ convenience variable are no longer unique between inferiors.
+
+ GDB now maintains a second thread ID per thread, referred to as the
+ global thread ID, which is the new equivalent of thread numbers in
+ previous releases.
+
+ For backwards compatibility, MI's thread IDs always refer to global
+ IDs.
+
+* You can use "info threads -gid" to display the global thread ID of
+ all threads.
+
+* The new convenience variable $_gthread holds the global number of
+ the current thread.
+
+* The new convenience variable $_inferior holds the number of the
+ current inferior.
+
* Record btrace now supports non-stop mode.

* Support for tracepoints on aarch64-linux was added in GDBserver.
@@ -141,6 +180,14 @@ show remote exec-event-feature-packet
format. It outputs data in hexadecimal format with zero-padding on the
left.

+* Python Scripting
+
+ ** gdb.InferiorThread objects have a new attribute "global_num",
+ which refers to the thread's global thread ID. The existing
+ "num" attribute now refers to the thread's per-inferior number.
+ ** gdb.InferiorThread objects have a new attribute "inferior", which
+ is the Inferior object the thread belongs to.
+
*** Changes in GDB 7.10

* Support for process record-replay and reverse debugging on aarch64*-linux*
diff --git c/gdb/doc/gdb.texinfo w/gdb/doc/gdb.texinfo
index bb68e21..b0e4106 100644
--- c/gdb/doc/gdb.texinfo
+++ w/gdb/doc/gdb.texinfo
@@ -2658,6 +2658,12 @@ Make inferior number @var{infno} the current inferior. The argument
in the first field of the @samp{info inferiors} display.
@end table

+@vindex $_inferior@r{, convenience variable}
+The debugger convenience variable @samp{$_inferior} contains the
+number of the current inferior. You may find this useful in writing
+breakpoint conditional expressions, command scripts, and so forth.
+@xref{Convenience Vars,, Convenience Variables}, for general
+information on convenience variables.

You can get multiple executables into a debugging session via the
@code{add-inferior} and @w{@code{clone-inferior}} commands. On some
@@ -2832,9 +2838,9 @@ programs:

@itemize @bullet
@item automatic notification of new threads
-@item @samp{thread @var{threadno}}, a command to switch among threads
+@item @samp{thread @var{thread-id}}, a command to switch among threads
@item @samp{info threads}, a command to inquire about existing threads
-@item @samp{thread apply [@var{threadno}] [@var{all}] @var{args}},
+@item @samp{thread apply [@var{thread-id}] [@var{all}] @var{args}},
a command to apply a command to a list of threads
@item thread-specific breakpoints
@item @samp{set print thread-events}, which controls printing of
@@ -2880,10 +2886,34 @@ further qualifier.
@c multithread systems permit starting a program with multiple
@c threads ab initio?

-@cindex thread number
+@anchor{thread numbers}
+@cindex thread number, per inferior
@cindex thread identifier (GDB)
-For debugging purposes, @value{GDBN} associates its own thread
-number---always a single integer---with each thread in your program.
+For debugging purposes, @value{GDBN} associates its own thread number
+---always a single integer---with each thread of an inferior. This
+number is unique between all threads of an inferior, but not unique
+between threads of different inferiors.
+
+You can refer to a given thread in an inferior using the qualified
+@var{inferior-num}.@var{thread-num} syntax, with @var{inferior-num}
+being the inferior number and @var{thread-num} being the thread number
+of the given inferior. For example, thread @code{2.3} refers to
+thread number 3 of inferior 2. If you omit @var{inferior-num}, then
+@value{GDBN} infers you're referring to a thread of the current
+inferior.
+
+Until you create a second inferior, @value{GDBN} does not show the
+@var{inferior-num} part of thread IDs, even though you can always use
+the full @var{inferior-num}.@var{thread-num} form to refer to threads
+of inferior 1, the initial inferior.
+
+@anchor{global thread numbers}
+@cindex global thread number
+@cindex global thread identifier (GDB)
+In addition to a @emph{per-inferior} number, each thread is also
+assigned a unique @emph{global} number, also a single integer. Unlike
+the thread number component of the thread ID, no two threads have the
+same global ID, even when you're debugging multiple inferiors.

From @value{GDBN}'s perspective, a process always has at least one
thread. In other words, @value{GDBN} assigns a thread number to the
@@ -2899,7 +2929,11 @@ means to print information only about the specified thread or threads.

@enumerate
@item
-the thread number assigned by @value{GDBN}
+the per-inferior thread number assigned by @value{GDBN}
+
+@item
+the global thread number assigned by @value{GDBN}, if the @samp{-gid}
+option was specified.

@item
the target system's thread identifier (@var{systag})
@@ -2930,6 +2964,21 @@ For example,
at threadtest.c:68
@end smallexample

+If you're debugging multiple inferiors, @value{GDBN} displays thread
+IDs using an expanded @var{inferior-num}.@var{thread-num} format.
+
+If you specify the @samp{-gid} option, @value{GDBN} displays a column
+indicating each thread's global thread ID:
+
+@smallexample
+(@value{GDBP}) info threads
+ Id GId Target Id Frame
+ 1.1 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8)
+ 1.2 3 process 35 thread 23 0x34e5 in sigpause ()
+ 1.3 4 process 35 thread 27 0x34e5 in sigpause ()
+* 2.1 2 process 65 thread 1 main (argc=1, argv=0x7ffffff8)
+@end smallexample
+
On Solaris, you can display more information about user threads with a
Solaris-specific command:

@@ -2941,13 +2990,13 @@ Display info on Solaris user threads.
@end table

@table @code
-@kindex thread @var{threadno}
-@item thread @var{threadno}
-Make thread number @var{threadno} the current thread. The command
-argument @var{threadno} is the internal @value{GDBN} thread number, as
+@kindex thread @var{thread-id}
+@item thread @var{thread-id}
+Make thread ID @var{thread-id} the current thread. The command
+argument @var{thread-id} is the internal @value{GDBN} thread ID, as
shown in the first field of the @samp{info threads} display.
-@value{GDBN} responds by displaying the system identifier of the thread
-you selected, and its current stack frame summary:
+@value{GDBN} responds by displaying the system identifier of the
+thread you selected, and its current stack frame summary:

@smallexample
(@value{GDBP}) thread 2
@@ -2962,24 +3011,33 @@ As with the @samp{[New @dots{}]} message, the form of the text after
threads.

@vindex $_thread@r{, convenience variable}
-The debugger convenience variable @samp{$_thread} contains the number
-of the current thread. You may find this useful in writing breakpoint
-conditional expressions, command scripts, and so forth. See
-@xref{Convenience Vars,, Convenience Variables}, for general
-information on convenience variables.
+The debugger convenience variable @samp{$_thread} contains the
+per-inferior thread number of the current thread. You may find this
+useful in writing breakpoint conditional expressions, command scripts,
+and so forth. @xref{Convenience Vars,, Convenience Variables}, for
+general information on convenience variables.
+
+@vindex $_gthread@r{, convenience variable}
+The debugger convenience variable @samp{$_gthread} contains the global
+number of the current thread, independent of the thread's containing
+inferior. You may find this useful in writing breakpoint conditional
+expressions, command scripts, and so forth. See @xref{Convenience
+Vars,, Convenience Variables}, for general information on convenience
+variables.

@kindex thread apply
@cindex apply command to several threads
-@item thread apply [@var{threadno} | all [-ascending]] @var{command}
+@item thread apply [@var{thread-id} | all [-ascending]] @var{command}
The @code{thread apply} command allows you to apply the named
@var{command} to one or more threads. Specify the numbers of the
threads that you want affected with the command argument
-@var{threadno}. It can be a single thread number, one of the numbers
-shown in the first field of the @samp{info threads} display; or it
-could be a range of thread numbers, as in @code{2-4}. To apply
-a command to all threads in descending order, type @kbd{thread apply all
-@var{command}}. To apply a command to all threads in ascending order,
-type @kbd{thread apply all -ascending @var{command}}.
+@var{thread-id}. It can be a single thread ID, as shown in the first
+field of the @samp{info threads} display, with or without an inferior
+qualifier (e.g., @samp{2.1} or @samp{1}); or it could be a range of
+thread numbers, as in @code{2-4}. To apply a command to all threads
+in descending order, type @kbd{thread apply all @var{command}}. To
+apply a command to all threads in ascending order, type @kbd{thread
+apply all -ascending @var{command}}.

@kindex thread name
@@ -6041,25 +6099,25 @@ breakpoints on all threads, or on a particular thread.
@table @code
@cindex breakpoints and threads
@cindex thread breakpoints
-@kindex break @dots{} thread @var{threadno}
-@item break @var{location} thread @var{threadno}
-@itemx break @var{location} thread @var{threadno} if @dots{}
+@kindex break @dots{} thread @var{thread-id}
+@item break @var{location} thread @var{thread-id}
+@itemx break @var{location} thread @var{thread-id} if @dots{}
@var{location} specifies source lines; there are several ways of
writing them (@pxref{Specify Location}), but the effect is always to
specify some source line.

-Use the qualifier @samp{thread @var{threadno}} with a breakpoint command
+Use the qualifier @samp{thread @var{thread-id}} with a breakpoint command
to specify that you only want @value{GDBN} to stop the program when a
-particular thread reaches this breakpoint. The @var{threadno} specifier
-is one of the numeric thread identifiers assigned by @value{GDBN}, shown
+particular thread reaches this breakpoint. The @var{thread-id} specifier
+is one of the thread identifiers assigned by @value{GDBN}, shown
in the first column of the @samp{info threads} display.

-If you do not specify @samp{thread @var{threadno}} when you set a
+If you do not specify @samp{thread @var{thread-id}} when you set a
breakpoint, the breakpoint applies to @emph{all} threads of your
program.

You can use the @code{thread} qualifier on conditional breakpoints as
-well; in this case, place @samp{thread @var{threadno}} before or
+well; in this case, place @samp{thread @var{thread-id}} before or
after the breakpoint condition, like this:

@smallexample
@@ -10378,6 +10436,16 @@ gdbserver that supports the @code{qGetTIBAddr} request.
@xref{General Query Packets}.
This variable contains the address of the thread information block.

+@item $_inferior
+The number of the current inferior. @xref{Inferiors and
+Programs, ,Debugging Multiple Inferiors and Programs}.
+
+@item $_thread
+The thread number of the current thread. @xref{thread numbers}.
+
+@item $_gthread
+The global number of the current thread. @xref{global thread numbers}.
+
@end table

@node Convenience Funs
@@ -16120,7 +16188,7 @@ This command prints the ID of the current task.

@item task @var{taskno}
@cindex Ada task switching
-This command is like the @code{thread @var{threadno}}
+This command is like the @code{thread @var{thread-id}}
command (@pxref{Threads}). It switches the context of debugging
from the current task to the given task.

@@ -25357,8 +25425,8 @@ increases the risk that by relying on implicitly selected thread, the
frontend may be operating on a wrong one. Therefore, each MI command
should explicitly specify which thread and frame to operate on. To
make it possible, each MI command accepts the @samp{--thread} and
-@samp{--frame} options, the value to each is @value{GDBN} identifier
-for thread and frame to operate on.
+@samp{--frame} options, the value to each is @value{GDBN} global
+identifier for thread and frame to operate on.

Usually, each top-level window in a frontend allows the user to select
a thread and a frame, and remembers the user selection for further
@@ -25911,15 +25979,16 @@ The following is the list of possible async records:
@table @code

@item *running,thread-id="@var{thread}"
-The target is now running. The @var{thread} field tells which
-specific thread is now running, and can be @samp{all} if all threads
-are running. The frontend should assume that no interaction with a
-running thread is possible after this notification is produced.
-The frontend should not assume that this notification is output
-only once for any command. @value{GDBN} may emit this notification
-several times, either for different threads, because it cannot resume
-all threads together, or even for a single thread, if the thread must
-be stepped though some code before letting it run freely.
+The target is now running. The @var{thread} field can be the global
+thread ID of the the thread that is now running, and it can be
+@samp{all} if all threads are running. The frontend should assume
+that no interaction with a running thread is possible after this
+notification is produced. The frontend should not assume that this
+notification is output only once for any command. @value{GDBN} may
+emit this notification several times, either for different threads,
+because it cannot resume all threads together, or even for a single
+thread, if the thread must be stepped though some code before letting
+it run freely.

@item *stopped,reason="@var{reason}",thread-id="@var{id}",stopped-threads="@var{stopped}",core="@var{core}"
The target has stopped. The @var{reason} field can have one of the
@@ -25973,8 +26042,9 @@ The inferior called @code{exec}. This is reported when @code{catch exec}
(@pxref{Set Catchpoints}) has been used.
@end table

-The @var{id} field identifies the thread that directly caused the stop
--- for example by hitting a breakpoint. Depending on whether all-stop
+The @var{id} field identifies the global thread ID of the thread
+that directly caused the stop -- for example by hitting a breakpoint.
+Depending on whether all-stop
mode is in effect (@pxref{All-Stop Mode}), @value{GDBN} may either
stop all threads, or only the thread that directly triggered the stop.
If all threads are stopped, the @var{stopped} field will have the
@@ -26010,7 +26080,7 @@ only when the inferior exited with some code.
@item =thread-created,id="@var{id}",group-id="@var{gid}"
@itemx =thread-exited,id="@var{id}",group-id="@var{gid}"
A thread either was created, or has exited. The @var{id} field
-contains the @value{GDBN} identifier of the thread. The @var{gid}
+contains the global @value{GDBN} identifier of the thread. The @var{gid}
field identifies the thread group this thread belongs to.

@item =thread-selected,id="@var{id}"
@@ -26271,7 +26341,7 @@ uses a tuple with the following fields:

@table @code
@item id
-The numeric id assigned to the thread by @value{GDBN}. This field is
+The global numeric id assigned to the thread by @value{GDBN}. This field is
always present.

@item target-id
@@ -26744,7 +26814,8 @@ Make the breakpoint conditional on @var{condition}.
@item -i @var{ignore-count}
Initialize the @var{ignore-count}.
@item -p @var{thread-id}
-Restrict the breakpoint to the specified @var{thread-id}.
+Restrict the breakpoint to the thread with the specified global
+@var{thread-id}.
@end table

@subsubheading Result
@@ -26834,7 +26905,8 @@ Make the breakpoint conditional on @var{condition}.
Set the ignore count of the breakpoint (@pxref{Conditions, ignore count})
to @var{ignore-count}.
@item -p @var{thread-id}
-Restrict the breakpoint to the specified @var{thread-id}.
+Restrict the breakpoint to the thread with the specified global
+@var{thread-id}.
@end table

@subsubheading Result
@@ -27484,10 +27556,11 @@ The corresponding @value{GDBN} command is @samp{pwd}.
-thread-info [ @var{thread-id} ]
@end smallexample

-Reports information about either a specific thread, if
-the @var{thread-id} parameter is present, or about all
-threads. When printing information about all threads,
-also reports the current thread.
+Reports information about either a specific thread, if the
+@var{thread-id} parameter is present, or about all threads.
+@var{thread-id} is the thread's global thread ID. When printing
+information about all threads, also reports the global ID of the
+current thread.

@subsubheading @value{GDBN} Command

@@ -27504,7 +27577,7 @@ defined for a given thread:
This field exists only for the current thread. It has the value @samp{*}.

@item id
-The identifier that @value{GDBN} uses to refer to the thread.
+The global identifier that @value{GDBN} uses to refer to the thread.

@item target-id
The identifier that the target uses to refer to the thread.
@@ -27570,8 +27643,9 @@ current-thread-id="1"
-thread-list-ids
@end smallexample

-Produces a list of the currently known @value{GDBN} thread ids. At the
-end of the list it also prints the total number of such threads.
+Produces a list of the currently known global @value{GDBN} thread ids.
+At the end of the list it also prints the total number of such
+threads.

This command is retained for historical reasons, the
@code{-thread-info} command should be used instead.
@@ -27600,8 +27674,9 @@ current-thread-id="1",number-of-threads="3"
-thread-select @var{threadnum}
@end smallexample

-Make @var{threadnum} the current thread. It prints the number of the new
-current thread, and the topmost frame for that thread.
+Make thread with global thread num @var{threadnum} the current thread.
+It prints the number of the new current thread, and the topmost frame
+for that thread.

This command is deprecated in favor of explicitly using the
@samp{--thread} option to each command.
@@ -27670,7 +27745,8 @@ The identifier that @value{GDBN} uses to refer to the Ada task.
The identifier that the target uses to refer to the Ada task.

@item thread-id
-The identifier of the thread corresponding to the Ada task.
+The global thread identifier of the thread corresponding to the Ada
+task.

This field should always exist, as Ada tasks are always implemented
on top of a thread. But if @value{GDBN} cannot find this corresponding
@@ -28886,7 +28962,7 @@ would be printed by the @value{GDBN} CLI. If @samp{print object}

@item thread-id
If a variable object is bound to a specific thread, then this is the
-thread's identifier.
+thread's global identifier.

@item has_more
For a dynamic varobj, this indicates whether there appear to be any
@@ -29067,8 +29143,8 @@ The type of the child. If @samp{print object}
If values were requested, this is the value.

@item thread-id
-If this variable object is associated with a thread, this is the thread id.
-Otherwise this result is not present.
+If this variable object is associated with a thread, this is the
+thread's global thread id. Otherwise this result is not present.

@item frozen
If the variable object is frozen, this variable will be present with a value of 1.