Skip to content

Commit 30ff747

Browse files
committed
Add "lane apply" command
This commit adds a "lane apply" command, analogous to "thread apply", but iterates over all lanes of the current wave. E.g.: lane apply 1 2 7 4 backtrace Apply 'backtrace' cmd to lanes 1,2,7,4 lane apply 2-7 9 p foo Apply 'p foo' cmd to lanes 2->7 & 9 lane apply all x/i $lane_pc Apply 'x/i $lane_pc' cmd to all lanes. Note you can use: (gdb) taa lane apply all CMD to apply CMD to all lanes of all threads. Online help shows: (gdb) help lane apply Apply a command to a list of lanes. Usage: lane apply ID... [OPTION]... COMMAND ID is a space-separated list of IDs of lanes to apply COMMAND on. Prints lane number and target system's lane id followed by COMMAND output. By default, an error raised during the execution of COMMAND aborts "lane apply". Options: -q Disables printing the thread or lane information. -c Print any error raised by COMMAND and continue. -s Silently ignore any errors or empty output produced by COMMAND. -all All lanes (active, inactive and unused). -active Only active lanes. -inactive Only inactive lanes. The -q, -c, -s options are shared with "thread apply". The -all,-active,-inactive options are shared with "info lanes". Change-Id: Ifd7d79be4a09daa8d268faf1733bed5cbefacc1c
1 parent 411cd1b commit 30ff747

File tree

3 files changed

+276
-28
lines changed

3 files changed

+276
-28
lines changed

gdb/ada-tasks.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,8 +1583,8 @@ task_apply_all_command (const char *cmd, int from_tty)
15831583

15841584
for (const auto &info : thr_list_cpy)
15851585
if (switch_to_thread_if_alive (info.second.get ()))
1586-
thread_try_catch_cmd (info.second.get (), info.first, cmd,
1587-
from_tty, flags);
1586+
thr_lane_try_catch_cmd (false, info.second.get (), 0, info.first, cmd,
1587+
from_tty, flags);
15881588
}
15891589

15901590
/* Implementation of 'task apply'. */
@@ -1647,8 +1647,8 @@ task_apply_command (const char *tidlist, int from_tty)
16471647

16481648
for (const auto &info : thr_list_cpy)
16491649
if (switch_to_thread_if_alive (info.second.get ()))
1650-
thread_try_catch_cmd (info.second.get (), info.first, cmd,
1651-
from_tty, flags);
1650+
thr_lane_try_catch_cmd (false, info.second.get (), 0, info.first, cmd,
1651+
from_tty, flags);
16521652
}
16531653

16541654
void _initialize_tasks ();

gdb/gdbthread.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,17 +1104,16 @@ extern const char *thread_name (thread_info *thread);
11041104

11051105
extern bool switch_to_thread_if_alive (thread_info *thr);
11061106

1107-
/* Assuming that THR is the current thread, execute CMD.
1108-
If ADA_TASK is not empty, it is the Ada task ID, and will
1109-
be printed instead of the thread information.
1110-
FLAGS.QUIET controls the printing of the thread information.
1107+
/* Switch to lane LANE of thread THR and execute CMD. If ADA_TASK is not
1108+
empty, it is the Ada task ID, and will be printed instead of the thread
1109+
information. FLAGS.QUIET controls the printing of the thread information.
11111110
FLAGS.CONT and FLAGS.SILENT control how to handle errors. Can throw an
11121111
exception if !FLAGS.SILENT and !FLAGS.CONT and CMD fails. */
11131112

1114-
extern void thread_try_catch_cmd (thread_info *thr,
1115-
std::optional<int> ada_task,
1116-
const char *cmd, int from_tty,
1117-
const qcs_flags &flags);
1113+
extern void thr_lane_try_catch_cmd (bool lane_mode, thread_info *thr, int lane,
1114+
std::optional<int> ada_task,
1115+
const char *cmd, int from_tty,
1116+
const qcs_flags &flags);
11181117

11191118
/* Return a string representation of STATE. */
11201119

gdb/thread.c

Lines changed: 265 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,32 +1988,41 @@ tp_array_compar_descending (const thread_info_ref &a, const thread_info_ref &b)
19881988
/* See gdbthread.h. */
19891989

19901990
void
1991-
thread_try_catch_cmd (thread_info *thr, std::optional<int> ada_task,
1992-
const char *cmd, int from_tty,
1993-
const qcs_flags &flags)
1991+
thr_lane_try_catch_cmd (bool lane_mode, thread_info *thr, int lane,
1992+
std::optional<int> ada_task, const char *cmd,
1993+
int from_tty, const qcs_flags &flags)
19941994
{
19951995
gdb_assert (is_current_thread (thr));
19961996

19971997
/* The thread header is computed before running the command since
1998-
the command can change the inferior, which is not permitted
1999-
by thread_target_id_str. */
2000-
std::string thr_header;
2001-
if (ada_task.has_value ())
2002-
thr_header = string_printf (_("\nTask ID %d:\n"), *ada_task);
1998+
the command can change the inferior, which is not permitted by
1999+
thread_target_id_str. */
2000+
std::string header;
2001+
2002+
if (lane_mode)
2003+
header
2004+
= string_printf (_("\nLane %d (%s):\n"), lane,
2005+
target_lane_to_str (thr, lane).c_str ());
2006+
else if (ada_task.has_value ())
2007+
header = string_printf (_("\nTask ID %d:\n"), *ada_task);
20032008
else
2004-
thr_header = string_printf (_("\nThread %s (%s):\n"),
2005-
print_thread_id (thr),
2006-
thread_target_id_str (thr).c_str ());
2009+
header
2010+
= string_printf (_("\nThread %s (%s):\n"), print_thread_id (thr),
2011+
thread_target_id_str (thr).c_str ());
20072012

20082013
try
20092014
{
2015+
/* Switch to the lane on which the command is executed. */
2016+
thr->set_current_simd_lane (lane);
2017+
20102018
std::string cmd_result;
20112019
execute_command_to_string
20122020
(cmd_result, cmd, from_tty, gdb_stdout->term_out ());
2021+
20132022
if (!flags.silent || cmd_result.length () > 0)
20142023
{
20152024
if (!flags.quiet)
2016-
gdb_printf ("%s", thr_header.c_str ());
2025+
gdb_puts (header.c_str ());
20172026
gdb_printf ("%s", cmd_result.c_str ());
20182027
}
20192028
}
@@ -2022,7 +2031,8 @@ thread_try_catch_cmd (thread_info *thr, std::optional<int> ada_task,
20222031
if (!flags.silent)
20232032
{
20242033
if (!flags.quiet)
2025-
gdb_printf ("%s", thr_header.c_str ());
2034+
gdb_puts (header.c_str ());
2035+
20262036
if (flags.cont)
20272037
gdb_printf ("%s\n", ex.what ());
20282038
else
@@ -2049,7 +2059,7 @@ using qcs_flag_option_def
20492059
static const gdb::option::option_def thr_qcs_flags_option_defs[] = {
20502060
qcs_flag_option_def {
20512061
"q", [] (qcs_flags *opt) { return &opt->quiet; },
2052-
N_("Disables printing the thread information."),
2062+
N_("Disables printing the thread or lane information."),
20532063
},
20542064

20552065
qcs_flag_option_def {
@@ -2135,7 +2145,8 @@ thread_apply_all_command (const char *cmd, int from_tty)
21352145

21362146
for (thread_info_ref &thr : thr_list_cpy)
21372147
if (switch_to_thread_if_alive (thr.get ()))
2138-
thread_try_catch_cmd (thr.get (), {}, cmd, from_tty, flags);
2148+
thr_lane_try_catch_cmd (false, thr.get (), 0, {}, cmd, from_tty,
2149+
flags);
21392150
}
21402151
}
21412152

@@ -2297,10 +2308,205 @@ thread_apply_command (const char *tidlist, int from_tty)
22972308
continue;
22982309
}
22992310

2300-
thread_try_catch_cmd (tp, {}, cmd, from_tty, flags);
2311+
thr_lane_try_catch_cmd (false, tp, 0, {}, cmd, from_tty, flags);
2312+
}
2313+
}
2314+
2315+
/* Create an option_def_group for the "lane apply" / "lane apply all"
2316+
options, with FLAGS and IL as context. */
2317+
2318+
static inline std::array<gdb::option::option_def_group, 2>
2319+
make_lane_apply_options_def_group (qcs_flags *flags,
2320+
info_lanes_opts *il)
2321+
{
2322+
return {{
2323+
{ {thr_qcs_flags_option_defs}, flags },
2324+
{ {info_lanes_option_defs}, il },
2325+
}};
2326+
}
2327+
2328+
/* Apply a GDB command to a list of lanes of the current thread. List
2329+
syntax is a whitespace separated list of numbers, or ranges, or the
2330+
keyword `all'. Ranges consist of two numbers separated by a
2331+
hyphen. Examples:
2332+
2333+
lane apply 1 2 7 4 backtrace Apply 'backtrace' cmd to lanes 1,2,7,4
2334+
lane apply 2-7 9 p foo Apply 'p foo' cmd to lanes 2->7 & 9
2335+
lane apply all x/i $lane_pc Apply 'x/i $lane_pc' cmd to all lanes.
2336+
*/
2337+
2338+
static void
2339+
lane_apply_all_command (const char *cmd, int from_tty)
2340+
{
2341+
qcs_flags flags;
2342+
info_lanes_opts il_opts;
2343+
2344+
auto group = make_lane_apply_options_def_group (&flags, &il_opts);
2345+
gdb::option::process_options
2346+
(&cmd, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group);
2347+
2348+
validate_flags_qcs ("lane apply all", &flags);
2349+
2350+
if (cmd == NULL || *cmd == '\000')
2351+
error (_("Please specify a command at the end of 'lane apply all'"));
2352+
2353+
if (inferior_ptid == null_ptid)
2354+
return;
2355+
2356+
thread_info *thr = inferior_thread ();
2357+
scoped_restore_current_simd_lane restore_lane (thr);
2358+
scoped_restore_selected_frame restore_frame;
2359+
2360+
gdbarch *arch = target_thread_architecture (thr->ptid);
2361+
int lane_count = gdbarch_supported_lanes_count (arch, thr);
2362+
int lane_used_count = gdbarch_used_lanes_count (arch, thr);
2363+
2364+
for (int lane = 0; lane < lane_count; ++lane)
2365+
{
2366+
if (!should_print_lane ("", thr, lane, il_opts, lane_used_count))
2367+
continue;
2368+
2369+
frame_info_ptr curr_frame = get_current_frame ();
2370+
select_frame (curr_frame);
2371+
2372+
thr_lane_try_catch_cmd (true, thr, lane, {}, cmd, from_tty, flags);
2373+
}
2374+
}
2375+
2376+
/* Completer for the "lane apply ..." commands. */
2377+
2378+
static void
2379+
lane_apply_completer (completion_tracker &tracker, const char *text)
2380+
{
2381+
const auto group = make_lane_apply_options_def_group (nullptr, nullptr);
2382+
if (gdb::option::complete_options
2383+
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
2384+
return;
2385+
2386+
complete_nested_command_line (tracker, text);
2387+
}
2388+
2389+
/* Completer for "lane apply [ID list]". */
2390+
2391+
static void
2392+
lane_apply_command_completer (cmd_list_element *ignore,
2393+
completion_tracker &tracker,
2394+
const char *text, const char * /*word*/)
2395+
{
2396+
/* Don't leave this to complete_options because there's an early
2397+
return below. */
2398+
tracker.set_use_custom_word_point (true);
2399+
2400+
number_or_range_parser parser (text);
2401+
2402+
try
2403+
{
2404+
while (!parser.finished ())
2405+
{
2406+
/* Call for effect. */
2407+
parser.get_number ();
2408+
2409+
if (parser.in_range ())
2410+
parser.skip_range ();
2411+
}
2412+
}
2413+
catch (const gdb_exception_error &ex)
2414+
{
2415+
/* get_number throws if it parses a negative number, for
2416+
example. But a seemingly negative number may be the start of
2417+
an option instead. */
2418+
}
2419+
2420+
const char *cmd = parser.cur_tok ();
2421+
2422+
if (cmd == text)
2423+
{
2424+
/* No lane ID list yet. */
2425+
return;
23012426
}
2427+
2428+
/* Check if we're past a valid lane ID already. */
2429+
if (parser.finished ()
2430+
&& cmd > text && !isspace (cmd[-1]))
2431+
return;
2432+
2433+
/* We're past the lane ID list, advance word point. */
2434+
tracker.advance_custom_word_point_by (cmd - text);
2435+
text = cmd;
2436+
2437+
lane_apply_completer (tracker, text);
23022438
}
23032439

2440+
/* Completer for "lane apply all". */
2441+
2442+
static void
2443+
lane_apply_all_command_completer (cmd_list_element *ignore,
2444+
completion_tracker &tracker,
2445+
const char *text, const char *word)
2446+
{
2447+
lane_apply_completer (tracker, text);
2448+
}
2449+
2450+
/* Implementation of the "lane apply" command. */
2451+
2452+
static void
2453+
lane_apply_command (const char *id_list, int from_tty)
2454+
{
2455+
qcs_flags flags;
2456+
info_lanes_opts il_opts;
2457+
const char *cmd = nullptr;
2458+
number_or_range_parser parser;
2459+
2460+
if (id_list == nullptr || *id_list == '\000')
2461+
error (_("Please specify a lane ID list"));
2462+
2463+
parser.init (id_list);
2464+
while (!parser.finished ())
2465+
parser.get_number ();
2466+
2467+
cmd = parser.cur_tok ();
2468+
2469+
auto group = make_lane_apply_options_def_group (&flags, &il_opts);
2470+
gdb::option::process_options
2471+
(&cmd, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group);
2472+
2473+
validate_flags_qcs ("lane apply", &flags);
2474+
2475+
if (*cmd == '\0')
2476+
error (_("Please specify a command following the lane ID list"));
2477+
2478+
if (id_list == cmd || isdigit (cmd[0]))
2479+
invalid_thread_id_error (cmd);
2480+
2481+
thread_info *thr = inferior_thread ();
2482+
scoped_restore_current_simd_lane restore_lane (thr);
2483+
scoped_restore_selected_frame restore_frame;
2484+
2485+
gdbarch *arch = target_thread_architecture (thr->ptid);
2486+
int lane_count = gdbarch_supported_lanes_count (arch, thr);
2487+
int lane_used_count = gdbarch_used_lanes_count (arch, thr);
2488+
2489+
parser.init (id_list);
2490+
while (!parser.finished ())
2491+
{
2492+
int lane = parser.get_number ();
2493+
2494+
if (lane >= lane_count)
2495+
{
2496+
/* Be consistent with "thread apply" and warn. */
2497+
warning (_("Lane %d does not exist on this thread."), lane);
2498+
continue;
2499+
}
2500+
2501+
if (!should_print_lane ("", thr, lane, il_opts, lane_used_count))
2502+
continue;
2503+
2504+
frame_info_ptr curr_frame = get_current_frame ();
2505+
select_frame (curr_frame);
2506+
2507+
thr_lane_try_catch_cmd (true, thr, lane, {}, cmd, from_tty, flags);
2508+
}
2509+
}
23042510

23052511
/* Implementation of the "taas" command. */
23062512

@@ -2779,6 +2985,7 @@ void
27792985
_initialize_thread ()
27802986
{
27812987
static struct cmd_list_element *thread_apply_list = NULL;
2988+
static struct cmd_list_element *lane_apply_list = NULL;
27822989
cmd_list_element *c;
27832990

27842991
const auto info_threads_opts = make_info_threads_options_def_group (nullptr);
@@ -2871,6 +3078,48 @@ THREAD_APPLY_OPTION_HELP),
28713078
&thread_apply_list);
28723079
set_cmd_completer_handle_brkchars (c, thread_apply_all_command_completer);
28733080

3081+
/* lane apply ... commands. */
3082+
{
3083+
#define LANE_APPLY_OPTION_HELP "\
3084+
Prints lane number and target system's lane id\n\
3085+
followed by COMMAND output.\n\
3086+
\n\
3087+
By default, an error raised during the execution of COMMAND\n\
3088+
aborts \"lane apply\".\n\
3089+
\n\
3090+
Options:\n\
3091+
%OPTIONS%"
3092+
3093+
const auto lane_apply_opts = make_lane_apply_options_def_group (nullptr,
3094+
nullptr);
3095+
3096+
static std::string lane_apply_help
3097+
= gdb::option::build_help (_("\
3098+
Apply a command to a list of lanes.\n\
3099+
Usage: lane apply ID... [OPTION]... COMMAND\n\
3100+
ID is a space-separated list of IDs of lanes to apply COMMAND on.\n"
3101+
LANE_APPLY_OPTION_HELP),
3102+
lane_apply_opts);
3103+
3104+
c = add_prefix_cmd ("apply", class_run, lane_apply_command,
3105+
lane_apply_help.c_str (),
3106+
&lane_apply_list, 1, &lane_cmd_list);
3107+
set_cmd_completer_handle_brkchars (c, lane_apply_command_completer);
3108+
3109+
static std::string lane_apply_all_help
3110+
= gdb::option::build_help (_("\
3111+
Apply a command to all lanes.\n\
3112+
\n\
3113+
Usage: lane apply all [OPTION]... COMMAND\n"
3114+
LANE_APPLY_OPTION_HELP),
3115+
lane_apply_opts);
3116+
3117+
c = add_cmd ("all", class_run, lane_apply_all_command,
3118+
lane_apply_all_help.c_str (),
3119+
&lane_apply_list);
3120+
set_cmd_completer_handle_brkchars (c, lane_apply_all_command_completer);
3121+
}
3122+
28743123
c = add_com ("taas", class_run, taas_command, _("\
28753124
Apply a command to all threads (ignoring errors and empty output).\n\
28763125
Usage: taas [OPTION]... COMMAND\n\

0 commit comments

Comments
 (0)