Skip to content

Commit 03d745b

Browse files
rtla/timerlat: Add -A/--aligned CLI option
Add a new option, -A/--aligned, that enables timerlat thread alignment implemented on the kernel-side in commit 4245bf4 ("tracing/osnoise: Add option to align tlat threads"). The option takes an argument, representing alignment between timerlat threads in microseconds. The feature is modeled after the option of the same name in the cyclictest tool. Link: https://lore.kernel.org/r/20260527144928.2944472-1-tglozar@redhat.com Signed-off-by: Tomas Glozar <tglozar@redhat.com>
1 parent 596a9be commit 03d745b

7 files changed

Lines changed: 202 additions & 0 deletions

File tree

tools/tracing/rtla/src/cli.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ struct common_params *timerlat_top_parse_args(int argc, char **argv)
248248
RTLA_OPT_USER_THREADS,
249249
RTLA_OPT_KERNEL_THREADS,
250250
RTLA_OPT_USER_LOAD,
251+
TIMERLAT_OPT_ALIGNED,
251252

252253
OPT_GROUP("Output:"),
253254
TIMERLAT_OPT_NANO,
@@ -362,6 +363,7 @@ struct common_params *timerlat_hist_parse_args(int argc, char **argv)
362363
RTLA_OPT_USER_THREADS,
363364
RTLA_OPT_KERNEL_THREADS,
364365
RTLA_OPT_USER_LOAD,
366+
TIMERLAT_OPT_ALIGNED,
365367

366368
OPT_GROUP("Histogram Options:"),
367369
HIST_OPT_BUCKET_SIZE,

tools/tracing/rtla/src/cli_p.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,10 @@ static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int
447447
"set the stack format (truncate, skip, full)", \
448448
opt_stack_format_cb)
449449

450+
#define TIMERLAT_OPT_ALIGNED OPT_CALLBACK('A', "aligned", params, "us", \
451+
"align thread wakeups to a specific offset", \
452+
opt_timerlat_align_cb)
453+
450454
/*
451455
* Callback functions for command line options for timerlat tools
452456
*/
@@ -608,6 +612,19 @@ static int opt_stack_format_cb(const struct option *opt, const char *arg, int un
608612
return 0;
609613
}
610614

615+
static int opt_timerlat_align_cb(const struct option *opt, const char *arg, int unset)
616+
{
617+
struct timerlat_params *params = opt->value;
618+
619+
if (unset || !arg)
620+
return -1;
621+
622+
params->timerlat_align = true;
623+
params->timerlat_align_us = get_llong_from_str((char *)arg);
624+
625+
return 0;
626+
}
627+
611628
/*
612629
* Macros for command line options specific to histogram-based tools
613630
*/

tools/tracing/rtla/src/common.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ struct osnoise_context {
5151
/* -1 as init value because 0 is off */
5252
int orig_opt_workload;
5353
int opt_workload;
54+
55+
/* -1 as init value because 0 is off */
56+
int orig_opt_timerlat_align;
57+
int opt_timerlat_align;
58+
59+
/* 0 as init value */
60+
unsigned long long orig_timerlat_align_us;
61+
unsigned long long timerlat_align_us;
5462
};
5563

5664
extern volatile int stop_tracing;

tools/tracing/rtla/src/osnoise.c

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,86 @@ void osnoise_put_timerlat_period_us(struct osnoise_context *context)
423423
context->orig_timerlat_period_us = OSNOISE_TIME_INIT_VAL;
424424
}
425425

426+
/*
427+
* osnoise_get_timerlat_align_us - read and save the original "timerlat_align_us"
428+
*/
429+
static long long
430+
osnoise_get_timerlat_align_us(struct osnoise_context *context)
431+
{
432+
long long timerlat_align_us;
433+
434+
if (context->timerlat_align_us != OSNOISE_OPTION_INIT_VAL)
435+
return context->timerlat_align_us;
436+
437+
if (context->orig_timerlat_align_us != OSNOISE_OPTION_INIT_VAL)
438+
return context->orig_timerlat_align_us;
439+
440+
timerlat_align_us = osnoise_read_ll_config("osnoise/timerlat_align_us");
441+
if (timerlat_align_us < 0)
442+
goto out_err;
443+
444+
context->orig_timerlat_align_us = timerlat_align_us;
445+
return timerlat_align_us;
446+
447+
out_err:
448+
return OSNOISE_OPTION_INIT_VAL;
449+
}
450+
451+
/*
452+
* osnoise_set_timerlat_align_us - set "timerlat_align_us"
453+
*/
454+
int osnoise_set_timerlat_align_us(struct osnoise_context *context, long long timerlat_align_us)
455+
{
456+
long long curr_timerlat_align_us = osnoise_get_timerlat_align_us(context);
457+
int retval;
458+
459+
if (curr_timerlat_align_us == OSNOISE_OPTION_INIT_VAL)
460+
return -1;
461+
462+
retval = osnoise_write_ll_config("osnoise/timerlat_align_us", timerlat_align_us);
463+
if (retval < 0)
464+
return -1;
465+
466+
context->timerlat_align_us = timerlat_align_us;
467+
468+
return 0;
469+
}
470+
471+
/*
472+
* osnoise_restore_timerlat_align_us - restore "timerlat_align_us"
473+
*/
474+
void osnoise_restore_timerlat_align_us(struct osnoise_context *context)
475+
{
476+
int retval;
477+
478+
if (context->orig_timerlat_align_us == OSNOISE_OPTION_INIT_VAL)
479+
return;
480+
481+
if (context->orig_timerlat_align_us == context->timerlat_align_us)
482+
goto out_done;
483+
484+
retval = osnoise_write_ll_config("osnoise/timerlat_align_us",
485+
context->orig_timerlat_align_us);
486+
if (retval < 0)
487+
err_msg("Could not restore original osnoise timerlat_align_us\n");
488+
489+
out_done:
490+
context->timerlat_align_us = OSNOISE_OPTION_INIT_VAL;
491+
}
492+
493+
/*
494+
* osnoise_put_timerlat_align_us - restore original values and cleanup data
495+
*/
496+
void osnoise_put_timerlat_align_us(struct osnoise_context *context)
497+
{
498+
osnoise_restore_timerlat_align_us(context);
499+
500+
if (context->orig_timerlat_align_us == OSNOISE_OPTION_INIT_VAL)
501+
return;
502+
503+
context->orig_timerlat_align_us = OSNOISE_OPTION_INIT_VAL;
504+
}
505+
426506
/*
427507
* osnoise_get_stop_us - read and save the original "stop_tracing_us"
428508
*/
@@ -908,6 +988,67 @@ static void osnoise_put_workload(struct osnoise_context *context)
908988
context->orig_opt_workload = OSNOISE_OPTION_INIT_VAL;
909989
}
910990

991+
static int osnoise_get_timerlat_align(struct osnoise_context *context)
992+
{
993+
if (context->opt_timerlat_align != OSNOISE_OPTION_INIT_VAL)
994+
return context->opt_timerlat_align;
995+
996+
if (context->orig_opt_timerlat_align != OSNOISE_OPTION_INIT_VAL)
997+
return context->orig_opt_timerlat_align;
998+
999+
context->orig_opt_timerlat_align = osnoise_options_get_option("TIMERLAT_ALIGN");
1000+
1001+
return context->orig_opt_timerlat_align;
1002+
}
1003+
1004+
int osnoise_set_timerlat_align(struct osnoise_context *context, bool onoff)
1005+
{
1006+
int opt_timerlat_align = osnoise_get_timerlat_align(context);
1007+
int retval;
1008+
1009+
if (opt_timerlat_align == OSNOISE_OPTION_INIT_VAL)
1010+
return -1;
1011+
1012+
if (opt_timerlat_align == onoff)
1013+
return 0;
1014+
1015+
retval = osnoise_options_set_option("TIMERLAT_ALIGN", onoff);
1016+
if (retval < 0)
1017+
return -2;
1018+
1019+
context->opt_timerlat_align = onoff;
1020+
1021+
return 0;
1022+
}
1023+
1024+
static void osnoise_restore_timerlat_align(struct osnoise_context *context)
1025+
{
1026+
int retval;
1027+
1028+
if (context->orig_opt_timerlat_align == OSNOISE_OPTION_INIT_VAL)
1029+
return;
1030+
1031+
if (context->orig_opt_timerlat_align == context->opt_timerlat_align)
1032+
goto out_done;
1033+
1034+
retval = osnoise_options_set_option("TIMERLAT_ALIGN", context->orig_opt_timerlat_align);
1035+
if (retval < 0)
1036+
err_msg("Could not restore original TIMERLAT_ALIGN option\n");
1037+
1038+
out_done:
1039+
context->orig_opt_timerlat_align = OSNOISE_OPTION_INIT_VAL;
1040+
}
1041+
1042+
static void osnoise_put_timerlat_align(struct osnoise_context *context)
1043+
{
1044+
osnoise_restore_timerlat_align(context);
1045+
1046+
if (context->orig_opt_timerlat_align == OSNOISE_OPTION_INIT_VAL)
1047+
return;
1048+
1049+
context->orig_opt_timerlat_align = OSNOISE_OPTION_INIT_VAL;
1050+
}
1051+
9111052
enum {
9121053
FLAG_CONTEXT_NEWLY_CREATED = (1 << 0),
9131054
FLAG_CONTEXT_DELETED = (1 << 1),
@@ -960,6 +1101,12 @@ struct osnoise_context *osnoise_context_alloc(void)
9601101
context->orig_opt_workload = OSNOISE_OPTION_INIT_VAL;
9611102
context->opt_workload = OSNOISE_OPTION_INIT_VAL;
9621103

1104+
context->orig_opt_timerlat_align = OSNOISE_OPTION_INIT_VAL;
1105+
context->opt_timerlat_align = OSNOISE_OPTION_INIT_VAL;
1106+
1107+
context->orig_timerlat_align_us = OSNOISE_OPTION_INIT_VAL;
1108+
context->timerlat_align_us = OSNOISE_OPTION_INIT_VAL;
1109+
9631110
osnoise_get_context(context);
9641111

9651112
return context;
@@ -988,6 +1135,8 @@ void osnoise_put_context(struct osnoise_context *context)
9881135
osnoise_put_tracing_thresh(context);
9891136
osnoise_put_irq_disable(context);
9901137
osnoise_put_workload(context);
1138+
osnoise_put_timerlat_align(context);
1139+
osnoise_put_timerlat_align_us(context);
9911140

9921141
free(context);
9931142
}

tools/tracing/rtla/src/osnoise.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ void osnoise_restore_print_stack(struct osnoise_context *context);
4949
int osnoise_set_print_stack(struct osnoise_context *context,
5050
long long print_stack);
5151

52+
int osnoise_set_timerlat_align_us(struct osnoise_context *context,
53+
long long timerlat_align_us);
54+
void osnoise_restore_timerlat_align_us(struct osnoise_context *context);
55+
56+
int osnoise_set_timerlat_align(struct osnoise_context *context, bool onoff);
57+
5258
int osnoise_set_irq_disable(struct osnoise_context *context, bool onoff);
5359
void osnoise_report_missed_events(struct osnoise_tool *tool);
5460
int osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params);

tools/tracing/rtla/src/timerlat.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,24 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
7777
goto out_err;
7878
}
7979

80+
retval = osnoise_set_timerlat_align(tool->context, params->timerlat_align);
81+
if (retval && params->timerlat_align) {
82+
/*
83+
* We might be running on a kernel that does not support timerlat align.
84+
* Unless user requested it explicitly, ignore the error.
85+
*/
86+
err_msg("Failed to enable timerlat align\n");
87+
goto out_err;
88+
}
89+
90+
if (params->timerlat_align) {
91+
retval = osnoise_set_timerlat_align_us(tool->context, params->timerlat_align_us);
92+
if (retval) {
93+
err_msg("Failed to set timerlat align us\n");
94+
goto out_err;
95+
}
96+
}
97+
8098
/*
8199
* If the user did not specify a type of thread, try user-threads first.
82100
* Fall back to kernel threads otherwise.

tools/tracing/rtla/src/timerlat.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ struct timerlat_params {
3131
enum timerlat_tracing_mode mode;
3232
const char *bpf_action_program;
3333
enum stack_format stack_format;
34+
bool timerlat_align;
35+
unsigned long long timerlat_align_us;
3436
};
3537

3638
#define to_timerlat_params(ptr) container_of(ptr, struct timerlat_params, common)

0 commit comments

Comments
 (0)