binutils-gdb/gdb/tid-parse.h
Pedro Alves 5d5658a1d3 Per-inferior/Inferior-qualified thread IDs
This commit changes GDB to track thread numbers per-inferior.  Then,
if you're debugging multiple inferiors, GDB displays
"inferior-num.thread-num" instead of just "thread-num" whenever it
needs to display a thread:

 (gdb) info inferiors
   Num  Description       Executable
   1    process 6022     /home/pedro/gdb/tests/threads
 * 2    process 6037     /home/pedro/gdb/tests/threads
 (gdb) info threads
   Id   Target Id         Frame
   1.1  Thread 0x7ffff7fc2740 (LWP 6022) "threads" (running)
   1.2  Thread 0x7ffff77c0700 (LWP 6028) "threads" (running)
   1.3  Thread 0x7ffff7fc2740 (LWP 6032) "threads" (running)
   2.1  Thread 0x7ffff7fc1700 (LWP 6037) "threads" (running)
   2.2  Thread 0x7ffff77c0700 (LWP 6038) "threads" (running)
 * 2.3  Thread 0x7ffff7fc2740 (LWP 6039) "threads" (running)
 (gdb)
...
 (gdb) thread 1.1
 [Switching to thread 1.1 (Thread 0x7ffff7fc2740 (LWP 8155))]
 (gdb)
...

etc.

You can still use "thread NUM", in which case GDB infers you're
referring to thread NUM of the current inferior.

The $_thread convenience var and Python's InferiorThread.num attribute
are remapped to the new per-inferior thread number.  It's a backward
compatibility break, but since it only matters when debugging multiple
inferiors, I think it's worth doing.

Because MI thread IDs need to be a single integer, we keep giving
threads a global identifier, _in addition_ to the per-inferior number,
and make MI always refer to the global thread IDs.  IOW, nothing
changes from a MI frontend's perspective.

Similarly, since Python's Breakpoint.thread and Guile's
breakpoint-thread/set-breakpoint-thread breakpoint methods need to
work with integers, those are adjusted to work with global thread IDs
too.  Follow up patches will provide convenient means to access
threads' global IDs.

To avoid potencially confusing users (which also avoids updating much
of the testsuite), if there's only one inferior and its ID is "1",
IOW, the user hasn't done anything multi-process/inferior related,
then the "INF." part of thread IDs is not shown.  E.g,.:

 (gdb) info inferiors
   Num  Description       Executable
 * 1    process 15275     /home/pedro/gdb/tests/threads
 (gdb) info threads
   Id   Target Id         Frame
 * 1    Thread 0x7ffff7fc1740 (LWP 15275) "threads" main () at threads.c:40
 (gdb) add-inferior
 Added inferior 2
 (gdb) info threads
   Id   Target Id         Frame
 * 1.1  Thread 0x7ffff7fc1740 (LWP 15275) "threads" main () at threads.c:40
 (gdb)

No regressions on x86_64 Fedora 20.

gdb/ChangeLog:
2016-01-13  Pedro Alves  <palves@redhat.com>

	* NEWS: Mention that thread IDs are now per inferior and global
	thread IDs.
	* Makefile.in (SFILES): Add tid-parse.c.
	(COMMON_OBS): Add tid-parse.o.
	(HFILES_NO_SRCDIR): Add tid-parse.h.
	* ada-tasks.c: Adjust to use ptid_to_global_thread_id.
	* breakpoint.c (insert_breakpoint_locations)
	(remove_threaded_breakpoints, bpstat_check_breakpoint_conditions)
	(print_one_breakpoint_location, set_longjmp_breakpoint)
	(check_longjmp_breakpoint_for_call_dummy)
	(set_momentary_breakpoint): Adjust to use global IDs.
	(find_condition_and_thread, watch_command_1): Use parse_thread_id.
	(until_break_command, longjmp_bkpt_dtor)
	(breakpoint_re_set_thread, insert_single_step_breakpoint): Adjust
	to use global IDs.
	* dummy-frame.c (pop_dummy_frame_bpt): Adjust to use
	ptid_to_global_thread_id.
	* elfread.c (elf_gnu_ifunc_resolver_stop): Likewise.
	* gdbthread.h (struct thread_info): Rename field 'num' to
	'global_num.  Add new fields 'per_inf_num' and 'inf'.
	(thread_id_to_pid): Rename thread_id_to_pid to
	global_thread_id_to_ptid.
	(pid_to_thread_id): Rename to ...
	(ptid_to_global_thread_id): ... this.
	(valid_thread_id): Rename to ...
	(valid_global_thread_id): ... this.
	(find_thread_id): Rename to ...
	(find_thread_global_id): ... this.
	(ALL_THREADS, ALL_THREADS_BY_INFERIOR): Declare.
	(print_thread_info): Add comment.
	* tid-parse.h: New file.
	* tid-parse.c: New file.
	* infcmd.c (step_command_fsm_prepare)
	(step_command_fsm_should_stop): Adjust to use the global thread
	ID.
	(until_next_command, until_next_command)
	(finish_command_fsm_should_stop): Adjust to use the global thread
	ID.
	(attach_post_wait): Adjust to check the inferior number too.
	* inferior.h (struct inferior) <highest_thread_num>: New field.
	* infrun.c (handle_signal_stop)
	(insert_exception_resume_breakpoint)
	(insert_exception_resume_from_probe): Adjust to use the global
	thread ID.
	* record-btrace.c (record_btrace_open): Use global thread IDs.
	* remote.c (process_initial_stop_replies): Also consider the
	inferior number.
	* target.c (target_pre_inferior): Clear the inferior's highest
	thread num.
	* thread.c (clear_thread_inferior_resources): Adjust to use the
	global thread ID.
	(new_thread): New inferior parameter.  Adjust to use it.  Set both
	the thread's global ID and the thread's per-inferior ID.
	(add_thread_silent): Adjust.
	(find_thread_global_id): New.
	(find_thread_id): Make static.  Adjust to rename.
	(valid_thread_id): Rename to ...
	(valid_global_thread_id): ... this.
	(pid_to_thread_id): Rename to ...
	(ptid_to_global_thread_id): ... this.
	(thread_id_to_pid): Rename to ...
	(global_thread_id_to_ptid): ... this.  Adjust.
	(first_thread_of_process): Adjust.
	(do_captured_list_thread_ids): Adjust to use global thread IDs.
	(should_print_thread): New function.
	(print_thread_info): Rename to ...
	(print_thread_info_1): ... this, and add new show_global_ids
	parameter.  Handle it.  Iterate over inferiors.
	(print_thread_info): Reimplement as wrapper around
	print_thread_info_1.
	(show_inferior_qualified_tids): New function.
	(print_thread_id): Use it.
	(tp_array_compar): Compare inferior numbers too.
	(thread_apply_command): Use tid_range_parser.
	(do_captured_thread_select): Use parse_thread_id.
	(thread_id_make_value): Adjust.
	(_initialize_thread): Adjust "info threads" help string.
	* varobj.c (struct varobj_root): Update comment.
	(varobj_create): Adjust to use global thread IDs.
	(value_of_root_1): Adjust to use global_thread_id_to_ptid.
	* windows-tdep.c (display_tib): No longer accept an argument.
	* cli/cli-utils.c (get_number_trailer): Make extern.
	* cli/cli-utils.h (get_number_trailer): Declare.
	(get_number_const): Adjust documentation.
	* mi/mi-cmd-var.c (mi_cmd_var_update_iter): Adjust to use global
	thread IDs.
	* mi/mi-interp.c (mi_new_thread, mi_thread_exit)
	(mi_on_normal_stop, mi_output_running_pid, mi_on_resume):
	* mi/mi-main.c (mi_execute_command, mi_cmd_execute): Likewise.
	* guile/scm-breakpoint.c (gdbscm_set_breakpoint_thread_x):
	Likewise.
	* python/py-breakpoint.c (bppy_set_thread): Likewise.
	* python/py-finishbreakpoint.c (bpfinishpy_init): Likewise.
	* python/py-infthread.c (thpy_get_num): Add comment and return the
	per-inferior thread ID.
	(thread_object_getset): Update comment of "num".

gdb/testsuite/ChangeLog:
2016-01-07  Pedro Alves  <palves@redhat.com>

	* gdb.base/break.exp: Adjust to output changes.
	* gdb.base/hbreak2.exp: Likewise.
	* gdb.base/sepdebug.exp: Likewise.
	* gdb.base/watch_thread_num.exp: Likewise.
	* gdb.linespec/keywords.exp: Likewise.
	* gdb.multi/info-threads.exp: Likewise.
	* gdb.threads/thread-find.exp: Likewise.
	* gdb.multi/tids.c: New file.
	* gdb.multi/tids.exp: New file.

gdb/doc/ChangeLog:
2016-01-07  Pedro Alves  <palves@redhat.com>

	* gdb.texinfo (Threads): Document per-inferior thread IDs,
	qualified thread IDs, global thread IDs and thread ID lists.
	(Set Watchpoints, Thread-Specific Breakpoints): Adjust to refer to
	thread IDs.
	(Convenience Vars): Document the $_thread convenience variable.
	(Ada Tasks): Adjust to refer to thread IDs.
	(GDB/MI Async Records, GDB/MI Thread Commands, GDB/MI Ada Tasking
	Commands, GDB/MI Variable Objects): Update to mention global
	thread IDs.
	* guile.texi (Breakpoints In Guile)
	<breakpoint-thread/set-breakpoint-thread breakpoint>: Mention
	global thread IDs instead of thread IDs.
	* python.texi (Threads In Python): Adjust documentation of
	InferiorThread.num.
	(Breakpoint.thread): Mention global thread IDs instead of thread
	IDs.
2016-01-13 10:59:43 +00:00

171 lines
6.3 KiB
C

/* TID parsing for GDB, the GNU debugger.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of GDB.
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/>. */
#ifndef TID_PARSE_H
#define TID_PARSE_H
#include "cli/cli-utils.h"
struct thread_info;
/* Issue an invalid thread ID error, pointing at STRING, the invalid
ID. */
extern void ATTRIBUTE_NORETURN invalid_thread_id_error (const char *string);
/* Parse TIDSTR as a per-inferior thread ID, in either INF_NUM.THR_NUM
or THR_NUM form. In the latter case, the missing INF_NUM is filled
in from the current inferior. If ENDPTR is not NULL,
parse_thread_id stores the address of the first character after the
thread ID. Either a valid thread is returned, or an error is
thrown. */
struct thread_info *parse_thread_id (const char *tidstr, const char **end);
/* The possible states of the tid range parser's state machine. */
enum tid_range_state
{
/* Parsing the inferior number. */
TID_RANGE_STATE_INFERIOR,
/* Parsing the thread number or thread number range. */
TID_RANGE_STATE_THREAD_RANGE,
};
/* An object of this type is passed to tid_range_parser_get_tid. It
must be initialized by calling tid_range_parser_init. This type is
defined here so that it can be stack-allocated, but all members
should be treated as opaque. */
struct tid_range_parser
{
/* What sub-component are we expecting. */
enum tid_range_state state;
/* The string being parsed. When parsing has finished, this points
past the last parsed token. */
const char *string;
/* The range parser state when we're parsing the thread number
sub-component. */
struct get_number_or_range_state range_parser;
/* Last inferior number returned. */
int inf_num;
/* True if the TID last parsed was explicitly inferior-qualified.
IOW, whether the spec specified an inferior number
explicitly. */
int qualified;
/* The inferior number to assume if the TID is not qualified. */
int default_inferior;
};
/* Initialize a tid_range_parser for use with
tid_range_parser_get_tid. TIDLIST is the string to be parsed.
DEFAULT_INFERIOR is the inferior number to assume if a
non-qualified thread ID is found. */
extern void tid_range_parser_init (struct tid_range_parser *parser,
const char *tidlist,
int default_inferior);
/* Parse a thread ID or a thread range list.
A range will be of the form
<inferior_num>.<thread_number1>-<thread_number2>
and will represent all the threads of inferior INFERIOR_NUM with
number between THREAD_NUMBER1 and THREAD_NUMBER2, inclusive.
<inferior_num> can also be omitted, as in
<thread_number1>-<thread_number2>
in which case GDB infers the inferior number from the default
passed to the tid_range_parser_init function.
This function is designed to be called iteratively. While
processing a thread ID range list, at each call it will return (in
the INF_NUM and THR_NUM output parameters) the next thread ID in
the range (irrespective of whether the thread actually exists).
At the beginning of parsing a thread range, the char pointer
PARSER->string will be advanced past <thread_number1> and left
pointing at the '-' token. Subsequent calls will not advance the
pointer until the range is completed. The call that completes the
range will advance the pointer past <thread_number2>.
This function advances through the input string for as long you
call it. Once the end of the input string is reached, a call to
tid_range_parser_finished returns false (see below).
E.g., with list: "1.2 3.4-6":
1st call: *INF_NUM=1; *THR_NUM=2 (finished==0)
2nd call: *INF_NUM=3; *THR_NUM=4 (finished==0)
3rd call: *INF_NUM=3; *THR_NUM=5 (finished==0)
4th call: *INF_NUM=3; *THR_NUM=6 (finished==1)
Returns true if parsed a thread/range successfully, false
otherwise. */
extern int tid_range_parser_get_tid (struct tid_range_parser *parser,
int *inf_num, int *thr_num);
/* Like tid_range_parser_get_tid, but return a thread ID range per
call, rather then a single thread ID.
If the next element in the list is a single thread ID, then
*THR_START and *THR_END are set to the same value.
E.g.,. with list: "1.2 3.4-6"
1st call: *INF_NUM=1; *THR_START=2; *THR_END=2 (finished==0)
2nd call: *INF_NUM=3; *THR_START=4; *THR_END=6 (finished==1)
Returns true if parsed a thread/range successfully, false
otherwise. */
extern int tid_range_parser_get_tid_range (struct tid_range_parser *parser,
int *inf_num,
int *thr_start, int *thr_end);
/* Returns non-zero if parsing has completed. */
extern int tid_range_parser_finished (struct tid_range_parser *parser);
/* Return the string being parsed. When parsing has finished, this
points past the last parsed token. */
const char *tid_range_parser_string (struct tid_range_parser *parser);
/* When parsing a range, advance past the final token in the range. */
extern void tid_range_parser_skip (struct tid_range_parser *parser);
/* True if the TID last parsed was explicitly inferior-qualified.
IOW, whether the spec specified an inferior number explicitly. */
extern int tid_range_parser_qualified (struct tid_range_parser *parser);
/* Accept a string-form list of thread IDs such as is accepted by
tid_range_parser_get_tid. Return true if the INF_NUM.THR.NUM
thread is in the list. DEFAULT_INFERIOR is the inferior number to
assume if a non-qualified thread ID is found in the list.
By definition, an empty list includes all threads. This is to be
interpreted as typing a command such as "info threads" with no
arguments. */
extern int tid_is_in_list (const char *list, int default_inferior,
int inf_num, int thr_num);
#endif /* TID_PARSE_H */