diff options
| author | Tomas Glozar <tglozar@redhat.com> | 2025-06-26 14:33:58 +0200 |
|---|---|---|
| committer | Steven Rostedt (Google) <rostedt@goodmis.org> | 2025-07-25 16:43:56 -0400 |
| commit | 6ea082b171e00bb68b749426f03d9d7e833e9f51 (patch) | |
| tree | 529cb15d3e632f649138611defbb12f7d8a882f0 /tools/tracing/rtla/src/timerlat_hist.c | |
| parent | 8b6cbcac76af2e6e8ac0330a4aab342d08ca7a5d (diff) | |
rtla/timerlat: Add action on threshold feature
Extend the functionality provided by the -t/--trace option, which
triggers saving the contents of a tracefs buffer after tracing is
stopped, to support implementing arbitrary actions.
A new option, --on-threshold, is added, taking an argument
that further specifies the action. Actions added in this patch are:
- trace[,file=<filename>]: Saves tracefs buffer, optionally taking a
filename.
- signal,num=<sig>,pid=<pid>: Sends signal to process. "parent" might
be specified instead of number to send signal to parent process.
- shell,command=<command>: Execute shell command.
Multiple actions may be specified and will be executed in order,
including multiple actions of the same type. Trace output requested via
-t and -a now adds a trace action to the end of the list.
If an action fails, the following actions are not executed. For
example, this command:
$ rtla timerlat -T 20 --on-threshold trace \
--on-threshold shell,command="grep ipi_send timerlat_trace.txt" \
--on-threshold signal,num=2,pid=parent
will send signal 2 (SIGINT) to parent process, but only if saved trace
contains the text "ipi_send".
This way, the feature can be used for flexible reactions on latency
spikes, and allows combining rtla with other tooling like perf.
Cc: John Kacur <jkacur@redhat.com>
Cc: Luis Goncalves <lgoncalv@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Chang Yin <cyin@redhat.com>
Cc: Costa Shulyupin <costa.shul@redhat.com>
Cc: Crystal Wood <crwood@redhat.com>
Cc: Gabriele Monaco <gmonaco@redhat.com>
Link: https://lore.kernel.org/20250626123405.1496931-3-tglozar@redhat.com
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Diffstat (limited to 'tools/tracing/rtla/src/timerlat_hist.c')
| -rw-r--r-- | tools/tracing/rtla/src/timerlat_hist.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c index 6cf260e8553b..d975d2cd6604 100644 --- a/tools/tracing/rtla/src/timerlat_hist.c +++ b/tools/tracing/rtla/src/timerlat_hist.c @@ -757,6 +757,7 @@ static void timerlat_hist_usage(char *usage) " --warm-up s: let the workload run for s seconds before collecting data", " --trace-buffer-size kB: set the per-cpu trace buffer size in kB", " --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency", + " --on-threshold <action>: define action to be executed at latency threshold, multiple are allowed", NULL, }; @@ -786,11 +787,14 @@ static struct timerlat_params int auto_thresh; int retval; int c; + char *trace_output = NULL; params = calloc(1, sizeof(*params)); if (!params) exit(1); + actions_init(¶ms->actions); + /* disabled by default */ params->dma_latency = -1; @@ -841,6 +845,7 @@ static struct timerlat_params {"warm-up", required_argument, 0, '\2'}, {"trace-buffer-size", required_argument, 0, '\3'}, {"deepest-idle-state", required_argument, 0, '\4'}, + {"on-threshold", required_argument, 0, '\5'}, {0, 0, 0, 0} }; @@ -866,7 +871,7 @@ static struct timerlat_params params->print_stack = auto_thresh; /* set trace */ - params->trace_output = "timerlat_trace.txt"; + trace_output = "timerlat_trace.txt"; break; case 'c': @@ -956,13 +961,13 @@ static struct timerlat_params case 't': if (optarg) { if (optarg[0] == '=') - params->trace_output = &optarg[1]; + trace_output = &optarg[1]; else - params->trace_output = &optarg[0]; + trace_output = &optarg[0]; } else if (optind < argc && argv[optind][0] != '-') - params->trace_output = argv[optind]; + trace_output = argv[optind]; else - params->trace_output = "timerlat_trace.txt"; + trace_output = "timerlat_trace.txt"; break; case 'u': params->user_workload = 1; @@ -1032,11 +1037,21 @@ static struct timerlat_params case '\4': params->deepest_idle_state = get_llong_from_str(optarg); break; + case '\5': + retval = actions_parse(¶ms->actions, optarg); + if (retval) { + err_msg("Invalid action %s\n", optarg); + exit(EXIT_FAILURE); + } + break; default: timerlat_hist_usage("Invalid option"); } } + if (trace_output) + actions_add_trace_output(¶ms->actions, trace_output); + if (geteuid()) { err_msg("rtla needs root permission\n"); exit(EXIT_FAILURE); @@ -1061,7 +1076,8 @@ static struct timerlat_params * If auto-analysis or trace output is enabled, switch from BPF mode to * mixed mode */ - if (params->mode == TRACING_MODE_BPF && params->trace_output && !params->no_aa) + if (params->mode == TRACING_MODE_BPF && + (params->actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa)) params->mode = TRACING_MODE_MIXED; return params; @@ -1254,12 +1270,13 @@ int timerlat_hist_main(int argc, char *argv[]) } } - if (params->trace_output) { + if (params->actions.present[ACTION_TRACE_OUTPUT]) { record = osnoise_init_trace_tool("timerlat"); if (!record) { err_msg("Failed to enable the trace instance\n"); goto out_free; } + params->actions.trace_output_inst = record->trace.inst; if (params->events) { retval = trace_events_enable(&record->trace, params->events); @@ -1325,7 +1342,7 @@ int timerlat_hist_main(int argc, char *argv[]) * tracing while enabling other instances. The trace instance is the * one with most valuable information. */ - if (params->trace_output) + if (params->actions.present[ACTION_TRACE_OUTPUT]) trace_instance_start(&record->trace); if (!params->no_aa) trace_instance_start(&aa->trace); @@ -1395,8 +1412,7 @@ int timerlat_hist_main(int argc, char *argv[]) if (!params->no_aa) timerlat_auto_analysis(params->stop_us, params->stop_total_us); - save_trace_to_file(record ? record->trace.inst : NULL, - params->trace_output); + actions_perform(¶ms->actions); return_value = FAILED; } @@ -1418,6 +1434,7 @@ out_free: osnoise_destroy_tool(aa); osnoise_destroy_tool(record); osnoise_destroy_tool(tool); + actions_destroy(¶ms->actions); if (params->mode != TRACING_MODE_TRACEFS) timerlat_bpf_destroy(); free(params); |