[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250611135644.219127-6-tglozar@redhat.com>
Date: Wed, 11 Jun 2025 15:56:41 +0200
From: Tomas Glozar <tglozar@...hat.com>
To: Steven Rostedt <rostedt@...dmis.org>
Cc: linux-trace-kernel@...r.kernel.org,
linux-kernel@...r.kernel.org,
John Kacur <jkacur@...hat.com>,
Luis Goncalves <lgoncalv@...hat.com>,
Arnaldo Carvalho de Melo <acme@...nel.org>,
Chang Yin <cyin@...hat.com>,
Costa Shulyupin <costa.shul@...hat.com>,
Tomas Glozar <tglozar@...hat.com>
Subject: [PATCH 5/8] rtla/timerlat: Add action on end feature
Implement actions on end next to actions on threshold. A new option,
-N/--on-end is added, parallel to -A/--on-threshold. Instead of being
executed whenever a latency threshold is reached, it is executed at the
end of the measurement.
For example:
$ rtla timerlat hist -d 5s -N trace
will save the trace output at the end.
All actions supported by -A are also supported by -N, except for
continue, which does nothing with -N.
Signed-off-by: Tomas Glozar <tglozar@...hat.com>
---
tools/tracing/rtla/src/timerlat.h | 5 ++-
tools/tracing/rtla/src/timerlat_hist.c | 46 +++++++++++++++++--------
tools/tracing/rtla/src/timerlat_top.c | 47 ++++++++++++++++++--------
3 files changed, 67 insertions(+), 31 deletions(-)
diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
index d1fcf9a97621..bc55ed04fc96 100644
--- a/tools/tracing/rtla/src/timerlat.h
+++ b/tools/tracing/rtla/src/timerlat.h
@@ -48,7 +48,10 @@ struct timerlat_params {
struct sched_attr sched_param;
struct trace_events *events;
enum timerlat_tracing_mode mode;
- struct actions actions;
+
+ struct actions threshold_actions;
+ struct actions end_actions;
+
union {
struct {
/* top only */
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 1feae978344b..1b4d5ddaa676 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -754,6 +754,7 @@ static void timerlat_hist_usage(char *usage)
" -u/--user-threads: use rtla user-space threads instead of kernel-space timerlat threads",
" -k/--kernel-threads: use timerlat kernel-space threads instead of rtla user-space threads",
" -A/--on-threshold <action>: define action to be executed at latency threshold, multiple -A are allowed",
+ " -N/--on-end: define action to be executed at measurement end, multiple -N are allowed"
" -U/--user-load: enable timerlat for user-defined user-space workload",
" --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",
@@ -793,7 +794,8 @@ static struct timerlat_params
if (!params)
exit(1);
- actions_init(¶ms->actions);
+ actions_init(¶ms->threshold_actions);
+ actions_init(¶ms->end_actions);
/* disabled by default */
params->dma_latency = -1;
@@ -822,6 +824,7 @@ static struct timerlat_params
{"house-keeping", required_argument, 0, 'H'},
{"help", no_argument, 0, 'h'},
{"irq", required_argument, 0, 'i'},
+ {"on-end", required_argument, 0, 'N'},
{"nano", no_argument, 0, 'n'},
{"period", required_argument, 0, 'p'},
{"priority", required_argument, 0, 'P'},
@@ -853,7 +856,7 @@ static struct timerlat_params
int option_index = 0;
c = getopt_long(argc, argv,
- "A:a:c:C::b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
+ "A:a:c:C::b:d:e:E:DhH:i:kN:np:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
long_options, &option_index);
/* detect the end of the options. */
@@ -876,7 +879,7 @@ static struct timerlat_params
break;
case 'A':
- retval = actions_parse(¶ms->actions, optarg);
+ retval = actions_parse(¶ms->threshold_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
@@ -946,6 +949,13 @@ static struct timerlat_params
case 'k':
params->kernel_workload = 1;
break;
+ case 'N':
+ retval = actions_parse(¶ms->end_actions, optarg);
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
case 'n':
params->output_divisor = 1;
break;
@@ -1051,7 +1061,7 @@ static struct timerlat_params
}
if (trace_output)
- actions_add_trace_output(¶ms->actions, trace_output);
+ actions_add_trace_output(¶ms->threshold_actions, trace_output);
if (geteuid()) {
err_msg("rtla needs root permission\n");
@@ -1078,7 +1088,8 @@ static struct timerlat_params
* mixed mode
*/
if (params->mode == TRACING_MODE_BPF &&
- (params->actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
+ (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
params->mode = TRACING_MODE_MIXED;
return params;
@@ -1271,13 +1282,15 @@ int timerlat_hist_main(int argc, char *argv[])
}
}
- if (params->actions.present[ACTION_TRACE_OUTPUT]) {
+ if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_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;
+ params->threshold_actions.trace_output_inst = record->trace.inst;
+ params->end_actions.trace_output_inst = record->trace.inst;
if (params->events) {
retval = trace_events_enable(&record->trace, params->events);
@@ -1343,7 +1356,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->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
@@ -1376,14 +1389,14 @@ int timerlat_hist_main(int argc, char *argv[])
}
if (osnoise_trace_is_off(tool, record)) {
- actions_perform(¶ms->actions);
+ actions_perform(¶ms->threshold_actions);
- if (!params->actions.continue_flag)
+ if (!params->threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
@@ -1404,14 +1417,14 @@ int timerlat_hist_main(int argc, char *argv[])
if (!stop_tracing) {
/* Threshold overflow, perform actions on threshold */
- actions_perform(¶ms->actions);
+ actions_perform(¶ms->threshold_actions);
- if (!params->actions.continue_flag)
+ if (!params->threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
@@ -1436,6 +1449,8 @@ int timerlat_hist_main(int argc, char *argv[])
timerlat_print_stats(params, tool);
+ actions_perform(¶ms->end_actions);
+
return_value = PASSED;
if (osnoise_trace_is_off(tool, record) && !stop_tracing) {
@@ -1465,7 +1480,8 @@ int timerlat_hist_main(int argc, char *argv[])
osnoise_destroy_tool(aa);
osnoise_destroy_tool(record);
osnoise_destroy_tool(tool);
- actions_destroy(¶ms->actions);
+ actions_destroy(¶ms->threshold_actions);
+ actions_destroy(¶ms->end_actions);
if (params->mode != TRACING_MODE_TRACEFS)
timerlat_bpf_destroy();
free(params);
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index ff0e6a7c3a1b..f022fbd9435e 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -514,6 +514,7 @@ static void timerlat_top_usage(char *usage)
" -k/--kernel-threads: use timerlat kernel-space threads instead of rtla user-space threads",
" -U/--user-load: enable timerlat for user-defined user-space workload",
" -A/--on-threshold <action>: define action to be executed at latency threshold, multiple -A are allowed",
+ " -N/--on-end: define action to be executed at measurement end, multiple -N are allowed"
" --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",
@@ -552,7 +553,8 @@ static struct timerlat_params
if (!params)
exit(1);
- actions_init(¶ms->actions);
+ actions_init(¶ms->threshold_actions);
+ actions_init(¶ms->end_actions);
/* disabled by default */
params->dma_latency = -1;
@@ -578,6 +580,7 @@ static struct timerlat_params
{"help", no_argument, 0, 'h'},
{"house-keeping", required_argument, 0, 'H'},
{"irq", required_argument, 0, 'i'},
+ {"on-end", required_argument, 0, 'N'},
{"nano", no_argument, 0, 'n'},
{"period", required_argument, 0, 'p'},
{"priority", required_argument, 0, 'P'},
@@ -603,7 +606,7 @@ static struct timerlat_params
/* getopt_long stores the option index here. */
int option_index = 0;
- c = getopt_long(argc, argv, "A:a:c:C::d:De:hH:i:knp:P:qs:t::T:uU0:1:2:345:6:7:",
+ c = getopt_long(argc, argv, "A:a:c:C::d:De:hH:i:kN:np:P:qs:t::T:uU0:1:2:345:6:7:",
long_options, &option_index);
/* detect the end of the options. */
@@ -623,9 +626,10 @@ static struct timerlat_params
/* set trace */
trace_output = "timerlat_trace.txt";
+
break;
case 'A':
- retval = actions_parse(¶ms->actions, optarg);
+ retval = actions_parse(¶ms->threshold_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
@@ -698,6 +702,13 @@ static struct timerlat_params
case 'k':
params->kernel_workload = true;
break;
+ case 'N':
+ retval = actions_parse(¶ms->end_actions, optarg);
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
case 'n':
params->output_divisor = 1;
break;
@@ -788,7 +799,7 @@ static struct timerlat_params
}
if (trace_output)
- actions_add_trace_output(¶ms->actions, trace_output);
+ actions_add_trace_output(¶ms->threshold_actions, trace_output);
if (geteuid()) {
err_msg("rtla needs root permission\n");
@@ -812,7 +823,8 @@ static struct timerlat_params
* mixed mode
*/
if (params->mode == TRACING_MODE_BPF &&
- (params->actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
+ (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
params->mode = TRACING_MODE_MIXED;
return params;
@@ -934,14 +946,14 @@ timerlat_top_main_loop(struct osnoise_tool *top,
timerlat_print_stats(params, top);
if (osnoise_trace_is_off(top, record)) {
- actions_perform(¶ms->actions);
+ actions_perform(¶ms->threshold_actions);
- if (!params->actions.continue_flag)
+ if (!params->threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
@@ -993,14 +1005,14 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
if (wait_retval == 1) {
/* Stopping requested by tracer */
- actions_perform(¶ms->actions);
+ actions_perform(¶ms->threshold_actions);
- if (!params->actions.continue_flag)
+ if (!params->threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
@@ -1128,13 +1140,15 @@ int timerlat_top_main(int argc, char *argv[])
}
}
- if (params->actions.present[ACTION_TRACE_OUTPUT]) {
+ if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_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;
+ params->threshold_actions.trace_output_inst = record->trace.inst;
+ params->end_actions.trace_output_inst = record->trace.inst;
if (params->events) {
retval = trace_events_enable(&record->trace, params->events);
@@ -1201,7 +1215,7 @@ int timerlat_top_main(int argc, char *argv[])
* tracing while enabling other instances. The trace instance is the
* one with most valuable information.
*/
- if (params->actions.present[ACTION_TRACE_OUTPUT])
+ if (record)
trace_instance_start(&record->trace);
if (!params->no_aa)
trace_instance_start(&aa->trace);
@@ -1236,6 +1250,8 @@ int timerlat_top_main(int argc, char *argv[])
timerlat_print_stats(params, top);
+ actions_perform(¶ms->end_actions);
+
return_value = PASSED;
if (osnoise_trace_is_off(top, record) && !stop_tracing) {
@@ -1276,7 +1292,8 @@ int timerlat_top_main(int argc, char *argv[])
osnoise_destroy_tool(aa);
osnoise_destroy_tool(record);
osnoise_destroy_tool(top);
- actions_destroy(¶ms->actions);
+ actions_destroy(¶ms->threshold_actions);
+ actions_destroy(¶ms->end_actions);
if (params->mode != TRACING_MODE_TRACEFS)
timerlat_bpf_destroy();
free(params);
--
2.49.0
Powered by blists - more mailing lists