* [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions
@ 2025-09-07 2:23 Crystal Wood
2025-09-07 2:23 ` [PATCH v2 1/7] tools/rtla: Consolidate common parameters into shared structure Crystal Wood
` (8 more replies)
0 siblings, 9 replies; 16+ messages in thread
From: Crystal Wood @ 2025-09-07 2:23 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
Consolidate code between osnoise/timerlat and top/hist for easier
maintenance and less future divergence.
As a consequence, actions work on osnoise as well as timerlat, so
expose it to the user, document it, and test it.
v2: minor changes from Tomas's feedback
v1: https://lore.kernel.org/linux-trace-kernel/20250821035719.137161-1-crwood@redhat.com/T/#t
Costa Shulyupin (1):
tools/rtla: Consolidate common parameters into shared structure
Crystal Wood (6):
tools/rtla: Move top/hist params into common struct
tools/rtla: Create common_apply_config()
tools/rtla: Consolidate code between osnoise/timerlat and hist/top
tools/rtla: Fix -A option name in test comment
tools/rtla: Add test engine support for unexpected output
tools/rtla: Add remaining support for osnoise actions
Documentation/tools/rtla/common_options.rst | 61 ++
.../tools/rtla/common_osnoise_options.rst | 8 +
.../tools/rtla/common_timerlat_options.rst | 74 +-
Documentation/tools/rtla/rtla-hwnoise.rst | 2 +
.../tools/rtla/rtla-osnoise-hist.rst | 2 +
Documentation/tools/rtla/rtla-osnoise-top.rst | 2 +
.../tools/rtla/rtla-timerlat-hist.rst | 2 +
.../tools/rtla/rtla-timerlat-top.rst | 2 +
tools/tracing/rtla/src/Build | 1 +
tools/tracing/rtla/src/actions.c | 8 +-
tools/tracing/rtla/src/actions.h | 2 +-
tools/tracing/rtla/src/common.c | 344 ++++++++++
tools/tracing/rtla/src/common.h | 154 +++++
tools/tracing/rtla/src/osnoise.c | 101 ++-
tools/tracing/rtla/src/osnoise.h | 114 +---
tools/tracing/rtla/src/osnoise_hist.c | 369 ++++------
tools/tracing/rtla/src/osnoise_top.c | 303 +++------
tools/tracing/rtla/src/timerlat.c | 210 ++++--
tools/tracing/rtla/src/timerlat.h | 55 +-
tools/tracing/rtla/src/timerlat_bpf.c | 22 +-
tools/tracing/rtla/src/timerlat_hist.c | 642 +++++-------------
tools/tracing/rtla/src/timerlat_top.c | 568 ++++------------
tools/tracing/rtla/src/trace.h | 3 -
tools/tracing/rtla/tests/engine.sh | 26 +-
tools/tracing/rtla/tests/osnoise.t | 27 +-
tools/tracing/rtla/tests/timerlat.t | 4 +-
26 files changed, 1395 insertions(+), 1711 deletions(-)
create mode 100644 tools/tracing/rtla/src/common.c
create mode 100644 tools/tracing/rtla/src/common.h
--
2.48.1
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 1/7] tools/rtla: Consolidate common parameters into shared structure
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
@ 2025-09-07 2:23 ` Crystal Wood
2025-09-07 2:23 ` [PATCH v2 2/7] tools/rtla: Move top/hist params into common struct Crystal Wood
` (7 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Crystal Wood @ 2025-09-07 2:23 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
From: Costa Shulyupin <costa.shul@redhat.com>
timerlat_params and osnoise_params structures contain 15 identical
fields.
Introduce a new header common.h and define a common_params structure to
consolidate shared fields, reduce code duplication, and enhance
maintainability.
Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
tools/tracing/rtla/src/common.h | 30 +++++++
tools/tracing/rtla/src/osnoise.c | 20 ++---
tools/tracing/rtla/src/osnoise.h | 19 +----
tools/tracing/rtla/src/osnoise_hist.c | 92 ++++++++++----------
tools/tracing/rtla/src/osnoise_top.c | 80 ++++++++---------
tools/tracing/rtla/src/timerlat.c | 24 +++---
tools/tracing/rtla/src/timerlat.h | 18 +---
tools/tracing/rtla/src/timerlat_bpf.c | 4 +-
tools/tracing/rtla/src/timerlat_hist.c | 113 +++++++++++++------------
tools/tracing/rtla/src/timerlat_top.c | 105 +++++++++++------------
10 files changed, 253 insertions(+), 252 deletions(-)
create mode 100644 tools/tracing/rtla/src/common.h
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
new file mode 100644
index 000000000000..0a44cfaa7c0b
--- /dev/null
+++ b/tools/tracing/rtla/src/common.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#pragma once
+
+#include "utils.h"
+
+/*
+ * common_params - Parameters shared between timerlat_params and osnoise_params
+ */
+struct common_params {
+ /* trace configuration */
+ char *cpus;
+ cpu_set_t monitored_cpus;
+ struct trace_events *events;
+ int buffer_size;
+
+ /* Timing parameters */
+ int warmup;
+ long long stop_us;
+ long long stop_total_us;
+ int sleep_time;
+ int duration;
+
+ /* Scheduling parameters */
+ int set_sched;
+ struct sched_attr sched_param;
+ int cgroup;
+ char *cgroup_name;
+ int hk_cpus;
+ cpu_set_t hk_cpu_set;
+};
diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
index 2dc3e4539e99..06ae7437c2c7 100644
--- a/tools/tracing/rtla/src/osnoise.c
+++ b/tools/tracing/rtla/src/osnoise.c
@@ -1127,10 +1127,10 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
{
int retval;
- if (!params->sleep_time)
- params->sleep_time = 1;
+ if (!params->common.sleep_time)
+ params->common.sleep_time = 1;
- retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all");
+ retval = osnoise_set_cpus(tool->context, params->common.cpus ? params->common.cpus : "all");
if (retval) {
err_msg("Failed to apply CPUs config\n");
goto out_err;
@@ -1151,13 +1151,13 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
goto out_err;
}
- retval = osnoise_set_stop_us(tool->context, params->stop_us);
+ retval = osnoise_set_stop_us(tool->context, params->common.stop_us);
if (retval) {
err_msg("Failed to set stop us\n");
goto out_err;
}
- retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us);
+ retval = osnoise_set_stop_total_us(tool->context, params->common.stop_total_us);
if (retval) {
err_msg("Failed to set stop total us\n");
goto out_err;
@@ -1169,14 +1169,14 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
goto out_err;
}
- if (params->hk_cpus) {
- retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set),
- ¶ms->hk_cpu_set);
+ if (params->common.hk_cpus) {
+ retval = sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set),
+ ¶ms->common.hk_cpu_set);
if (retval == -1) {
err_msg("Failed to set rtla to the house keeping CPUs\n");
goto out_err;
}
- } else if (params->cpus) {
+ } else if (params->common.cpus) {
/*
* Even if the user do not set a house-keeping CPU, try to
* move rtla to a CPU set different to the one where the user
@@ -1184,7 +1184,7 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
*
* No need to check results as this is an automatic attempt.
*/
- auto_house_keeping(¶ms->monitored_cpus);
+ auto_house_keeping(¶ms->common.monitored_cpus);
}
retval = osnoise_set_workload(tool->context, true);
diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osnoise.h
index ac1c99910744..0386bb50ffa1 100644
--- a/tools/tracing/rtla/src/osnoise.h
+++ b/tools/tracing/rtla/src/osnoise.h
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#pragma once
-#include "utils.h"
+#include "common.h"
#include "trace.h"
enum osnoise_mode {
@@ -10,26 +10,11 @@ enum osnoise_mode {
};
struct osnoise_params {
- /* Common params */
- char *cpus;
- cpu_set_t monitored_cpus;
+ struct common_params common;
char *trace_output;
- char *cgroup_name;
unsigned long long runtime;
unsigned long long period;
long long threshold;
- long long stop_us;
- long long stop_total_us;
- int sleep_time;
- int duration;
- int set_sched;
- int cgroup;
- int hk_cpus;
- cpu_set_t hk_cpu_set;
- struct sched_attr sched_param;
- struct trace_events *events;
- int warmup;
- int buffer_size;
union {
struct {
/* top only */
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 8d579bcee709..3fb9bb553498 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -243,7 +243,7 @@ static void osnoise_hist_header(struct osnoise_tool *tool)
trace_seq_printf(s, "Index");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -274,7 +274,7 @@ osnoise_print_summary(struct osnoise_params *params,
trace_seq_printf(trace->seq, "count:");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -288,7 +288,7 @@ osnoise_print_summary(struct osnoise_params *params,
trace_seq_printf(trace->seq, "min: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -303,7 +303,7 @@ osnoise_print_summary(struct osnoise_params *params,
trace_seq_printf(trace->seq, "avg: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -321,7 +321,7 @@ osnoise_print_summary(struct osnoise_params *params,
trace_seq_printf(trace->seq, "max: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -357,7 +357,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
bucket * data->bucket_size);
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -395,7 +395,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
trace_seq_printf(trace->seq, "over: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].count)
@@ -537,7 +537,7 @@ static struct osnoise_params
switch (c) {
case 'a':
/* set sample stop to auto_thresh */
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
/* set sample threshold to 1 */
params->threshold = 1;
@@ -552,27 +552,27 @@ static struct osnoise_params
osnoise_hist_usage("Bucket size needs to be > 0 and <= 1000000\n");
break;
case 'c':
- retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
+ retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
if (retval)
osnoise_hist_usage("\nInvalid -c cpu list\n");
- params->cpus = optarg;
+ params->common.cpus = optarg;
break;
case 'C':
- params->cgroup = 1;
+ params->common.cgroup = 1;
if (!optarg) {
/* will inherit this cgroup */
- params->cgroup_name = NULL;
+ params->common.cgroup_name = NULL;
} else if (*optarg == '=') {
/* skip the = */
- params->cgroup_name = ++optarg;
+ params->common.cgroup_name = ++optarg;
}
break;
case 'D':
config_debug = 1;
break;
case 'd':
- params->duration = parse_seconds_duration(optarg);
- if (!params->duration)
+ params->common.duration = parse_seconds_duration(optarg);
+ if (!params->common.duration)
osnoise_hist_usage("Invalid -D duration\n");
break;
case 'e':
@@ -582,10 +582,10 @@ static struct osnoise_params
exit(EXIT_FAILURE);
}
- if (params->events)
- tevent->next = params->events;
+ if (params->common.events)
+ tevent->next = params->common.events;
- params->events = tevent;
+ params->common.events = tevent;
break;
case 'E':
params->entries = get_llong_from_str(optarg);
@@ -597,8 +597,8 @@ static struct osnoise_params
osnoise_hist_usage(NULL);
break;
case 'H':
- params->hk_cpus = 1;
- retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
+ params->common.hk_cpus = 1;
+ retval = parse_cpu_set(optarg, ¶ms->common.hk_cpu_set);
if (retval) {
err_msg("Error parsing house keeping CPUs\n");
exit(EXIT_FAILURE);
@@ -610,10 +610,10 @@ static struct osnoise_params
osnoise_hist_usage("Period longer than 10 s\n");
break;
case 'P':
- retval = parse_prio(optarg, ¶ms->sched_param);
+ retval = parse_prio(optarg, ¶ms->common.sched_param);
if (retval == -1)
osnoise_hist_usage("Invalid -P priority");
- params->set_sched = 1;
+ params->common.set_sched = 1;
break;
case 'r':
params->runtime = get_llong_from_str(optarg);
@@ -621,10 +621,10 @@ static struct osnoise_params
osnoise_hist_usage("Runtime shorter than 100 us\n");
break;
case 's':
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
break;
case 'S':
- params->stop_total_us = get_llong_from_str(optarg);
+ params->common.stop_total_us = get_llong_from_str(optarg);
break;
case 'T':
params->threshold = get_llong_from_str(optarg);
@@ -653,8 +653,8 @@ static struct osnoise_params
params->with_zeros = 1;
break;
case '4': /* trigger */
- if (params->events) {
- retval = trace_event_add_trigger(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_trigger(params->common.events, optarg);
if (retval) {
err_msg("Error adding trigger %s\n", optarg);
exit(EXIT_FAILURE);
@@ -664,8 +664,8 @@ static struct osnoise_params
}
break;
case '5': /* filter */
- if (params->events) {
- retval = trace_event_add_filter(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_filter(params->common.events, optarg);
if (retval) {
err_msg("Error adding filter %s\n", optarg);
exit(EXIT_FAILURE);
@@ -675,10 +675,10 @@ static struct osnoise_params
}
break;
case '6':
- params->warmup = get_llong_from_str(optarg);
+ params->common.warmup = get_llong_from_str(optarg);
break;
case '7':
- params->buffer_size = get_llong_from_str(optarg);
+ params->common.buffer_size = get_llong_from_str(optarg);
break;
default:
osnoise_hist_usage("Invalid option");
@@ -755,9 +755,9 @@ static void
osnoise_hist_set_signals(struct osnoise_params *params)
{
signal(SIGINT, stop_hist);
- if (params->duration) {
+ if (params->common.duration) {
signal(SIGALRM, stop_hist);
- alarm(params->duration);
+ alarm(params->common.duration);
}
}
@@ -798,16 +798,16 @@ int osnoise_hist_main(int argc, char *argv[])
if (retval)
goto out_destroy;
- if (params->set_sched) {
- retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param);
+ if (params->common.set_sched) {
+ retval = set_comm_sched_attr("osnoise/", ¶ms->common.sched_param);
if (retval) {
err_msg("Failed to set sched parameters\n");
goto out_free;
}
}
- if (params->cgroup) {
- retval = set_comm_cgroup("timerlat/", params->cgroup_name);
+ if (params->common.cgroup) {
+ retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
if (!retval) {
err_msg("Failed to move threads to cgroup\n");
goto out_free;
@@ -821,14 +821,14 @@ int osnoise_hist_main(int argc, char *argv[])
goto out_free;
}
- if (params->events) {
- retval = trace_events_enable(&record->trace, params->events);
+ if (params->common.events) {
+ retval = trace_events_enable(&record->trace, params->common.events);
if (retval)
goto out_hist;
}
- if (params->buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->buffer_size);
+ if (params->common.buffer_size > 0) {
+ retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
if (retval)
goto out_hist;
}
@@ -845,9 +845,9 @@ int osnoise_hist_main(int argc, char *argv[])
trace_instance_start(&record->trace);
trace_instance_start(trace);
- if (params->warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->warmup);
- sleep(params->warmup);
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
if (stop_tracing)
goto out_hist;
@@ -868,7 +868,7 @@ int osnoise_hist_main(int argc, char *argv[])
osnoise_hist_set_signals(params);
while (!stop_tracing) {
- sleep(params->sleep_time);
+ sleep(params->common.sleep_time);
retval = tracefs_iterate_raw_events(trace->tep,
trace->inst,
@@ -899,8 +899,8 @@ int osnoise_hist_main(int argc, char *argv[])
}
out_hist:
- trace_events_destroy(&record->trace, params->events);
- params->events = NULL;
+ trace_events_destroy(&record->trace, params->common.events);
+ params->common.events = NULL;
out_free:
osnoise_free_histogram(tool->data);
out_destroy:
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 2c12780c8aa9..ad5daa8210aa 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -238,7 +238,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *top)
osnoise_top_header(top);
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
osnoise_top_print(top, i);
}
@@ -377,7 +377,7 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
switch (c) {
case 'a':
/* set sample stop to auto_thresh */
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
/* set sample threshold to 1 */
params->threshold = 1;
@@ -387,27 +387,27 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
break;
case 'c':
- retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
+ retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
if (retval)
osnoise_top_usage(params, "\nInvalid -c cpu list\n");
- params->cpus = optarg;
+ params->common.cpus = optarg;
break;
case 'C':
- params->cgroup = 1;
+ params->common.cgroup = 1;
if (!optarg) {
/* will inherit this cgroup */
- params->cgroup_name = NULL;
+ params->common.cgroup_name = NULL;
} else if (*optarg == '=') {
/* skip the = */
- params->cgroup_name = ++optarg;
+ params->common.cgroup_name = ++optarg;
}
break;
case 'D':
config_debug = 1;
break;
case 'd':
- params->duration = parse_seconds_duration(optarg);
- if (!params->duration)
+ params->common.duration = parse_seconds_duration(optarg);
+ if (!params->common.duration)
osnoise_top_usage(params, "Invalid -d duration\n");
break;
case 'e':
@@ -417,9 +417,9 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
exit(EXIT_FAILURE);
}
- if (params->events)
- tevent->next = params->events;
- params->events = tevent;
+ if (params->common.events)
+ tevent->next = params->common.events;
+ params->common.events = tevent;
break;
case 'h':
@@ -427,8 +427,8 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
osnoise_top_usage(params, NULL);
break;
case 'H':
- params->hk_cpus = 1;
- retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
+ params->common.hk_cpus = 1;
+ retval = parse_cpu_set(optarg, ¶ms->common.hk_cpu_set);
if (retval) {
err_msg("Error parsing house keeping CPUs\n");
exit(EXIT_FAILURE);
@@ -440,10 +440,10 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
osnoise_top_usage(params, "Period longer than 10 s\n");
break;
case 'P':
- retval = parse_prio(optarg, ¶ms->sched_param);
+ retval = parse_prio(optarg, ¶ms->common.sched_param);
if (retval == -1)
osnoise_top_usage(params, "Invalid -P priority");
- params->set_sched = 1;
+ params->common.set_sched = 1;
break;
case 'q':
params->quiet = 1;
@@ -454,10 +454,10 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
osnoise_top_usage(params, "Runtime shorter than 100 us\n");
break;
case 's':
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
break;
case 'S':
- params->stop_total_us = get_llong_from_str(optarg);
+ params->common.stop_total_us = get_llong_from_str(optarg);
break;
case 't':
if (optarg) {
@@ -474,8 +474,8 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
params->threshold = get_llong_from_str(optarg);
break;
case '0': /* trigger */
- if (params->events) {
- retval = trace_event_add_trigger(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_trigger(params->common.events, optarg);
if (retval) {
err_msg("Error adding trigger %s\n", optarg);
exit(EXIT_FAILURE);
@@ -485,8 +485,8 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
}
break;
case '1': /* filter */
- if (params->events) {
- retval = trace_event_add_filter(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_filter(params->common.events, optarg);
if (retval) {
err_msg("Error adding filter %s\n", optarg);
exit(EXIT_FAILURE);
@@ -496,10 +496,10 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
}
break;
case '2':
- params->warmup = get_llong_from_str(optarg);
+ params->common.warmup = get_llong_from_str(optarg);
break;
case '3':
- params->buffer_size = get_llong_from_str(optarg);
+ params->common.buffer_size = get_llong_from_str(optarg);
break;
default:
osnoise_top_usage(params, "Invalid option");
@@ -583,9 +583,9 @@ static void stop_top(int sig)
static void osnoise_top_set_signals(struct osnoise_params *params)
{
signal(SIGINT, stop_top);
- if (params->duration) {
+ if (params->common.duration) {
signal(SIGALRM, stop_top);
- alarm(params->duration);
+ alarm(params->common.duration);
}
}
@@ -622,16 +622,16 @@ int osnoise_top_main(int argc, char **argv)
goto out_free;
}
- if (params->set_sched) {
- retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param);
+ if (params->common.set_sched) {
+ retval = set_comm_sched_attr("osnoise/", ¶ms->common.sched_param);
if (retval) {
err_msg("Failed to set sched parameters\n");
goto out_free;
}
}
- if (params->cgroup) {
- retval = set_comm_cgroup("osnoise/", params->cgroup_name);
+ if (params->common.cgroup) {
+ retval = set_comm_cgroup("osnoise/", params->common.cgroup_name);
if (!retval) {
err_msg("Failed to move threads to cgroup\n");
goto out_free;
@@ -645,14 +645,14 @@ int osnoise_top_main(int argc, char **argv)
goto out_free;
}
- if (params->events) {
- retval = trace_events_enable(&record->trace, params->events);
+ if (params->common.events) {
+ retval = trace_events_enable(&record->trace, params->common.events);
if (retval)
goto out_top;
}
- if (params->buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->buffer_size);
+ if (params->common.buffer_size > 0) {
+ retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
if (retval)
goto out_top;
}
@@ -669,9 +669,9 @@ int osnoise_top_main(int argc, char **argv)
trace_instance_start(&record->trace);
trace_instance_start(trace);
- if (params->warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->warmup);
- sleep(params->warmup);
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
if (stop_tracing)
goto out_top;
@@ -692,7 +692,7 @@ int osnoise_top_main(int argc, char **argv)
osnoise_top_set_signals(params);
while (!stop_tracing) {
- sleep(params->sleep_time);
+ sleep(params->common.sleep_time);
retval = tracefs_iterate_raw_events(trace->tep,
trace->inst,
@@ -725,8 +725,8 @@ int osnoise_top_main(int argc, char **argv)
}
out_top:
- trace_events_destroy(&record->trace, params->events);
- params->events = NULL;
+ trace_events_destroy(&record->trace, params->common.events);
+ params->common.events = NULL;
out_free:
osnoise_free_top(tool->data);
osnoise_destroy_tool(record);
diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/timerlat.c
index 63d6d43eafff..0b2f03e1e612 100644
--- a/tools/tracing/rtla/src/timerlat.c
+++ b/tools/tracing/rtla/src/timerlat.c
@@ -26,18 +26,18 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
{
int retval, i;
- if (!params->sleep_time)
- params->sleep_time = 1;
+ if (!params->common.sleep_time)
+ params->common.sleep_time = 1;
- retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all");
+ retval = osnoise_set_cpus(tool->context, params->common.cpus ? params->common.cpus : "all");
if (retval) {
err_msg("Failed to apply CPUs config\n");
goto out_err;
}
- if (!params->cpus) {
+ if (!params->common.cpus) {
for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++)
- CPU_SET(i, ¶ms->monitored_cpus);
+ CPU_SET(i, ¶ms->common.monitored_cpus);
}
if (params->mode != TRACING_MODE_BPF) {
@@ -45,13 +45,13 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
* In tracefs and mixed mode, timerlat tracer handles stopping
* on threshold
*/
- retval = osnoise_set_stop_us(tool->context, params->stop_us);
+ retval = osnoise_set_stop_us(tool->context, params->common.stop_us);
if (retval) {
err_msg("Failed to set stop us\n");
goto out_err;
}
- retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us);
+ retval = osnoise_set_stop_total_us(tool->context, params->common.stop_total_us);
if (retval) {
err_msg("Failed to set stop total us\n");
goto out_err;
@@ -75,14 +75,14 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
goto out_err;
}
- if (params->hk_cpus) {
- retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set),
- ¶ms->hk_cpu_set);
+ if (params->common.hk_cpus) {
+ retval = sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set),
+ ¶ms->common.hk_cpu_set);
if (retval == -1) {
err_msg("Failed to set rtla to the house keeping CPUs\n");
goto out_err;
}
- } else if (params->cpus) {
+ } else if (params->common.cpus) {
/*
* Even if the user do not set a house-keeping CPU, try to
* move rtla to a CPU set different to the one where the user
@@ -90,7 +90,7 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
*
* No need to check results as this is an automatic attempt.
*/
- auto_house_keeping(¶ms->monitored_cpus);
+ auto_house_keeping(¶ms->common.monitored_cpus);
}
/*
diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
index bc55ed04fc96..dd9e0f05bdad 100644
--- a/tools/tracing/rtla/src/timerlat.h
+++ b/tools/tracing/rtla/src/timerlat.h
@@ -20,33 +20,17 @@ enum timerlat_tracing_mode {
};
struct timerlat_params {
- /* Common params */
- char *cpus;
- cpu_set_t monitored_cpus;
- char *cgroup_name;
- unsigned long long runtime;
- long long stop_us;
- long long stop_total_us;
+ struct common_params common;
long long timerlat_period_us;
long long print_stack;
- int sleep_time;
int output_divisor;
- int duration;
- int set_sched;
int dma_latency;
int no_aa;
int dump_tasks;
- int cgroup;
- int hk_cpus;
int user_workload;
int kernel_workload;
int user_data;
- int warmup;
- int buffer_size;
int deepest_idle_state;
- cpu_set_t hk_cpu_set;
- struct sched_attr sched_param;
- struct trace_events *events;
enum timerlat_tracing_mode mode;
struct actions threshold_actions;
diff --git a/tools/tracing/rtla/src/timerlat_bpf.c b/tools/tracing/rtla/src/timerlat_bpf.c
index 1666215dd687..a6c77ac55e00 100644
--- a/tools/tracing/rtla/src/timerlat_bpf.c
+++ b/tools/tracing/rtla/src/timerlat_bpf.c
@@ -23,8 +23,8 @@ int timerlat_bpf_init(struct timerlat_params *params)
/* Pass common options */
bpf->rodata->output_divisor = params->output_divisor;
bpf->rodata->entries = params->entries;
- bpf->rodata->irq_threshold = params->stop_us;
- bpf->rodata->thread_threshold = params->stop_total_us;
+ bpf->rodata->irq_threshold = params->common.stop_us;
+ bpf->rodata->thread_threshold = params->common.stop_total_us;
bpf->rodata->aa_only = params->aa_only;
if (params->entries != 0) {
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 9baea1b251ed..a3de644f2b75 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -303,7 +303,7 @@ static void timerlat_hist_header(struct osnoise_tool *tool)
trace_seq_printf(s, "Index");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -357,7 +357,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "count:");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -381,7 +381,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "min: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -411,7 +411,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "avg: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -441,7 +441,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "max: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -488,7 +488,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
sum.min_user = ~0;
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -636,7 +636,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
bucket * data->bucket_size);
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -676,7 +676,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
trace_seq_printf(trace->seq, "over: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
- if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(cpu, ¶ms->common.monitored_cpus))
continue;
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
@@ -867,8 +867,8 @@ static struct timerlat_params
auto_thresh = get_llong_from_str(optarg);
/* set thread stop to auto_thresh */
- params->stop_total_us = auto_thresh;
- params->stop_us = auto_thresh;
+ params->common.stop_total_us = auto_thresh;
+ params->common.stop_us = auto_thresh;
/* get stack trace */
params->print_stack = auto_thresh;
@@ -878,19 +878,19 @@ static struct timerlat_params
break;
case 'c':
- retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
+ retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
if (retval)
timerlat_hist_usage("\nInvalid -c cpu list\n");
- params->cpus = optarg;
+ params->common.cpus = optarg;
break;
case 'C':
- params->cgroup = 1;
+ params->common.cgroup = 1;
if (!optarg) {
/* will inherit this cgroup */
- params->cgroup_name = NULL;
+ params->common.cgroup_name = NULL;
} else if (*optarg == '=') {
/* skip the = */
- params->cgroup_name = ++optarg;
+ params->common.cgroup_name = ++optarg;
}
break;
case 'b':
@@ -902,8 +902,8 @@ static struct timerlat_params
config_debug = 1;
break;
case 'd':
- params->duration = parse_seconds_duration(optarg);
- if (!params->duration)
+ params->common.duration = parse_seconds_duration(optarg);
+ if (!params->common.duration)
timerlat_hist_usage("Invalid -D duration\n");
break;
case 'e':
@@ -913,10 +913,10 @@ static struct timerlat_params
exit(EXIT_FAILURE);
}
- if (params->events)
- tevent->next = params->events;
+ if (params->common.events)
+ tevent->next = params->common.events;
- params->events = tevent;
+ params->common.events = tevent;
break;
case 'E':
params->entries = get_llong_from_str(optarg);
@@ -928,15 +928,15 @@ static struct timerlat_params
timerlat_hist_usage(NULL);
break;
case 'H':
- params->hk_cpus = 1;
- retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
+ params->common.hk_cpus = 1;
+ retval = parse_cpu_set(optarg, ¶ms->common.hk_cpu_set);
if (retval) {
err_msg("Error parsing house keeping CPUs\n");
exit(EXIT_FAILURE);
}
break;
case 'i':
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
break;
case 'k':
params->kernel_workload = 1;
@@ -950,16 +950,16 @@ static struct timerlat_params
timerlat_hist_usage("Period longer than 1 s\n");
break;
case 'P':
- retval = parse_prio(optarg, ¶ms->sched_param);
+ retval = parse_prio(optarg, ¶ms->common.sched_param);
if (retval == -1)
timerlat_hist_usage("Invalid -P priority");
- params->set_sched = 1;
+ params->common.set_sched = 1;
break;
case 's':
params->print_stack = get_llong_from_str(optarg);
break;
case 'T':
- params->stop_total_us = get_llong_from_str(optarg);
+ params->common.stop_total_us = get_llong_from_str(optarg);
break;
case 't':
if (optarg) {
@@ -997,8 +997,8 @@ static struct timerlat_params
params->with_zeros = 1;
break;
case '6': /* trigger */
- if (params->events) {
- retval = trace_event_add_trigger(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_trigger(params->common.events, optarg);
if (retval) {
err_msg("Error adding trigger %s\n", optarg);
exit(EXIT_FAILURE);
@@ -1008,8 +1008,8 @@ static struct timerlat_params
}
break;
case '7': /* filter */
- if (params->events) {
- retval = trace_event_add_filter(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_filter(params->common.events, optarg);
if (retval) {
err_msg("Error adding filter %s\n", optarg);
exit(EXIT_FAILURE);
@@ -1032,10 +1032,10 @@ static struct timerlat_params
params->dump_tasks = 1;
break;
case '\2':
- params->warmup = get_llong_from_str(optarg);
+ params->common.warmup = get_llong_from_str(optarg);
break;
case '\3':
- params->buffer_size = get_llong_from_str(optarg);
+ params->common.buffer_size = get_llong_from_str(optarg);
break;
case '\4':
params->deepest_idle_state = get_llong_from_str(optarg);
@@ -1076,7 +1076,7 @@ static struct timerlat_params
/*
* Auto analysis only happens if stop tracing, thus:
*/
- if (!params->stop_us && !params->stop_total_us)
+ if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
if (params->kernel_workload && params->user_workload)
@@ -1167,9 +1167,9 @@ static void
timerlat_hist_set_signals(struct timerlat_params *params)
{
signal(SIGINT, stop_hist);
- if (params->duration) {
+ if (params->common.duration) {
signal(SIGALRM, stop_hist);
- alarm(params->duration);
+ alarm(params->common.duration);
}
}
@@ -1235,16 +1235,16 @@ int timerlat_hist_main(int argc, char *argv[])
goto out_free;
}
- if (params->set_sched) {
- retval = set_comm_sched_attr("timerlat/", ¶ms->sched_param);
+ if (params->common.set_sched) {
+ retval = set_comm_sched_attr("timerlat/", ¶ms->common.sched_param);
if (retval) {
err_msg("Failed to set sched parameters\n");
goto out_free;
}
}
- if (params->cgroup && !params->user_workload) {
- retval = set_comm_cgroup("timerlat/", params->cgroup_name);
+ if (params->common.cgroup && !params->user_workload) {
+ retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
if (!retval) {
err_msg("Failed to move threads to cgroup\n");
goto out_free;
@@ -1268,7 +1268,7 @@ int timerlat_hist_main(int argc, char *argv[])
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
if (save_cpu_idle_disable_state(i) < 0) {
err_msg("Could not save cpu idle state.\n");
@@ -1291,14 +1291,14 @@ int timerlat_hist_main(int argc, char *argv[])
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);
+ if (params->common.events) {
+ retval = trace_events_enable(&record->trace, params->common.events);
if (retval)
goto out_hist;
}
- if (params->buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->buffer_size);
+ if (params->common.buffer_size > 0) {
+ retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
if (retval)
goto out_hist;
}
@@ -1328,22 +1328,22 @@ int timerlat_hist_main(int argc, char *argv[])
/* all threads left */
params_u.stopped_running = 0;
- params_u.set = ¶ms->monitored_cpus;
- if (params->set_sched)
- params_u.sched_param = ¶ms->sched_param;
+ params_u.set = ¶ms->common.monitored_cpus;
+ if (params->common.set_sched)
+ params_u.sched_param = ¶ms->common.sched_param;
else
params_u.sched_param = NULL;
- params_u.cgroup_name = params->cgroup_name;
+ params_u.cgroup_name = params->common.cgroup_name;
retval = pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, ¶ms_u);
if (retval)
err_msg("Error creating timerlat user-space threads\n");
}
- if (params->warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->warmup);
- sleep(params->warmup);
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
if (stop_tracing)
goto out_hist;
}
@@ -1374,7 +1374,7 @@ int timerlat_hist_main(int argc, char *argv[])
if (params->mode == TRACING_MODE_TRACEFS) {
while (!stop_tracing) {
- sleep(params->sleep_time);
+ sleep(params->common.sleep_time);
retval = tracefs_iterate_raw_events(trace->tep,
trace->inst,
@@ -1456,7 +1456,8 @@ int timerlat_hist_main(int argc, char *argv[])
printf("rtla timerlat hit stop tracing\n");
if (!params->no_aa)
- timerlat_auto_analysis(params->stop_us, params->stop_total_us);
+ timerlat_auto_analysis(params->common.stop_us,
+ params->common.stop_total_us);
return_value = FAILED;
}
@@ -1467,13 +1468,13 @@ int timerlat_hist_main(int argc, char *argv[])
close(dma_latency_fd);
if (params->deepest_idle_state >= -1) {
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
restore_cpu_idle_disable_state(i);
}
}
- trace_events_destroy(&record->trace, params->events);
- params->events = NULL;
+ trace_events_destroy(&record->trace, params->common.events);
+ params->common.events = NULL;
out_free:
timerlat_free_histogram(tool->data);
osnoise_destroy_tool(aa);
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index c80b81c0b4da..9fb60f4dd092 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -457,7 +457,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *top)
timerlat_top_header(params, top);
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
timerlat_top_print(top, i);
timerlat_top_update_sum(top, i, &summary);
@@ -618,8 +618,8 @@ static struct timerlat_params
auto_thresh = get_llong_from_str(optarg);
/* set thread stop to auto_thresh */
- params->stop_total_us = auto_thresh;
- params->stop_us = auto_thresh;
+ params->common.stop_total_us = auto_thresh;
+ params->common.stop_us = auto_thresh;
/* get stack trace */
params->print_stack = auto_thresh;
@@ -633,8 +633,8 @@ static struct timerlat_params
auto_thresh = get_llong_from_str(optarg);
/* set thread stop to auto_thresh */
- params->stop_total_us = auto_thresh;
- params->stop_us = auto_thresh;
+ params->common.stop_total_us = auto_thresh;
+ params->common.stop_us = auto_thresh;
/* get stack trace */
params->print_stack = auto_thresh;
@@ -643,27 +643,27 @@ static struct timerlat_params
params->aa_only = 1;
break;
case 'c':
- retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
+ retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
if (retval)
timerlat_top_usage("\nInvalid -c cpu list\n");
- params->cpus = optarg;
+ params->common.cpus = optarg;
break;
case 'C':
- params->cgroup = 1;
+ params->common.cgroup = 1;
if (!optarg) {
/* will inherit this cgroup */
- params->cgroup_name = NULL;
+ params->common.cgroup_name = NULL;
} else if (*optarg == '=') {
/* skip the = */
- params->cgroup_name = ++optarg;
+ params->common.cgroup_name = ++optarg;
}
break;
case 'D':
config_debug = 1;
break;
case 'd':
- params->duration = parse_seconds_duration(optarg);
- if (!params->duration)
+ params->common.duration = parse_seconds_duration(optarg);
+ if (!params->common.duration)
timerlat_top_usage("Invalid -d duration\n");
break;
case 'e':
@@ -673,24 +673,24 @@ static struct timerlat_params
exit(EXIT_FAILURE);
}
- if (params->events)
- tevent->next = params->events;
- params->events = tevent;
+ if (params->common.events)
+ tevent->next = params->common.events;
+ params->common.events = tevent;
break;
case 'h':
case '?':
timerlat_top_usage(NULL);
break;
case 'H':
- params->hk_cpus = 1;
- retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
+ params->common.hk_cpus = 1;
+ retval = parse_cpu_set(optarg, ¶ms->common.hk_cpu_set);
if (retval) {
err_msg("Error parsing house keeping CPUs\n");
exit(EXIT_FAILURE);
}
break;
case 'i':
- params->stop_us = get_llong_from_str(optarg);
+ params->common.stop_us = get_llong_from_str(optarg);
break;
case 'k':
params->kernel_workload = true;
@@ -704,10 +704,10 @@ static struct timerlat_params
timerlat_top_usage("Period longer than 1 s\n");
break;
case 'P':
- retval = parse_prio(optarg, ¶ms->sched_param);
+ retval = parse_prio(optarg, ¶ms->common.sched_param);
if (retval == -1)
timerlat_top_usage("Invalid -P priority");
- params->set_sched = 1;
+ params->common.set_sched = 1;
break;
case 'q':
params->quiet = 1;
@@ -716,7 +716,7 @@ static struct timerlat_params
params->print_stack = get_llong_from_str(optarg);
break;
case 'T':
- params->stop_total_us = get_llong_from_str(optarg);
+ params->common.stop_total_us = get_llong_from_str(optarg);
break;
case 't':
if (optarg) {
@@ -736,8 +736,8 @@ static struct timerlat_params
params->user_data = true;
break;
case '0': /* trigger */
- if (params->events) {
- retval = trace_event_add_trigger(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_trigger(params->common.events, optarg);
if (retval) {
err_msg("Error adding trigger %s\n", optarg);
exit(EXIT_FAILURE);
@@ -747,8 +747,8 @@ static struct timerlat_params
}
break;
case '1': /* filter */
- if (params->events) {
- retval = trace_event_add_filter(params->events, optarg);
+ if (params->common.events) {
+ retval = trace_event_add_filter(params->common.events, optarg);
if (retval) {
err_msg("Error adding filter %s\n", optarg);
exit(EXIT_FAILURE);
@@ -771,10 +771,10 @@ static struct timerlat_params
params->dump_tasks = 1;
break;
case '6':
- params->warmup = get_llong_from_str(optarg);
+ params->common.warmup = get_llong_from_str(optarg);
break;
case '7':
- params->buffer_size = get_llong_from_str(optarg);
+ params->common.buffer_size = get_llong_from_str(optarg);
break;
case '8':
params->deepest_idle_state = get_llong_from_str(optarg);
@@ -809,7 +809,7 @@ static struct timerlat_params
/*
* Auto analysis only happens if stop tracing, thus:
*/
- if (!params->stop_us && !params->stop_total_us)
+ if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
if (params->no_aa && params->aa_only)
@@ -906,9 +906,9 @@ static void
timerlat_top_set_signals(struct timerlat_params *params)
{
signal(SIGINT, stop_top);
- if (params->duration) {
+ if (params->common.duration) {
signal(SIGALRM, stop_top);
- alarm(params->duration);
+ alarm(params->common.duration);
}
}
@@ -926,7 +926,7 @@ timerlat_top_main_loop(struct osnoise_tool *top,
int retval;
while (!stop_tracing) {
- sleep(params->sleep_time);
+ sleep(params->common.sleep_time);
if (params->aa_only && !osnoise_trace_is_off(top, record))
continue;
@@ -992,7 +992,7 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
/* Pull and display data in a loop */
while (!stop_tracing) {
- wait_retval = timerlat_bpf_wait(params->quiet ? -1 : params->sleep_time);
+ wait_retval = timerlat_bpf_wait(params->quiet ? -1 : params->common.sleep_time);
retval = timerlat_top_bpf_pull_data(top);
if (retval) {
@@ -1094,16 +1094,16 @@ int timerlat_top_main(int argc, char *argv[])
goto out_free;
}
- if (params->set_sched) {
- retval = set_comm_sched_attr("timerlat/", ¶ms->sched_param);
+ if (params->common.set_sched) {
+ retval = set_comm_sched_attr("timerlat/", ¶ms->common.sched_param);
if (retval) {
err_msg("Failed to set sched parameters\n");
goto out_free;
}
}
- if (params->cgroup && !params->user_data) {
- retval = set_comm_cgroup("timerlat/", params->cgroup_name);
+ if (params->common.cgroup && !params->user_data) {
+ retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
if (!retval) {
err_msg("Failed to move threads to cgroup\n");
goto out_free;
@@ -1127,7 +1127,7 @@ int timerlat_top_main(int argc, char *argv[])
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
if (save_cpu_idle_disable_state(i) < 0) {
err_msg("Could not save cpu idle state.\n");
@@ -1150,14 +1150,14 @@ int timerlat_top_main(int argc, char *argv[])
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);
+ if (params->common.events) {
+ retval = trace_events_enable(&record->trace, params->common.events);
if (retval)
goto out_top;
}
- if (params->buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->buffer_size);
+ if (params->common.buffer_size > 0) {
+ retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
if (retval)
goto out_top;
}
@@ -1190,22 +1190,22 @@ int timerlat_top_main(int argc, char *argv[])
/* all threads left */
params_u.stopped_running = 0;
- params_u.set = ¶ms->monitored_cpus;
- if (params->set_sched)
- params_u.sched_param = ¶ms->sched_param;
+ params_u.set = ¶ms->common.monitored_cpus;
+ if (params->common.set_sched)
+ params_u.sched_param = ¶ms->common.sched_param;
else
params_u.sched_param = NULL;
- params_u.cgroup_name = params->cgroup_name;
+ params_u.cgroup_name = params->common.cgroup_name;
retval = pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, ¶ms_u);
if (retval)
err_msg("Error creating timerlat user-space threads\n");
}
- if (params->warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->warmup);
- sleep(params->warmup);
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
}
/*
@@ -1258,7 +1258,8 @@ int timerlat_top_main(int argc, char *argv[])
printf("rtla timerlat hit stop tracing\n");
if (!params->no_aa)
- timerlat_auto_analysis(params->stop_us, params->stop_total_us);
+ timerlat_auto_analysis(params->common.stop_us,
+ params->common.stop_total_us);
return_value = FAILED;
} else if (params->aa_only) {
@@ -1279,13 +1280,13 @@ int timerlat_top_main(int argc, char *argv[])
close(dma_latency_fd);
if (params->deepest_idle_state >= -1) {
for (i = 0; i < nr_cpus; i++) {
- if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
continue;
restore_cpu_idle_disable_state(i);
}
}
- trace_events_destroy(&record->trace, params->events);
- params->events = NULL;
+ trace_events_destroy(&record->trace, params->common.events);
+ params->common.events = NULL;
out_free:
timerlat_free_top(top->data);
if (aa && aa != top)
--
2.48.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 2/7] tools/rtla: Move top/hist params into common struct
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
2025-09-07 2:23 ` [PATCH v2 1/7] tools/rtla: Consolidate common parameters into shared structure Crystal Wood
@ 2025-09-07 2:23 ` Crystal Wood
2025-09-07 2:23 ` [PATCH v2 3/7] tools/rtla: Create common_apply_config() Crystal Wood
` (6 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Crystal Wood @ 2025-09-07 2:23 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
The hist members were very similar between timerlat and top, so
just use one common hist struct.
output_divisor, quiet, and pretty printing are pretty generic
concepts that can go in the main struct even if not every
specific tool (currently) uses them.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
tools/tracing/rtla/src/common.h | 17 ++++
tools/tracing/rtla/src/osnoise.h | 19 +---
tools/tracing/rtla/src/osnoise_hist.c | 59 ++++++------
tools/tracing/rtla/src/osnoise_top.c | 19 ++--
tools/tracing/rtla/src/timerlat.h | 22 +----
tools/tracing/rtla/src/timerlat_bpf.c | 14 +--
tools/tracing/rtla/src/timerlat_hist.c | 127 +++++++++++++------------
tools/tracing/rtla/src/timerlat_top.c | 38 ++++----
8 files changed, 152 insertions(+), 163 deletions(-)
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
index 0a44cfaa7c0b..276dfbc7f955 100644
--- a/tools/tracing/rtla/src/common.h
+++ b/tools/tracing/rtla/src/common.h
@@ -3,6 +3,17 @@
#include "utils.h"
+struct hist_params {
+ char no_irq;
+ char no_thread;
+ char no_header;
+ char no_summary;
+ char no_index;
+ char with_zeros;
+ int bucket_size;
+ int entries;
+};
+
/*
* common_params - Parameters shared between timerlat_params and osnoise_params
*/
@@ -27,4 +38,10 @@ struct common_params {
char *cgroup_name;
int hk_cpus;
cpu_set_t hk_cpu_set;
+
+ /* Other parameters */
+ struct hist_params hist;
+ int output_divisor;
+ int pretty_output;
+ int quiet;
};
diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osnoise.h
index 0386bb50ffa1..b64b39de97b5 100644
--- a/tools/tracing/rtla/src/osnoise.h
+++ b/tools/tracing/rtla/src/osnoise.h
@@ -15,24 +15,7 @@ struct osnoise_params {
unsigned long long runtime;
unsigned long long period;
long long threshold;
- union {
- struct {
- /* top only */
- int quiet;
- int pretty_output;
- enum osnoise_mode mode;
- };
- struct {
- /* hist only */
- int output_divisor;
- char no_header;
- char no_summary;
- char no_index;
- char with_zeros;
- int bucket_size;
- int entries;
- };
- };
+ enum osnoise_mode mode;
};
/*
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 3fb9bb553498..a31ab9b4ab21 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -102,8 +102,8 @@ static void osnoise_hist_update_multiple(struct osnoise_tool *tool, int cpu,
int bucket;
int *hist;
- if (params->output_divisor)
- duration = duration / params->output_divisor;
+ if (params->common.output_divisor)
+ duration = duration / params->common.output_divisor;
bucket = duration / data->bucket_size;
@@ -146,7 +146,7 @@ static int osnoise_init_trace_hist(struct osnoise_tool *tool)
/*
* Set the size of the bucket.
*/
- bucket_size = params->output_divisor * params->bucket_size;
+ bucket_size = params->common.output_divisor * params->common.hist.bucket_size;
snprintf(buff, sizeof(buff), "duration.buckets=%d", bucket_size);
data->trace_hist = tracefs_hist_alloc(tool->trace.tep, "osnoise", "sample_threshold",
@@ -228,18 +228,18 @@ static void osnoise_hist_header(struct osnoise_tool *tool)
char duration[26];
int cpu;
- if (params->no_header)
+ if (params->common.hist.no_header)
return;
get_duration(tool->start_time, duration, sizeof(duration));
trace_seq_printf(s, "# RTLA osnoise histogram\n");
trace_seq_printf(s, "# Time unit is %s (%s)\n",
- params->output_divisor == 1 ? "nanoseconds" : "microseconds",
- params->output_divisor == 1 ? "ns" : "us");
+ params->common.output_divisor == 1 ? "nanoseconds" : "microseconds",
+ params->common.output_divisor == 1 ? "ns" : "us");
trace_seq_printf(s, "# Duration: %s\n", duration);
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(s, "Index");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -267,10 +267,10 @@ osnoise_print_summary(struct osnoise_params *params,
{
int cpu;
- if (params->no_summary)
+ if (params->common.hist.no_summary)
return;
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "count:");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -284,7 +284,7 @@ osnoise_print_summary(struct osnoise_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "min: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -299,7 +299,7 @@ osnoise_print_summary(struct osnoise_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "avg: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -317,7 +317,7 @@ osnoise_print_summary(struct osnoise_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "max: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -352,7 +352,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
for (bucket = 0; bucket < data->entries; bucket++) {
total = 0;
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "%-6d",
bucket * data->bucket_size);
@@ -367,7 +367,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].samples[bucket]);
}
- if (total == 0 && !params->with_zeros) {
+ if (total == 0 && !params->common.hist.with_zeros) {
trace_seq_reset(trace->seq);
continue;
}
@@ -391,7 +391,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
return;
}
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "over: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -490,9 +490,9 @@ static struct osnoise_params
exit(1);
/* display data in microseconds */
- params->output_divisor = 1000;
- params->bucket_size = 1;
- params->entries = 256;
+ params->common.output_divisor = 1000;
+ params->common.hist.bucket_size = 1;
+ params->common.hist.entries = 256;
while (1) {
static struct option long_options[] = {
@@ -547,8 +547,9 @@ static struct osnoise_params
break;
case 'b':
- params->bucket_size = get_llong_from_str(optarg);
- if ((params->bucket_size == 0) || (params->bucket_size >= 1000000))
+ params->common.hist.bucket_size = get_llong_from_str(optarg);
+ if (params->common.hist.bucket_size == 0 ||
+ params->common.hist.bucket_size >= 1000000)
osnoise_hist_usage("Bucket size needs to be > 0 and <= 1000000\n");
break;
case 'c':
@@ -588,8 +589,9 @@ static struct osnoise_params
params->common.events = tevent;
break;
case 'E':
- params->entries = get_llong_from_str(optarg);
- if ((params->entries < 10) || (params->entries > 9999999))
+ params->common.hist.entries = get_llong_from_str(optarg);
+ if (params->common.hist.entries < 10 ||
+ params->common.hist.entries > 9999999)
osnoise_hist_usage("Entries must be > 10 and < 9999999\n");
break;
case 'h':
@@ -641,16 +643,16 @@ static struct osnoise_params
params->trace_output = "osnoise_trace.txt";
break;
case '0': /* no header */
- params->no_header = 1;
+ params->common.hist.no_header = 1;
break;
case '1': /* no summary */
- params->no_summary = 1;
+ params->common.hist.no_summary = 1;
break;
case '2': /* no index */
- params->no_index = 1;
+ params->common.hist.no_index = 1;
break;
case '3': /* with zeros */
- params->with_zeros = 1;
+ params->common.hist.with_zeros = 1;
break;
case '4': /* trigger */
if (params->common.events) {
@@ -690,7 +692,7 @@ static struct osnoise_params
exit(EXIT_FAILURE);
}
- if (params->no_index && !params->with_zeros)
+ if (params->common.hist.no_index && !params->common.hist.with_zeros)
osnoise_hist_usage("no-index set and with-zeros not set - it does not make sense");
return params;
@@ -729,7 +731,8 @@ static struct osnoise_tool
if (!tool)
return NULL;
- tool->data = osnoise_alloc_histogram(nr_cpus, params->entries, params->bucket_size);
+ tool->data = osnoise_alloc_histogram(nr_cpus, params->common.hist.entries,
+ params->common.hist.bucket_size);
if (!tool->data)
goto out_err;
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index ad5daa8210aa..7c68feed300e 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -125,11 +125,12 @@ static void osnoise_top_header(struct osnoise_tool *top)
{
struct osnoise_params *params = top->params;
struct trace_seq *s = top->trace.seq;
+ bool pretty = params->common.pretty_output;
char duration[26];
get_duration(top->start_time, duration, sizeof(duration));
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[2;37;40m");
trace_seq_printf(s, " ");
@@ -143,13 +144,13 @@ static void osnoise_top_header(struct osnoise_tool *top)
trace_seq_printf(s, " ");
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[0;0;0m");
trace_seq_printf(s, "\n");
trace_seq_printf(s, "duration: %9s | time is in us\n", duration);
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[2;30;47m");
trace_seq_printf(s, "CPU Period Runtime ");
@@ -164,7 +165,7 @@ static void osnoise_top_header(struct osnoise_tool *top)
trace_seq_printf(s, " IRQ Softirq Thread");
eol:
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[0;0;0m");
trace_seq_printf(s, "\n");
}
@@ -232,7 +233,7 @@ osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *top)
if (nr_cpus == -1)
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
- if (!params->quiet)
+ if (!params->common.quiet)
clear_terminal(trace->seq);
osnoise_top_header(top);
@@ -446,7 +447,7 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
params->common.set_sched = 1;
break;
case 'q':
- params->quiet = 1;
+ params->common.quiet = 1;
break;
case 'r':
params->runtime = get_llong_from_str(optarg);
@@ -534,8 +535,8 @@ osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_params *param
}
}
- if (isatty(STDOUT_FILENO) && !params->quiet)
- params->pretty_output = 1;
+ if (isatty(STDOUT_FILENO) && !params->common.quiet)
+ params->common.pretty_output = 1;
return 0;
@@ -705,7 +706,7 @@ int osnoise_top_main(int argc, char **argv)
goto out_top;
}
- if (!params->quiet)
+ if (!params->common.quiet)
osnoise_print_stats(params, tool);
if (osnoise_trace_is_off(tool, record))
diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
index dd9e0f05bdad..212ee7971bab 100644
--- a/tools/tracing/rtla/src/timerlat.h
+++ b/tools/tracing/rtla/src/timerlat.h
@@ -23,7 +23,6 @@ struct timerlat_params {
struct common_params common;
long long timerlat_period_us;
long long print_stack;
- int output_divisor;
int dma_latency;
int no_aa;
int dump_tasks;
@@ -31,30 +30,11 @@ struct timerlat_params {
int kernel_workload;
int user_data;
int deepest_idle_state;
+ int aa_only;
enum timerlat_tracing_mode mode;
struct actions threshold_actions;
struct actions end_actions;
-
- union {
- struct {
- /* top only */
- int quiet;
- int aa_only;
- int pretty_output;
- };
- struct {
- /* hist only */
- char no_irq;
- char no_thread;
- char no_header;
- char no_summary;
- char no_index;
- char with_zeros;
- int bucket_size;
- int entries;
- };
- };
};
int timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params);
diff --git a/tools/tracing/rtla/src/timerlat_bpf.c b/tools/tracing/rtla/src/timerlat_bpf.c
index a6c77ac55e00..03be2606f54a 100644
--- a/tools/tracing/rtla/src/timerlat_bpf.c
+++ b/tools/tracing/rtla/src/timerlat_bpf.c
@@ -21,20 +21,20 @@ int timerlat_bpf_init(struct timerlat_params *params)
return 1;
/* Pass common options */
- bpf->rodata->output_divisor = params->output_divisor;
- bpf->rodata->entries = params->entries;
+ bpf->rodata->output_divisor = params->common.output_divisor;
+ bpf->rodata->entries = params->common.hist.entries;
bpf->rodata->irq_threshold = params->common.stop_us;
bpf->rodata->thread_threshold = params->common.stop_total_us;
bpf->rodata->aa_only = params->aa_only;
- if (params->entries != 0) {
+ if (params->common.hist.entries != 0) {
/* Pass histogram options */
- bpf->rodata->bucket_size = params->bucket_size;
+ bpf->rodata->bucket_size = params->common.hist.bucket_size;
/* Set histogram array sizes */
- bpf_map__set_max_entries(bpf->maps.hist_irq, params->entries);
- bpf_map__set_max_entries(bpf->maps.hist_thread, params->entries);
- bpf_map__set_max_entries(bpf->maps.hist_user, params->entries);
+ bpf_map__set_max_entries(bpf->maps.hist_irq, params->common.hist.entries);
+ bpf_map__set_max_entries(bpf->maps.hist_thread, params->common.hist.entries);
+ bpf_map__set_max_entries(bpf->maps.hist_user, params->common.hist.entries);
} else {
/* No entries, disable histogram */
bpf_map__set_autocreate(bpf->maps.hist_irq, false);
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index a3de644f2b75..4dc22a749885 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -141,8 +141,8 @@ timerlat_hist_update(struct osnoise_tool *tool, int cpu,
int bucket;
int *hist;
- if (params->output_divisor)
- latency = latency / params->output_divisor;
+ if (params->common.output_divisor)
+ latency = latency / params->common.output_divisor;
bucket = latency / data->bucket_size;
@@ -288,18 +288,18 @@ static void timerlat_hist_header(struct osnoise_tool *tool)
char duration[26];
int cpu;
- if (params->no_header)
+ if (params->common.hist.no_header)
return;
get_duration(tool->start_time, duration, sizeof(duration));
trace_seq_printf(s, "# RTLA timerlat histogram\n");
trace_seq_printf(s, "# Time unit is %s (%s)\n",
- params->output_divisor == 1 ? "nanoseconds" : "microseconds",
- params->output_divisor == 1 ? "ns" : "us");
+ params->common.output_divisor == 1 ? "nanoseconds" : "microseconds",
+ params->common.output_divisor == 1 ? "ns" : "us");
trace_seq_printf(s, "# Duration: %s\n", duration);
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(s, "Index");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -309,10 +309,10 @@ static void timerlat_hist_header(struct osnoise_tool *tool)
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(s, " IRQ-%03d", cpu);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(s, " Thr-%03d", cpu);
if (params->user_data)
@@ -350,10 +350,10 @@ timerlat_print_summary(struct timerlat_params *params,
{
int cpu;
- if (params->no_summary)
+ if (params->common.hist.no_summary)
return;
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "count:");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -363,11 +363,11 @@ timerlat_print_summary(struct timerlat_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].irq_count);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].thread_count);
@@ -377,7 +377,7 @@ timerlat_print_summary(struct timerlat_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "min: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -387,13 +387,13 @@ timerlat_print_summary(struct timerlat_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
data->hist[cpu].irq_count,
data->hist[cpu].min_irq,
false);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
data->hist[cpu].thread_count,
data->hist[cpu].min_thread,
@@ -407,7 +407,7 @@ timerlat_print_summary(struct timerlat_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "avg: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -417,13 +417,13 @@ timerlat_print_summary(struct timerlat_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
data->hist[cpu].irq_count,
data->hist[cpu].sum_irq,
true);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
data->hist[cpu].thread_count,
data->hist[cpu].sum_thread,
@@ -437,7 +437,7 @@ timerlat_print_summary(struct timerlat_params *params,
}
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "max: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -447,13 +447,13 @@ timerlat_print_summary(struct timerlat_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
data->hist[cpu].irq_count,
data->hist[cpu].max_irq,
false);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
data->hist[cpu].thread_count,
data->hist[cpu].max_thread,
@@ -479,7 +479,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
struct timerlat_hist_cpu sum;
int cpu;
- if (params->no_summary)
+ if (params->common.hist.no_summary)
return;
memset(&sum, 0, sizeof(sum));
@@ -512,13 +512,13 @@ timerlat_print_stats_all(struct timerlat_params *params,
update_max(&sum.max_user, &cpu_data->max_user);
}
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "ALL: ");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(trace->seq, " IRQ");
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, " Thr");
if (params->user_data)
@@ -526,14 +526,14 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "count:");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(trace->seq, "%9llu ",
sum.irq_count);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, "%9llu ",
sum.thread_count);
@@ -543,16 +543,16 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "min: ");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
sum.irq_count,
sum.min_irq,
false);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
sum.thread_count,
sum.min_thread,
@@ -566,16 +566,16 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "avg: ");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
sum.irq_count,
sum.sum_irq,
true);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
sum.thread_count,
sum.sum_thread,
@@ -589,16 +589,16 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "\n");
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "max: ");
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
format_summary_value(trace->seq,
sum.irq_count,
sum.max_irq,
false);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
format_summary_value(trace->seq,
sum.thread_count,
sum.max_thread,
@@ -631,7 +631,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
for (bucket = 0; bucket < data->entries; bucket++) {
total = 0;
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "%-6d",
bucket * data->bucket_size);
@@ -642,13 +642,13 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq) {
+ if (!params->common.hist.no_irq) {
total += data->hist[cpu].irq[bucket];
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].irq[bucket]);
}
- if (!params->no_thread) {
+ if (!params->common.hist.no_thread) {
total += data->hist[cpu].thread[bucket];
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].thread[bucket]);
@@ -662,7 +662,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
}
- if (total == 0 && !params->with_zeros) {
+ if (total == 0 && !params->common.hist.with_zeros) {
trace_seq_reset(trace->seq);
continue;
}
@@ -672,7 +672,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
trace_seq_reset(trace->seq);
}
- if (!params->no_index)
+ if (!params->common.hist.no_index)
trace_seq_printf(trace->seq, "over: ");
for (cpu = 0; cpu < data->nr_cpus; cpu++) {
@@ -682,11 +682,11 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq)
+ if (!params->common.hist.no_irq)
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].irq[data->entries]);
- if (!params->no_thread)
+ if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].thread[data->entries]);
@@ -804,9 +804,9 @@ static struct timerlat_params
params->deepest_idle_state = -2;
/* display data in microseconds */
- params->output_divisor = 1000;
- params->bucket_size = 1;
- params->entries = 256;
+ params->common.output_divisor = 1000;
+ params->common.hist.bucket_size = 1;
+ params->common.hist.entries = 256;
/* default to BPF mode */
params->mode = TRACING_MODE_BPF;
@@ -894,8 +894,9 @@ static struct timerlat_params
}
break;
case 'b':
- params->bucket_size = get_llong_from_str(optarg);
- if ((params->bucket_size == 0) || (params->bucket_size >= 1000000))
+ params->common.hist.bucket_size = get_llong_from_str(optarg);
+ if (params->common.hist.bucket_size == 0 ||
+ params->common.hist.bucket_size >= 1000000)
timerlat_hist_usage("Bucket size needs to be > 0 and <= 1000000\n");
break;
case 'D':
@@ -919,9 +920,10 @@ static struct timerlat_params
params->common.events = tevent;
break;
case 'E':
- params->entries = get_llong_from_str(optarg);
- if ((params->entries < 10) || (params->entries > 9999999))
- timerlat_hist_usage("Entries must be > 10 and < 9999999\n");
+ params->common.hist.entries = get_llong_from_str(optarg);
+ if (params->common.hist.entries < 10 ||
+ params->common.hist.entries > 9999999)
+ timerlat_hist_usage("Entries must be > 10 and < 9999999\n");
break;
case 'h':
case '?':
@@ -942,7 +944,7 @@ static struct timerlat_params
params->kernel_workload = 1;
break;
case 'n':
- params->output_divisor = 1;
+ params->common.output_divisor = 1;
break;
case 'p':
params->timerlat_period_us = get_llong_from_str(optarg);
@@ -979,22 +981,22 @@ static struct timerlat_params
params->user_data = 1;
break;
case '0': /* no irq */
- params->no_irq = 1;
+ params->common.hist.no_irq = 1;
break;
case '1': /* no thread */
- params->no_thread = 1;
+ params->common.hist.no_thread = 1;
break;
case '2': /* no header */
- params->no_header = 1;
+ params->common.hist.no_header = 1;
break;
case '3': /* no summary */
- params->no_summary = 1;
+ params->common.hist.no_summary = 1;
break;
case '4': /* no index */
- params->no_index = 1;
+ params->common.hist.no_index = 1;
break;
case '5': /* with zeros */
- params->with_zeros = 1;
+ params->common.hist.with_zeros = 1;
break;
case '6': /* trigger */
if (params->common.events) {
@@ -1067,10 +1069,10 @@ static struct timerlat_params
exit(EXIT_FAILURE);
}
- if (params->no_irq && params->no_thread)
+ if (params->common.hist.no_irq && params->common.hist.no_thread)
timerlat_hist_usage("no-irq and no-thread set, there is nothing to do here");
- if (params->no_index && !params->with_zeros)
+ if (params->common.hist.no_index && !params->common.hist.with_zeros)
timerlat_hist_usage("no-index set with with-zeros is not set - it does not make sense");
/*
@@ -1127,7 +1129,8 @@ static struct osnoise_tool
if (!tool)
return NULL;
- tool->data = timerlat_alloc_histogram(nr_cpus, params->entries, params->bucket_size);
+ tool->data = timerlat_alloc_histogram(nr_cpus, params->common.hist.entries,
+ params->common.hist.bucket_size);
if (!tool->data)
goto out_err;
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 9fb60f4dd092..72be083d7d71 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -132,8 +132,8 @@ timerlat_top_update(struct osnoise_tool *tool, int cpu,
struct timerlat_top_data *data = tool->data;
struct timerlat_top_cpu *cpu_data = &data->cpu_data[cpu];
- if (params->output_divisor)
- latency = latency / params->output_divisor;
+ if (params->common.output_divisor)
+ latency = latency / params->common.output_divisor;
if (!thread) {
cpu_data->irq_count++;
@@ -258,39 +258,40 @@ static int timerlat_top_bpf_pull_data(struct osnoise_tool *tool)
static void timerlat_top_header(struct timerlat_params *params, struct osnoise_tool *top)
{
struct trace_seq *s = top->trace.seq;
+ bool pretty = params->common.pretty_output;
char duration[26];
get_duration(top->start_time, duration, sizeof(duration));
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[2;37;40m");
trace_seq_printf(s, " Timer Latency ");
if (params->user_data)
trace_seq_printf(s, " ");
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[0;0;0m");
trace_seq_printf(s, "\n");
trace_seq_printf(s, "%-6s | IRQ Timer Latency (%s) | Thread Timer Latency (%s)", duration,
- params->output_divisor == 1 ? "ns" : "us",
- params->output_divisor == 1 ? "ns" : "us");
+ params->common.output_divisor == 1 ? "ns" : "us",
+ params->common.output_divisor == 1 ? "ns" : "us");
if (params->user_data) {
trace_seq_printf(s, " | Ret user Timer Latency (%s)",
- params->output_divisor == 1 ? "ns" : "us");
+ params->common.output_divisor == 1 ? "ns" : "us");
}
trace_seq_printf(s, "\n");
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[2;30;47m");
trace_seq_printf(s, "CPU COUNT | cur min avg max | cur min avg max");
if (params->user_data)
trace_seq_printf(s, " | cur min avg max");
- if (params->pretty_output)
+ if (pretty)
trace_seq_printf(s, "\033[0;0;0m");
trace_seq_printf(s, "\n");
}
@@ -449,7 +450,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *top)
if (nr_cpus == -1)
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
- if (!params->quiet)
+ if (!params->common.quiet)
clear_terminal(trace->seq);
timerlat_top_reset_sum(&summary);
@@ -563,7 +564,7 @@ static struct timerlat_params
params->deepest_idle_state = -2;
/* display data in microseconds */
- params->output_divisor = 1000;
+ params->common.output_divisor = 1000;
/* default to BPF mode */
params->mode = TRACING_MODE_BPF;
@@ -696,7 +697,7 @@ static struct timerlat_params
params->kernel_workload = true;
break;
case 'n':
- params->output_divisor = 1;
+ params->common.output_divisor = 1;
break;
case 'p':
params->timerlat_period_us = get_llong_from_str(optarg);
@@ -710,7 +711,7 @@ static struct timerlat_params
params->common.set_sched = 1;
break;
case 'q':
- params->quiet = 1;
+ params->common.quiet = 1;
break;
case 's':
params->print_stack = get_llong_from_str(optarg);
@@ -842,8 +843,8 @@ timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_params *para
if (retval)
goto out_err;
- if (isatty(STDOUT_FILENO) && !params->quiet)
- params->pretty_output = 1;
+ if (isatty(STDOUT_FILENO) && !params->common.quiet)
+ params->common.pretty_output = 1;
return 0;
@@ -942,7 +943,7 @@ timerlat_top_main_loop(struct osnoise_tool *top,
return retval;
}
- if (!params->quiet)
+ if (!params->common.quiet)
timerlat_print_stats(params, top);
if (osnoise_trace_is_off(top, record)) {
@@ -992,7 +993,8 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
/* Pull and display data in a loop */
while (!stop_tracing) {
- wait_retval = timerlat_bpf_wait(params->quiet ? -1 : params->common.sleep_time);
+ wait_retval = timerlat_bpf_wait(params->common.quiet ? -1 :
+ params->common.sleep_time);
retval = timerlat_top_bpf_pull_data(top);
if (retval) {
@@ -1000,7 +1002,7 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
return retval;
}
- if (!params->quiet)
+ if (!params->common.quiet)
timerlat_print_stats(params, top);
if (wait_retval == 1) {
--
2.48.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 3/7] tools/rtla: Create common_apply_config()
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
2025-09-07 2:23 ` [PATCH v2 1/7] tools/rtla: Consolidate common parameters into shared structure Crystal Wood
2025-09-07 2:23 ` [PATCH v2 2/7] tools/rtla: Move top/hist params into common struct Crystal Wood
@ 2025-09-07 2:23 ` Crystal Wood
2025-09-07 2:23 ` [PATCH v2 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top Crystal Wood
` (5 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Crystal Wood @ 2025-09-07 2:23 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
Merge the common bits of osnoise_apply_config() and
timerlat_apply_config(). Put the result in a new common.c, and move
enough things to common.h so that common.c does not need to include
osnoise.h.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
v2: Removed blank line after SPDX comment
---
tools/tracing/rtla/src/Build | 1 +
tools/tracing/rtla/src/common.c | 63 ++++++++++++++++++++++++
tools/tracing/rtla/src/common.h | 67 ++++++++++++++++++++++++++
tools/tracing/rtla/src/osnoise.c | 37 ++------------
tools/tracing/rtla/src/osnoise.h | 64 ------------------------
tools/tracing/rtla/src/timerlat.c | 51 ++------------------
tools/tracing/rtla/src/timerlat.h | 1 -
tools/tracing/rtla/src/timerlat_hist.c | 4 +-
tools/tracing/rtla/src/timerlat_top.c | 4 +-
9 files changed, 142 insertions(+), 150 deletions(-)
create mode 100644 tools/tracing/rtla/src/common.c
diff --git a/tools/tracing/rtla/src/Build b/tools/tracing/rtla/src/Build
index 66631280b75b..329e24a40cf7 100644
--- a/tools/tracing/rtla/src/Build
+++ b/tools/tracing/rtla/src/Build
@@ -1,6 +1,7 @@
rtla-y += trace.o
rtla-y += utils.o
rtla-y += actions.o
+rtla-y += common.o
rtla-y += osnoise.o
rtla-y += osnoise_top.o
rtla-y += osnoise_hist.o
diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
new file mode 100644
index 000000000000..32a6faffc714
--- /dev/null
+++ b/tools/tracing/rtla/src/common.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include "common.h"
+
+/*
+ * common_apply_config - apply common configs to the initialized tool
+ */
+int
+common_apply_config(struct osnoise_tool *tool, struct common_params *params)
+{
+ int retval, i;
+
+ if (!params->sleep_time)
+ params->sleep_time = 1;
+
+ retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all");
+ if (retval) {
+ err_msg("Failed to apply CPUs config\n");
+ goto out_err;
+ }
+
+ if (!params->cpus) {
+ for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++)
+ CPU_SET(i, ¶ms->monitored_cpus);
+ }
+
+ if (params->hk_cpus) {
+ retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set),
+ ¶ms->hk_cpu_set);
+ if (retval == -1) {
+ err_msg("Failed to set rtla to the house keeping CPUs\n");
+ goto out_err;
+ }
+ } else if (params->cpus) {
+ /*
+ * Even if the user do not set a house-keeping CPU, try to
+ * move rtla to a CPU set different to the one where the user
+ * set the workload to run.
+ *
+ * No need to check results as this is an automatic attempt.
+ */
+ auto_house_keeping(¶ms->monitored_cpus);
+ }
+
+ /*
+ * Set workload according to type of thread if the kernel supports it.
+ * On kernels without support, user threads will have already failed
+ * on missing fd, and kernel threads do not need it.
+ */
+ retval = osnoise_set_workload(tool->context, params->kernel_workload);
+ if (retval < -1) {
+ err_msg("Failed to set OSNOISE_WORKLOAD option\n");
+ goto out_err;
+ }
+
+ return 0;
+
+out_err:
+ return -1;
+}
+
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
index 276dfbc7f955..c306ba502688 100644
--- a/tools/tracing/rtla/src/common.h
+++ b/tools/tracing/rtla/src/common.h
@@ -1,8 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0 */
#pragma once
+#include "trace.h"
#include "utils.h"
+/*
+ * osnoise_context - read, store, write, restore osnoise configs.
+ */
+struct osnoise_context {
+ int flags;
+ int ref;
+
+ char *curr_cpus;
+ char *orig_cpus;
+
+ /* 0 as init value */
+ unsigned long long orig_runtime_us;
+ unsigned long long runtime_us;
+
+ /* 0 as init value */
+ unsigned long long orig_period_us;
+ unsigned long long period_us;
+
+ /* 0 as init value */
+ long long orig_timerlat_period_us;
+ long long timerlat_period_us;
+
+ /* 0 as init value */
+ long long orig_tracing_thresh;
+ long long tracing_thresh;
+
+ /* -1 as init value because 0 is disabled */
+ long long orig_stop_us;
+ long long stop_us;
+
+ /* -1 as init value because 0 is disabled */
+ long long orig_stop_total_us;
+ long long stop_total_us;
+
+ /* -1 as init value because 0 is disabled */
+ long long orig_print_stack;
+ long long print_stack;
+
+ /* -1 as init value because 0 is off */
+ int orig_opt_irq_disable;
+ int opt_irq_disable;
+
+ /* -1 as init value because 0 is off */
+ int orig_opt_workload;
+ int opt_workload;
+};
+
+/*
+ * osnoise_tool - osnoise based tool definition.
+ */
+struct osnoise_tool {
+ struct trace_instance trace;
+ struct osnoise_context *context;
+ void *data;
+ void *params;
+ time_t start_time;
+};
+
struct hist_params {
char no_irq;
char no_thread;
@@ -44,4 +103,12 @@ struct common_params {
int output_divisor;
int pretty_output;
int quiet;
+ int kernel_workload;
};
+
+int osnoise_set_cpus(struct osnoise_context *context, char *cpus);
+void osnoise_restore_cpus(struct osnoise_context *context);
+
+int osnoise_set_workload(struct osnoise_context *context, bool onoff);
+
+int common_apply_config(struct osnoise_tool *tool, struct common_params *params);
diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
index 06ae7437c2c7..4051b21db69a 100644
--- a/tools/tracing/rtla/src/osnoise.c
+++ b/tools/tracing/rtla/src/osnoise.c
@@ -1120,21 +1120,14 @@ osnoise_report_missed_events(struct osnoise_tool *tool)
}
/*
- * osnoise_apply_config - apply common configs to the initialized tool
+ * osnoise_apply_config - apply osnoise configs to the initialized tool
*/
int
osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
{
int retval;
- if (!params->common.sleep_time)
- params->common.sleep_time = 1;
-
- retval = osnoise_set_cpus(tool->context, params->common.cpus ? params->common.cpus : "all");
- if (retval) {
- err_msg("Failed to apply CPUs config\n");
- goto out_err;
- }
+ params->common.kernel_workload = true;
if (params->runtime || params->period) {
retval = osnoise_set_runtime_period(tool->context,
@@ -1169,31 +1162,7 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
goto out_err;
}
- if (params->common.hk_cpus) {
- retval = sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set),
- ¶ms->common.hk_cpu_set);
- if (retval == -1) {
- err_msg("Failed to set rtla to the house keeping CPUs\n");
- goto out_err;
- }
- } else if (params->common.cpus) {
- /*
- * Even if the user do not set a house-keeping CPU, try to
- * move rtla to a CPU set different to the one where the user
- * set the workload to run.
- *
- * No need to check results as this is an automatic attempt.
- */
- auto_house_keeping(¶ms->common.monitored_cpus);
- }
-
- retval = osnoise_set_workload(tool->context, true);
- if (retval < -1) {
- err_msg("Failed to set OSNOISE_WORKLOAD option\n");
- goto out_err;
- }
-
- return 0;
+ return common_apply_config(tool, ¶ms->common);
out_err:
return -1;
diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osnoise.h
index b64b39de97b5..25baf46a2520 100644
--- a/tools/tracing/rtla/src/osnoise.h
+++ b/tools/tracing/rtla/src/osnoise.h
@@ -2,7 +2,6 @@
#pragma once
#include "common.h"
-#include "trace.h"
enum osnoise_mode {
MODE_OSNOISE = 0,
@@ -18,53 +17,6 @@ struct osnoise_params {
enum osnoise_mode mode;
};
-/*
- * osnoise_context - read, store, write, restore osnoise configs.
- */
-struct osnoise_context {
- int flags;
- int ref;
-
- char *curr_cpus;
- char *orig_cpus;
-
- /* 0 as init value */
- unsigned long long orig_runtime_us;
- unsigned long long runtime_us;
-
- /* 0 as init value */
- unsigned long long orig_period_us;
- unsigned long long period_us;
-
- /* 0 as init value */
- long long orig_timerlat_period_us;
- long long timerlat_period_us;
-
- /* 0 as init value */
- long long orig_tracing_thresh;
- long long tracing_thresh;
-
- /* -1 as init value because 0 is disabled */
- long long orig_stop_us;
- long long stop_us;
-
- /* -1 as init value because 0 is disabled */
- long long orig_stop_total_us;
- long long stop_total_us;
-
- /* -1 as init value because 0 is disabled */
- long long orig_print_stack;
- long long print_stack;
-
- /* -1 as init value because 0 is off */
- int orig_opt_irq_disable;
- int opt_irq_disable;
-
- /* -1 as init value because 0 is off */
- int orig_opt_workload;
- int opt_workload;
-};
-
/*
* *_INIT_VALs are also invalid values, they are used to
* communicate errors.
@@ -76,9 +28,6 @@ struct osnoise_context *osnoise_context_alloc(void);
int osnoise_get_context(struct osnoise_context *context);
void osnoise_put_context(struct osnoise_context *context);
-int osnoise_set_cpus(struct osnoise_context *context, char *cpus);
-void osnoise_restore_cpus(struct osnoise_context *context);
-
int osnoise_set_runtime_period(struct osnoise_context *context,
unsigned long long runtime,
unsigned long long period);
@@ -105,19 +54,6 @@ int osnoise_set_print_stack(struct osnoise_context *context,
long long print_stack);
int osnoise_set_irq_disable(struct osnoise_context *context, bool onoff);
-int osnoise_set_workload(struct osnoise_context *context, bool onoff);
-
-/*
- * osnoise_tool - osnoise based tool definition.
- */
-struct osnoise_tool {
- struct trace_instance trace;
- struct osnoise_context *context;
- void *data;
- void *params;
- time_t start_time;
-};
-
void osnoise_destroy_tool(struct osnoise_tool *top);
struct osnoise_tool *osnoise_init_tool(char *tool_name);
struct osnoise_tool *osnoise_init_trace_tool(char *tracer);
diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/timerlat.c
index 0b2f03e1e612..e4bf58db1dd2 100644
--- a/tools/tracing/rtla/src/timerlat.c
+++ b/tools/tracing/rtla/src/timerlat.c
@@ -24,21 +24,7 @@
int
timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
{
- int retval, i;
-
- if (!params->common.sleep_time)
- params->common.sleep_time = 1;
-
- retval = osnoise_set_cpus(tool->context, params->common.cpus ? params->common.cpus : "all");
- if (retval) {
- err_msg("Failed to apply CPUs config\n");
- goto out_err;
- }
-
- if (!params->common.cpus) {
- for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++)
- CPU_SET(i, ¶ms->common.monitored_cpus);
- }
+ int retval;
if (params->mode != TRACING_MODE_BPF) {
/*
@@ -75,29 +61,11 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
goto out_err;
}
- if (params->common.hk_cpus) {
- retval = sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set),
- ¶ms->common.hk_cpu_set);
- if (retval == -1) {
- err_msg("Failed to set rtla to the house keeping CPUs\n");
- goto out_err;
- }
- } else if (params->common.cpus) {
- /*
- * Even if the user do not set a house-keeping CPU, try to
- * move rtla to a CPU set different to the one where the user
- * set the workload to run.
- *
- * No need to check results as this is an automatic attempt.
- */
- auto_house_keeping(¶ms->common.monitored_cpus);
- }
-
/*
* If the user did not specify a type of thread, try user-threads first.
* Fall back to kernel threads otherwise.
*/
- if (!params->kernel_workload && !params->user_data) {
+ if (!params->common.kernel_workload && !params->user_data) {
retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd");
if (retval) {
debug_msg("User-space interface detected, setting user-threads\n");
@@ -105,22 +73,11 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
params->user_data = 1;
} else {
debug_msg("User-space interface not detected, setting kernel-threads\n");
- params->kernel_workload = 1;
+ params->common.kernel_workload = 1;
}
}
- /*
- * Set workload according to type of thread if the kernel supports it.
- * On kernels without support, user threads will have already failed
- * on missing timerlat_fd, and kernel threads do not need it.
- */
- retval = osnoise_set_workload(tool->context, params->kernel_workload);
- if (retval < -1) {
- err_msg("Failed to set OSNOISE_WORKLOAD option\n");
- goto out_err;
- }
-
- return 0;
+ return common_apply_config(tool, ¶ms->common);
out_err:
return -1;
diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
index 212ee7971bab..86cd9bac8855 100644
--- a/tools/tracing/rtla/src/timerlat.h
+++ b/tools/tracing/rtla/src/timerlat.h
@@ -27,7 +27,6 @@ struct timerlat_params {
int no_aa;
int dump_tasks;
int user_workload;
- int kernel_workload;
int user_data;
int deepest_idle_state;
int aa_only;
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 4dc22a749885..d339e2cffae2 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -941,7 +941,7 @@ static struct timerlat_params
params->common.stop_us = get_llong_from_str(optarg);
break;
case 'k':
- params->kernel_workload = 1;
+ params->common.kernel_workload = 1;
break;
case 'n':
params->common.output_divisor = 1;
@@ -1081,7 +1081,7 @@ static struct timerlat_params
if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
- if (params->kernel_workload && params->user_workload)
+ if (params->common.kernel_workload && params->user_workload)
timerlat_hist_usage("--kernel-threads and --user-threads are mutually exclusive!");
/*
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 72be083d7d71..bb42697d2575 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -694,7 +694,7 @@ static struct timerlat_params
params->common.stop_us = get_llong_from_str(optarg);
break;
case 'k':
- params->kernel_workload = true;
+ params->common.kernel_workload = true;
break;
case 'n':
params->common.output_divisor = 1;
@@ -816,7 +816,7 @@ static struct timerlat_params
if (params->no_aa && params->aa_only)
timerlat_top_usage("--no-aa and --aa-only are mutually exclusive!");
- if (params->kernel_workload && params->user_workload)
+ if (params->common.kernel_workload && params->user_workload)
timerlat_top_usage("--kernel-threads and --user-threads are mutually exclusive!");
/*
--
2.48.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (2 preceding siblings ...)
2025-09-07 2:23 ` [PATCH v2 3/7] tools/rtla: Create common_apply_config() Crystal Wood
@ 2025-09-07 2:23 ` Crystal Wood
2025-09-07 19:51 ` Costa Shulyupin
2025-09-07 2:23 ` [PATCH v2 5/7] tools/rtla: Fix -A option name in test comment Crystal Wood
` (4 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Crystal Wood @ 2025-09-07 2:23 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
Currently a lot of code is duplicated between the different rtla tools,
making maintenance more difficult, and encouraging divergence such as
features that are only implemented for certain tools even though they
could be more broadly applicable.
Merge the various main() functions into a common run_tool() with an ops
struct for tool-specific details.
Implement enough support for actions on osnoise to not need to keep the
old params->trace_output path.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
v2:
Removed leading underscores from timerlat_top_bpf_main_loop(),
and used op->tracer for the "hit stop tracing" message
v1:
I've reworked this from my original plan in order to avoid a "god object
anti-pattern" with the params struct, as requested by Costa. In this
case I'm not 100% convinced that the separation is worth the hassle and
all the "params->common.xxx" and the churn as a field or some code goes
from tool-specific to common, but I can see some advantages.
Some bits like aa_only and the user stuff are in common even though they
are only used by timerlat. In the case of user stuff I plan to submit
patches for supporting that on osnoise, and it doesn't seem worthwhile to
jump through hoops to move some of that code out of code that is otherwise
able to be shared. For aa_only, making it non-common would have precluded
sharing some code, and the code that the flag inhibits isn't tool-specific
(unlike no_aa). Plus, there's other common code referring to tool->aa.
---
tools/tracing/rtla/src/common.c | 281 +++++++++++++++
tools/tracing/rtla/src/common.h | 60 +++-
tools/tracing/rtla/src/osnoise.c | 66 ++--
tools/tracing/rtla/src/osnoise.h | 14 +-
tools/tracing/rtla/src/osnoise_hist.c | 234 +++---------
tools/tracing/rtla/src/osnoise_top.c | 218 ++----------
tools/tracing/rtla/src/timerlat.c | 167 ++++++++-
tools/tracing/rtla/src/timerlat.h | 16 +-
tools/tracing/rtla/src/timerlat_bpf.c | 4 +-
tools/tracing/rtla/src/timerlat_hist.c | 450 +++++------------------
tools/tracing/rtla/src/timerlat_top.c | 473 ++++---------------------
tools/tracing/rtla/src/trace.h | 3 -
12 files changed, 792 insertions(+), 1194 deletions(-)
diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c
index 32a6faffc714..2e6e3dac1897 100644
--- a/tools/tracing/rtla/src/common.c
+++ b/tools/tracing/rtla/src/common.c
@@ -1,9 +1,42 @@
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
#include <unistd.h>
#include "common.h"
+struct trace_instance *trace_inst;
+int stop_tracing;
+
+static void stop_trace(int sig)
+{
+ if (stop_tracing) {
+ /*
+ * Stop requested twice in a row; abort event processing and
+ * exit immediately
+ */
+ tracefs_iterate_stop(trace_inst->inst);
+ return;
+ }
+ stop_tracing = 1;
+ if (trace_inst)
+ trace_instance_stop(trace_inst);
+}
+
+/*
+ * set_signals - handles the signal to stop the tool
+ */
+static void set_signals(struct common_params *params)
+{
+ signal(SIGINT, stop_trace);
+ if (params->duration) {
+ signal(SIGALRM, stop_trace);
+ alarm(params->duration);
+ }
+}
+
/*
* common_apply_config - apply common configs to the initialized tool
*/
@@ -61,3 +94,251 @@ common_apply_config(struct osnoise_tool *tool, struct common_params *params)
return -1;
}
+
+int run_tool(struct tool_ops *ops, int argc, char *argv[])
+{
+ struct common_params *params;
+ enum result return_value = ERROR;
+ struct osnoise_tool *tool;
+ bool stopped;
+ int retval;
+
+ params = ops->parse_args(argc, argv);
+ if (!params)
+ exit(1);
+
+ tool = ops->init_tool(params);
+ if (!tool) {
+ err_msg("Could not init osnoise tool\n");
+ goto out_exit;
+ }
+ tool->ops = ops;
+ tool->params = params;
+
+ /*
+ * Save trace instance into global variable so that SIGINT can stop
+ * the timerlat tracer.
+ * Otherwise, rtla could loop indefinitely when overloaded.
+ */
+ trace_inst = &tool->trace;
+
+ retval = ops->apply_config(tool);
+ if (retval) {
+ err_msg("Could not apply config\n");
+ goto out_free;
+ }
+
+ retval = enable_tracer_by_name(trace_inst->inst, ops->tracer);
+ if (retval) {
+ err_msg("Failed to enable %s tracer\n", ops->tracer);
+ goto out_free;
+ }
+
+ if (params->set_sched) {
+ retval = set_comm_sched_attr(ops->comm_prefix, ¶ms->sched_param);
+ if (retval) {
+ err_msg("Failed to set sched parameters\n");
+ goto out_free;
+ }
+ }
+
+ if (params->cgroup && !params->user_data) {
+ retval = set_comm_cgroup(ops->comm_prefix, params->cgroup_name);
+ if (!retval) {
+ err_msg("Failed to move threads to cgroup\n");
+ goto out_free;
+ }
+ }
+
+
+ if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->end_actions.present[ACTION_TRACE_OUTPUT]) {
+ tool->record = osnoise_init_trace_tool(ops->tracer);
+ if (!tool->record) {
+ err_msg("Failed to enable the trace instance\n");
+ goto out_free;
+ }
+ params->threshold_actions.trace_output_inst = tool->record->trace.inst;
+ params->end_actions.trace_output_inst = tool->record->trace.inst;
+
+ if (params->events) {
+ retval = trace_events_enable(&tool->record->trace, params->events);
+ if (retval)
+ goto out_trace;
+ }
+
+ if (params->buffer_size > 0) {
+ retval = trace_set_buffer_size(&tool->record->trace, params->buffer_size);
+ if (retval)
+ goto out_trace;
+ }
+ }
+
+ if (params->user_workload) {
+ pthread_t user_thread;
+
+ /* rtla asked to stop */
+ params->user.should_run = 1;
+ /* all threads left */
+ params->user.stopped_running = 0;
+
+ params->user.set = ¶ms->monitored_cpus;
+ if (params->set_sched)
+ params->user.sched_param = ¶ms->sched_param;
+ else
+ params->user.sched_param = NULL;
+
+ params->user.cgroup_name = params->cgroup_name;
+
+ retval = pthread_create(&user_thread, NULL, timerlat_u_dispatcher, ¶ms->user);
+ if (retval)
+ err_msg("Error creating timerlat user-space threads\n");
+ }
+
+ retval = ops->enable(tool);
+ if (retval)
+ goto out_trace;
+
+ tool->start_time = time(NULL);
+ set_signals(params);
+
+ retval = ops->main(tool);
+ if (retval)
+ goto out_trace;
+
+ if (params->user_workload && !params->user.stopped_running) {
+ params->user.should_run = 0;
+ sleep(1);
+ }
+
+ ops->print_stats(tool);
+
+ actions_perform(¶ms->end_actions);
+
+ return_value = PASSED;
+
+ stopped = osnoise_trace_is_off(tool, tool->record) && !stop_tracing;
+ if (stopped) {
+ printf("%s hit stop tracing\n", ops->tracer);
+ return_value = FAILED;
+ }
+
+ if (ops->analyze)
+ ops->analyze(tool, stopped);
+
+out_trace:
+ trace_events_destroy(&tool->record->trace, params->events);
+ params->events = NULL;
+out_free:
+ ops->free(tool);
+ osnoise_destroy_tool(tool->record);
+ osnoise_destroy_tool(tool);
+ actions_destroy(¶ms->threshold_actions);
+ actions_destroy(¶ms->end_actions);
+ free(params);
+out_exit:
+ exit(return_value);
+}
+
+int top_main_loop(struct osnoise_tool *tool)
+{
+ struct common_params *params = tool->params;
+ struct trace_instance *trace = &tool->trace;
+ struct osnoise_tool *record = tool->record;
+ int retval;
+
+ while (!stop_tracing) {
+ sleep(params->sleep_time);
+
+ if (params->aa_only && !osnoise_trace_is_off(tool, record))
+ continue;
+
+ retval = tracefs_iterate_raw_events(trace->tep,
+ trace->inst,
+ NULL,
+ 0,
+ collect_registered_events,
+ trace);
+ if (retval < 0) {
+ err_msg("Error iterating on events\n");
+ return retval;
+ }
+
+ if (!params->quiet)
+ tool->ops->print_stats(tool);
+
+ if (osnoise_trace_is_off(tool, record)) {
+ actions_perform(¶ms->threshold_actions);
+
+ if (!params->threshold_actions.continue_flag)
+ /* continue flag not set, break */
+ return 0;
+
+ /* continue action reached, re-enable tracing */
+ if (record)
+ trace_instance_start(&record->trace);
+ if (tool->aa)
+ trace_instance_start(&tool->aa->trace);
+ trace_instance_start(trace);
+ }
+
+ /* is there still any user-threads ? */
+ if (params->user_workload) {
+ if (params->user.stopped_running) {
+ debug_msg("timerlat user space threads stopped!\n");
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int hist_main_loop(struct osnoise_tool *tool)
+{
+ struct common_params *params = tool->params;
+ struct trace_instance *trace = &tool->trace;
+ int retval = 0;
+
+ while (!stop_tracing) {
+ sleep(params->sleep_time);
+
+ retval = tracefs_iterate_raw_events(trace->tep,
+ trace->inst,
+ NULL,
+ 0,
+ collect_registered_events,
+ trace);
+ if (retval < 0) {
+ err_msg("Error iterating on events\n");
+ break;
+ }
+
+ if (osnoise_trace_is_off(tool, tool->record)) {
+ actions_perform(¶ms->threshold_actions);
+
+ if (!params->threshold_actions.continue_flag) {
+ /* continue flag not set, break */
+ break;
+
+ /* continue action reached, re-enable tracing */
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ if (tool->aa)
+ trace_instance_start(&tool->aa->trace);
+ trace_instance_start(&tool->trace);
+ }
+ break;
+ }
+
+ /* is there still any user-threads ? */
+ if (params->user_workload) {
+ if (params->user.stopped_running) {
+ debug_msg("user-space threads stopped!\n");
+ break;
+ }
+ }
+ }
+
+ return retval;
+}
diff --git a/tools/tracing/rtla/src/common.h b/tools/tracing/rtla/src/common.h
index c306ba502688..355f113a14a3 100644
--- a/tools/tracing/rtla/src/common.h
+++ b/tools/tracing/rtla/src/common.h
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#pragma once
+#include "actions.h"
+#include "timerlat_u.h"
#include "trace.h"
#include "utils.h"
@@ -51,16 +53,8 @@ struct osnoise_context {
int opt_workload;
};
-/*
- * osnoise_tool - osnoise based tool definition.
- */
-struct osnoise_tool {
- struct trace_instance trace;
- struct osnoise_context *context;
- void *data;
- void *params;
- time_t start_time;
-};
+extern struct trace_instance *trace_inst;
+extern int stop_tracing;
struct hist_params {
char no_irq;
@@ -103,7 +97,46 @@ struct common_params {
int output_divisor;
int pretty_output;
int quiet;
+ int user_workload;
int kernel_workload;
+ int user_data;
+ int aa_only;
+
+ struct actions threshold_actions;
+ struct actions end_actions;
+ struct timerlat_u_params user;
+};
+
+struct tool_ops;
+
+/*
+ * osnoise_tool - osnoise based tool definition.
+ *
+ * Only the "trace" and "context" fields are used for
+ * the additional trace instances (record and aa).
+ */
+struct osnoise_tool {
+ struct tool_ops *ops;
+ struct trace_instance trace;
+ struct osnoise_context *context;
+ void *data;
+ struct common_params *params;
+ time_t start_time;
+ struct osnoise_tool *record;
+ struct osnoise_tool *aa;
+};
+
+struct tool_ops {
+ const char *tracer;
+ const char *comm_prefix;
+ struct common_params *(*parse_args)(int argc, char *argv[]);
+ struct osnoise_tool *(*init_tool)(struct common_params *params);
+ int (*apply_config)(struct osnoise_tool *tool);
+ int (*enable)(struct osnoise_tool *tool);
+ int (*main)(struct osnoise_tool *tool);
+ void (*print_stats)(struct osnoise_tool *tool);
+ void (*analyze)(struct osnoise_tool *tool, bool stopped);
+ void (*free)(struct osnoise_tool *tool);
};
int osnoise_set_cpus(struct osnoise_context *context, char *cpus);
@@ -111,4 +144,11 @@ void osnoise_restore_cpus(struct osnoise_context *context);
int osnoise_set_workload(struct osnoise_context *context, bool onoff);
+void osnoise_destroy_tool(struct osnoise_tool *top);
+struct osnoise_tool *osnoise_init_tool(char *tool_name);
+struct osnoise_tool *osnoise_init_trace_tool(const char *tracer);
+bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record);
+
int common_apply_config(struct osnoise_tool *tool, struct common_params *params);
+int top_main_loop(struct osnoise_tool *tool);
+int hist_main_loop(struct osnoise_tool *tool);
diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
index 4051b21db69a..312c511fa004 100644
--- a/tools/tracing/rtla/src/osnoise.c
+++ b/tools/tracing/rtla/src/osnoise.c
@@ -906,22 +906,6 @@ static void osnoise_put_workload(struct osnoise_context *context)
context->orig_opt_workload = OSNOISE_OPTION_INIT_VAL;
}
-/*
- * enable_osnoise - enable osnoise tracer in the trace_instance
- */
-int enable_osnoise(struct trace_instance *trace)
-{
- return enable_tracer_by_name(trace->inst, "osnoise");
-}
-
-/*
- * enable_timerlat - enable timerlat tracer in the trace_instance
- */
-int enable_timerlat(struct trace_instance *trace)
-{
- return enable_tracer_by_name(trace->inst, "timerlat");
-}
-
enum {
FLAG_CONTEXT_NEWLY_CREATED = (1 << 0),
FLAG_CONTEXT_DELETED = (1 << 1),
@@ -1056,7 +1040,7 @@ struct osnoise_tool *osnoise_init_tool(char *tool_name)
/*
* osnoise_init_trace_tool - init a tracer instance to trace osnoise events
*/
-struct osnoise_tool *osnoise_init_trace_tool(char *tracer)
+struct osnoise_tool *osnoise_init_trace_tool(const char *tracer)
{
struct osnoise_tool *trace;
int retval;
@@ -1168,6 +1152,44 @@ osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
return -1;
}
+int osnoise_enable(struct osnoise_tool *tool)
+{
+ struct osnoise_params *params = to_osnoise_params(tool->params);
+ int retval;
+
+ /*
+ * Start the tracer here, after having set all instances.
+ *
+ * Let the trace instance start first for the case of hitting a stop
+ * tracing while enabling other instances. The trace instance is the
+ * one with most valuable information.
+ */
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ trace_instance_start(&tool->trace);
+
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
+ if (stop_tracing)
+ return -1;
+
+ /*
+ * Clean up the buffer. The osnoise workload do not run
+ * with tracing off to avoid creating a performance penalty
+ * when not needed.
+ */
+ retval = tracefs_instance_file_write(tool->trace.inst, "trace", "");
+ if (retval < 0) {
+ debug_msg("Error cleaning up the buffer");
+ return retval;
+ }
+
+ }
+
+ return 0;
+}
+
static void osnoise_usage(int err)
{
int i;
@@ -1201,7 +1223,7 @@ int osnoise_main(int argc, char *argv[])
* default cmdline.
*/
if (argc == 1) {
- osnoise_top_main(argc, argv);
+ run_tool(&osnoise_top_ops, argc, argv);
exit(0);
}
@@ -1209,13 +1231,13 @@ int osnoise_main(int argc, char *argv[])
osnoise_usage(0);
} else if (strncmp(argv[1], "-", 1) == 0) {
/* the user skipped the tool, call the default one */
- osnoise_top_main(argc, argv);
+ run_tool(&osnoise_top_ops, argc, argv);
exit(0);
} else if (strcmp(argv[1], "top") == 0) {
- osnoise_top_main(argc-1, &argv[1]);
+ run_tool(&osnoise_top_ops, argc-1, &argv[1]);
exit(0);
} else if (strcmp(argv[1], "hist") == 0) {
- osnoise_hist_main(argc-1, &argv[1]);
+ run_tool(&osnoise_hist_ops, argc-1, &argv[1]);
exit(0);
}
@@ -1226,6 +1248,6 @@ int osnoise_main(int argc, char *argv[])
int hwnoise_main(int argc, char *argv[])
{
- osnoise_top_main(argc, argv);
+ run_tool(&osnoise_top_ops, argc, argv);
exit(0);
}
diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osnoise.h
index 25baf46a2520..895687030c0b 100644
--- a/tools/tracing/rtla/src/osnoise.h
+++ b/tools/tracing/rtla/src/osnoise.h
@@ -10,13 +10,14 @@ enum osnoise_mode {
struct osnoise_params {
struct common_params common;
- char *trace_output;
unsigned long long runtime;
unsigned long long period;
long long threshold;
enum osnoise_mode mode;
};
+#define to_osnoise_params(ptr) container_of(ptr, struct osnoise_params, common)
+
/*
* *_INIT_VALs are also invalid values, they are used to
* communicate errors.
@@ -54,14 +55,17 @@ int osnoise_set_print_stack(struct osnoise_context *context,
long long print_stack);
int osnoise_set_irq_disable(struct osnoise_context *context, bool onoff);
-void osnoise_destroy_tool(struct osnoise_tool *top);
-struct osnoise_tool *osnoise_init_tool(char *tool_name);
-struct osnoise_tool *osnoise_init_trace_tool(char *tracer);
void osnoise_report_missed_events(struct osnoise_tool *tool);
-bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record);
int osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params);
int osnoise_hist_main(int argc, char *argv[]);
int osnoise_top_main(int argc, char **argv);
+int osnoise_enable(struct osnoise_tool *tool);
int osnoise_main(int argc, char **argv);
int hwnoise_main(int argc, char **argv);
+
+extern struct tool_ops timerlat_top_ops, timerlat_hist_ops;
+extern struct tool_ops osnoise_top_ops, osnoise_hist_ops;
+
+int run_tool(struct tool_ops *ops, int argc, char *argv[]);
+int hist_main_loop(struct osnoise_tool *tool);
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index a31ab9b4ab21..2c2cdd467a67 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -54,6 +54,11 @@ osnoise_free_histogram(struct osnoise_hist_data *data)
free(data);
}
+static void osnoise_free_hist_tool(struct osnoise_tool *tool)
+{
+ osnoise_free_histogram(tool->data);
+}
+
/*
* osnoise_alloc_histogram - alloc runtime data
*/
@@ -95,7 +100,7 @@ static struct osnoise_hist_data
static void osnoise_hist_update_multiple(struct osnoise_tool *tool, int cpu,
unsigned long long duration, int count)
{
- struct osnoise_params *params = tool->params;
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct osnoise_hist_data *data = tool->data;
unsigned long long total_duration;
int entries = data->entries;
@@ -137,7 +142,7 @@ static void osnoise_destroy_trace_hist(struct osnoise_tool *tool)
*/
static int osnoise_init_trace_hist(struct osnoise_tool *tool)
{
- struct osnoise_params *params = tool->params;
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct osnoise_hist_data *data = tool->data;
int bucket_size;
char buff[128];
@@ -222,7 +227,7 @@ static void osnoise_read_trace_hist(struct osnoise_tool *tool)
*/
static void osnoise_hist_header(struct osnoise_tool *tool)
{
- struct osnoise_params *params = tool->params;
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct osnoise_hist_data *data = tool->data;
struct trace_seq *s = tool->trace.seq;
char duration[26];
@@ -339,8 +344,9 @@ osnoise_print_summary(struct osnoise_params *params,
* osnoise_print_stats - print data for all CPUs
*/
static void
-osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool)
+osnoise_print_stats(struct osnoise_tool *tool)
{
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct osnoise_hist_data *data = tool->data;
struct trace_instance *trace = &tool->trace;
int has_samples = 0;
@@ -477,18 +483,22 @@ static void osnoise_hist_usage(char *usage)
/*
* osnoise_hist_parse_args - allocs, parse and fill the cmd line parameters
*/
-static struct osnoise_params
+static struct common_params
*osnoise_hist_parse_args(int argc, char *argv[])
{
struct osnoise_params *params;
struct trace_events *tevent;
int retval;
int c;
+ char *trace_output = NULL;
params = calloc(1, sizeof(*params));
if (!params)
exit(1);
+ actions_init(¶ms->common.threshold_actions);
+ actions_init(¶ms->common.end_actions);
+
/* display data in microseconds */
params->common.output_divisor = 1000;
params->common.hist.bucket_size = 1;
@@ -543,7 +553,7 @@ static struct osnoise_params
params->threshold = 1;
/* set trace */
- params->trace_output = "osnoise_trace.txt";
+ trace_output = "osnoise_trace.txt";
break;
case 'b':
@@ -634,13 +644,13 @@ static struct osnoise_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] != '0')
- params->trace_output = argv[optind];
+ trace_output = argv[optind];
else
- params->trace_output = "osnoise_trace.txt";
+ trace_output = "osnoise_trace.txt";
break;
case '0': /* no header */
params->common.hist.no_header = 1;
@@ -687,6 +697,9 @@ static struct osnoise_params
}
}
+ if (trace_output)
+ actions_add_trace_output(¶ms->common.threshold_actions, trace_output);
+
if (geteuid()) {
err_msg("rtla needs root permission\n");
exit(EXIT_FAILURE);
@@ -695,32 +708,23 @@ static struct osnoise_params
if (params->common.hist.no_index && !params->common.hist.with_zeros)
osnoise_hist_usage("no-index set and with-zeros not set - it does not make sense");
- return params;
+ return ¶ms->common;
}
/*
* osnoise_hist_apply_config - apply the hist configs to the initialized tool
*/
static int
-osnoise_hist_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
+osnoise_hist_apply_config(struct osnoise_tool *tool)
{
- int retval;
-
- retval = osnoise_apply_config(tool, params);
- if (retval)
- goto out_err;
-
- return 0;
-
-out_err:
- return -1;
+ return osnoise_apply_config(tool, to_osnoise_params(tool->params));
}
/*
* osnoise_init_hist - initialize a osnoise hist tool with parameters
*/
static struct osnoise_tool
-*osnoise_init_hist(struct osnoise_params *params)
+*osnoise_init_hist(struct common_params *params)
{
struct osnoise_tool *tool;
int nr_cpus;
@@ -731,13 +735,11 @@ static struct osnoise_tool
if (!tool)
return NULL;
- tool->data = osnoise_alloc_histogram(nr_cpus, params->common.hist.entries,
- params->common.hist.bucket_size);
+ tool->data = osnoise_alloc_histogram(nr_cpus, params->hist.entries,
+ params->hist.bucket_size);
if (!tool->data)
goto out_err;
- tool->params = params;
-
return tool;
out_err:
@@ -745,171 +747,35 @@ static struct osnoise_tool
return NULL;
}
-static int stop_tracing;
-static void stop_hist(int sig)
-{
- stop_tracing = 1;
-}
-
-/*
- * osnoise_hist_set_signals - handles the signal to stop the tool
- */
-static void
-osnoise_hist_set_signals(struct osnoise_params *params)
+static int osnoise_hist_enable(struct osnoise_tool *tool)
{
- signal(SIGINT, stop_hist);
- if (params->common.duration) {
- signal(SIGALRM, stop_hist);
- alarm(params->common.duration);
- }
-}
-
-int osnoise_hist_main(int argc, char *argv[])
-{
- struct osnoise_params *params;
- struct osnoise_tool *record = NULL;
- struct osnoise_tool *tool = NULL;
- enum result return_value = ERROR;
- struct trace_instance *trace;
int retval;
- params = osnoise_hist_parse_args(argc, argv);
- if (!params)
- exit(1);
-
- tool = osnoise_init_hist(params);
- if (!tool) {
- err_msg("Could not init osnoise hist\n");
- goto out_exit;
- }
-
- retval = osnoise_hist_apply_config(tool, params);
- if (retval) {
- err_msg("Could not apply config\n");
- goto out_destroy;
- }
-
- trace = &tool->trace;
-
- retval = enable_osnoise(trace);
- if (retval) {
- err_msg("Failed to enable osnoise tracer\n");
- goto out_destroy;
- }
-
retval = osnoise_init_trace_hist(tool);
if (retval)
- goto out_destroy;
+ return retval;
- if (params->common.set_sched) {
- retval = set_comm_sched_attr("osnoise/", ¶ms->common.sched_param);
- if (retval) {
- err_msg("Failed to set sched parameters\n");
- goto out_free;
- }
- }
-
- if (params->common.cgroup) {
- retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
- if (!retval) {
- err_msg("Failed to move threads to cgroup\n");
- goto out_free;
- }
- }
-
- if (params->trace_output) {
- record = osnoise_init_trace_tool("osnoise");
- if (!record) {
- err_msg("Failed to enable the trace instance\n");
- goto out_free;
- }
-
- if (params->common.events) {
- retval = trace_events_enable(&record->trace, params->common.events);
- if (retval)
- goto out_hist;
- }
-
- if (params->common.buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
- if (retval)
- goto out_hist;
- }
- }
-
- /*
- * Start the tracer here, after having set all instances.
- *
- * Let the trace instance start first for the case of hitting a stop
- * tracing while enabling other instances. The trace instance is the
- * one with most valuable information.
- */
- if (params->trace_output)
- trace_instance_start(&record->trace);
- trace_instance_start(trace);
-
- if (params->common.warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->common.warmup);
- sleep(params->common.warmup);
- if (stop_tracing)
- goto out_hist;
-
- /*
- * Clean up the buffer. The osnoise workload do not run
- * with tracing off to avoid creating a performance penalty
- * when not needed.
- */
- retval = tracefs_instance_file_write(trace->inst, "trace", "");
- if (retval < 0) {
- debug_msg("Error cleaning up the buffer");
- goto out_hist;
- }
-
- }
-
- tool->start_time = time(NULL);
- osnoise_hist_set_signals(params);
-
- while (!stop_tracing) {
- sleep(params->common.sleep_time);
-
- retval = tracefs_iterate_raw_events(trace->tep,
- trace->inst,
- NULL,
- 0,
- collect_registered_events,
- trace);
- if (retval < 0) {
- err_msg("Error iterating on events\n");
- goto out_hist;
- }
+ return osnoise_enable(tool);
+}
- if (osnoise_trace_is_off(tool, record))
- break;
- }
+static int osnoise_hist_main_loop(struct osnoise_tool *tool)
+{
+ int retval;
+ retval = hist_main_loop(tool);
osnoise_read_trace_hist(tool);
- osnoise_print_stats(params, tool);
-
- return_value = PASSED;
-
- if (osnoise_trace_is_off(tool, record)) {
- printf("rtla osnoise hit stop tracing\n");
- save_trace_to_file(record ? record->trace.inst : NULL,
- params->trace_output);
- return_value = FAILED;
- }
-
-out_hist:
- trace_events_destroy(&record->trace, params->common.events);
- params->common.events = NULL;
-out_free:
- osnoise_free_histogram(tool->data);
-out_destroy:
- osnoise_destroy_tool(record);
- osnoise_destroy_tool(tool);
- free(params);
-out_exit:
- exit(return_value);
+ return retval;
}
+
+struct tool_ops osnoise_hist_ops = {
+ .tracer = "osnoise",
+ .comm_prefix = "osnoise/",
+ .parse_args = osnoise_hist_parse_args,
+ .init_tool = osnoise_init_hist,
+ .apply_config = osnoise_hist_apply_config,
+ .enable = osnoise_hist_enable,
+ .main = osnoise_hist_main_loop,
+ .print_stats = osnoise_print_stats,
+ .free = osnoise_free_hist_tool,
+};
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 7c68feed300e..5a56c276f9da 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -37,13 +37,17 @@ struct osnoise_top_data {
/*
* osnoise_free_top - free runtime data
*/
-static void
-osnoise_free_top(struct osnoise_top_data *data)
+static void osnoise_free_top(struct osnoise_top_data *data)
{
free(data->cpu_data);
free(data);
}
+static void osnoise_free_top_tool(struct osnoise_tool *tool)
+{
+ osnoise_free_top(tool->data);
+}
+
/*
* osnoise_alloc_histogram - alloc runtime data
*/
@@ -123,7 +127,7 @@ osnoise_top_handler(struct trace_seq *s, struct tep_record *record,
*/
static void osnoise_top_header(struct osnoise_tool *top)
{
- struct osnoise_params *params = top->params;
+ struct osnoise_params *params = to_osnoise_params(top->params);
struct trace_seq *s = top->trace.seq;
bool pretty = params->common.pretty_output;
char duration[26];
@@ -184,7 +188,7 @@ static void clear_terminal(struct trace_seq *seq)
*/
static void osnoise_top_print(struct osnoise_tool *tool, int cpu)
{
- struct osnoise_params *params = tool->params;
+ struct osnoise_params *params = to_osnoise_params(tool->params);
struct trace_seq *s = tool->trace.seq;
struct osnoise_top_cpu *cpu_data;
struct osnoise_top_data *data;
@@ -224,8 +228,9 @@ static void osnoise_top_print(struct osnoise_tool *tool, int cpu)
* osnoise_print_stats - print data for all cpus
*/
static void
-osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *top)
+osnoise_print_stats(struct osnoise_tool *top)
{
+ struct osnoise_params *params = to_osnoise_params(top->params);
struct trace_instance *trace = &top->trace;
static int nr_cpus = -1;
int i;
@@ -320,17 +325,21 @@ static void osnoise_top_usage(struct osnoise_params *params, char *usage)
/*
* osnoise_top_parse_args - allocs, parse and fill the cmd line parameters
*/
-struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
+struct common_params *osnoise_top_parse_args(int argc, char **argv)
{
struct osnoise_params *params;
struct trace_events *tevent;
int retval;
int c;
+ char *trace_output = NULL;
params = calloc(1, sizeof(*params));
if (!params)
exit(1);
+ actions_init(¶ms->common.threshold_actions);
+ actions_init(¶ms->common.end_actions);
+
if (strcmp(argv[0], "hwnoise") == 0) {
params->mode = MODE_HWNOISE;
/*
@@ -384,7 +393,7 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
params->threshold = 1;
/* set trace */
- params->trace_output = "osnoise_trace.txt";
+ trace_output = "osnoise_trace.txt";
break;
case 'c':
@@ -463,13 +472,13 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
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 = "osnoise_trace.txt";
+ trace_output = "osnoise_trace.txt";
break;
case 'T':
params->threshold = get_llong_from_str(optarg);
@@ -507,20 +516,24 @@ struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
}
}
+ if (trace_output)
+ actions_add_trace_output(¶ms->common.threshold_actions, trace_output);
+
if (geteuid()) {
err_msg("osnoise needs root permission\n");
exit(EXIT_FAILURE);
}
- return params;
+ return ¶ms->common;
}
/*
* osnoise_top_apply_config - apply the top configs to the initialized tool
*/
static int
-osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
+osnoise_top_apply_config(struct osnoise_tool *tool)
{
+ struct osnoise_params *params = to_osnoise_params(tool->params);
int retval;
retval = osnoise_apply_config(tool, params);
@@ -547,7 +560,7 @@ osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_params *param
/*
* osnoise_init_top - initialize a osnoise top tool with parameters
*/
-struct osnoise_tool *osnoise_init_top(struct osnoise_params *params)
+struct osnoise_tool *osnoise_init_top(struct common_params *params)
{
struct osnoise_tool *tool;
int nr_cpus;
@@ -564,175 +577,20 @@ struct osnoise_tool *osnoise_init_top(struct osnoise_params *params)
return NULL;
}
- tool->params = params;
-
tep_register_event_handler(tool->trace.tep, -1, "ftrace", "osnoise",
osnoise_top_handler, NULL);
return tool;
}
-static int stop_tracing;
-static void stop_top(int sig)
-{
- stop_tracing = 1;
-}
-
-/*
- * osnoise_top_set_signals - handles the signal to stop the tool
- */
-static void osnoise_top_set_signals(struct osnoise_params *params)
-{
- signal(SIGINT, stop_top);
- if (params->common.duration) {
- signal(SIGALRM, stop_top);
- alarm(params->common.duration);
- }
-}
-
-int osnoise_top_main(int argc, char **argv)
-{
- struct osnoise_params *params;
- struct osnoise_tool *record = NULL;
- struct osnoise_tool *tool = NULL;
- enum result return_value = ERROR;
- struct trace_instance *trace;
- int retval;
-
- params = osnoise_top_parse_args(argc, argv);
- if (!params)
- exit(1);
-
- tool = osnoise_init_top(params);
- if (!tool) {
- err_msg("Could not init osnoise top\n");
- goto out_exit;
- }
-
- retval = osnoise_top_apply_config(tool, params);
- if (retval) {
- err_msg("Could not apply config\n");
- goto out_free;
- }
-
- trace = &tool->trace;
-
- retval = enable_osnoise(trace);
- if (retval) {
- err_msg("Failed to enable osnoise tracer\n");
- goto out_free;
- }
-
- if (params->common.set_sched) {
- retval = set_comm_sched_attr("osnoise/", ¶ms->common.sched_param);
- if (retval) {
- err_msg("Failed to set sched parameters\n");
- goto out_free;
- }
- }
-
- if (params->common.cgroup) {
- retval = set_comm_cgroup("osnoise/", params->common.cgroup_name);
- if (!retval) {
- err_msg("Failed to move threads to cgroup\n");
- goto out_free;
- }
- }
-
- if (params->trace_output) {
- record = osnoise_init_trace_tool("osnoise");
- if (!record) {
- err_msg("Failed to enable the trace instance\n");
- goto out_free;
- }
-
- if (params->common.events) {
- retval = trace_events_enable(&record->trace, params->common.events);
- if (retval)
- goto out_top;
- }
-
- if (params->common.buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
- if (retval)
- goto out_top;
- }
- }
-
- /*
- * Start the tracer here, after having set all instances.
- *
- * Let the trace instance start first for the case of hitting a stop
- * tracing while enabling other instances. The trace instance is the
- * one with most valuable information.
- */
- if (params->trace_output)
- trace_instance_start(&record->trace);
- trace_instance_start(trace);
-
- if (params->common.warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->common.warmup);
- sleep(params->common.warmup);
- if (stop_tracing)
- goto out_top;
-
- /*
- * Clean up the buffer. The osnoise workload do not run
- * with tracing off to avoid creating a performance penalty
- * when not needed.
- */
- retval = tracefs_instance_file_write(trace->inst, "trace", "");
- if (retval < 0) {
- debug_msg("Error cleaning up the buffer");
- goto out_top;
- }
-
- }
-
- tool->start_time = time(NULL);
- osnoise_top_set_signals(params);
-
- while (!stop_tracing) {
- sleep(params->common.sleep_time);
-
- retval = tracefs_iterate_raw_events(trace->tep,
- trace->inst,
- NULL,
- 0,
- collect_registered_events,
- trace);
- if (retval < 0) {
- err_msg("Error iterating on events\n");
- goto out_top;
- }
-
- if (!params->common.quiet)
- osnoise_print_stats(params, tool);
-
- if (osnoise_trace_is_off(tool, record))
- break;
-
- }
-
- osnoise_print_stats(params, tool);
-
- return_value = PASSED;
-
- if (osnoise_trace_is_off(tool, record)) {
- printf("osnoise hit stop tracing\n");
- save_trace_to_file(record ? record->trace.inst : NULL,
- params->trace_output);
- return_value = FAILED;
- }
-
-out_top:
- trace_events_destroy(&record->trace, params->common.events);
- params->common.events = NULL;
-out_free:
- osnoise_free_top(tool->data);
- osnoise_destroy_tool(record);
- osnoise_destroy_tool(tool);
- free(params);
-out_exit:
- exit(return_value);
-}
+struct tool_ops osnoise_top_ops = {
+ .tracer = "osnoise",
+ .comm_prefix = "osnoise/",
+ .parse_args = osnoise_top_parse_args,
+ .init_tool = osnoise_init_top,
+ .apply_config = osnoise_top_apply_config,
+ .enable = osnoise_enable,
+ .main = top_main_loop,
+ .print_stats = osnoise_print_stats,
+ .free = osnoise_free_top_tool,
+};
diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/timerlat.c
index e4bf58db1dd2..b69212874127 100644
--- a/tools/tracing/rtla/src/timerlat.c
+++ b/tools/tracing/rtla/src/timerlat.c
@@ -15,9 +15,13 @@
#include <sched.h>
#include "timerlat.h"
+#include "timerlat_aa.h"
+#include "timerlat_bpf.h"
#define DEFAULT_TIMERLAT_PERIOD 1000 /* 1ms */
+static int dma_latency_fd = -1;
+
/*
* timerlat_apply_config - apply common configs to the initialized tool
*/
@@ -26,6 +30,24 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
{
int retval;
+ /*
+ * Try to enable BPF, unless disabled explicitly.
+ * If BPF enablement fails, fall back to tracefs mode.
+ */
+ if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
+ debug_msg("RTLA_NO_BPF set, disabling BPF\n");
+ params->mode = TRACING_MODE_TRACEFS;
+ } else if (!tep_find_event_by_name(tool->trace.tep, "osnoise", "timerlat_sample")) {
+ debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
+ params->mode = TRACING_MODE_TRACEFS;
+ } else {
+ retval = timerlat_bpf_init(params);
+ if (retval) {
+ debug_msg("Could not enable BPF\n");
+ params->mode = TRACING_MODE_TRACEFS;
+ }
+ }
+
if (params->mode != TRACING_MODE_BPF) {
/*
* In tracefs and mixed mode, timerlat tracer handles stopping
@@ -65,12 +87,12 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
* If the user did not specify a type of thread, try user-threads first.
* Fall back to kernel threads otherwise.
*/
- if (!params->common.kernel_workload && !params->user_data) {
+ if (!params->common.kernel_workload && !params->common.user_data) {
retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd");
if (retval) {
debug_msg("User-space interface detected, setting user-threads\n");
- params->user_workload = 1;
- params->user_data = 1;
+ params->common.user_workload = 1;
+ params->common.user_data = 1;
} else {
debug_msg("User-space interface not detected, setting kernel-threads\n");
params->common.kernel_workload = 1;
@@ -83,6 +105,137 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
return -1;
}
+int timerlat_enable(struct osnoise_tool *tool)
+{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
+ int retval, nr_cpus, i;
+
+ if (params->dma_latency >= 0) {
+ dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
+ if (dma_latency_fd < 0) {
+ err_msg("Could not set /dev/cpu_dma_latency.\n");
+ return -1;
+ }
+ }
+
+ if (params->deepest_idle_state >= -1) {
+ if (!have_libcpupower_support()) {
+ err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
+ return -1;
+ }
+
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+ for (i = 0; i < nr_cpus; i++) {
+ if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
+ continue;
+ if (save_cpu_idle_disable_state(i) < 0) {
+ err_msg("Could not save cpu idle state.\n");
+ return -1;
+ }
+ if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
+ err_msg("Could not set deepest cpu idle state.\n");
+ return -1;
+ }
+ }
+ }
+
+ if (!params->no_aa) {
+ tool->aa = osnoise_init_tool("timerlat_aa");
+ if (!tool->aa)
+ return -1;
+
+ retval = timerlat_aa_init(tool->aa, params->dump_tasks);
+ if (retval) {
+ err_msg("Failed to enable the auto analysis instance\n");
+ return retval;
+ }
+
+ retval = enable_tracer_by_name(tool->aa->trace.inst, "timerlat");
+ if (retval) {
+ err_msg("Failed to enable aa tracer\n");
+ return retval;
+ }
+ }
+
+ if (params->common.warmup > 0) {
+ debug_msg("Warming up for %d seconds\n", params->common.warmup);
+ sleep(params->common.warmup);
+ if (stop_tracing)
+ return -1;
+ }
+
+ /*
+ * Start the tracers here, after having set all instances.
+ *
+ * Let the trace instance start first for the case of hitting a stop
+ * tracing while enabling other instances. The trace instance is the
+ * one with most valuable information.
+ */
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ if (!params->no_aa)
+ trace_instance_start(&tool->aa->trace);
+ if (params->mode == TRACING_MODE_TRACEFS) {
+ trace_instance_start(&tool->trace);
+ } else {
+ retval = timerlat_bpf_attach();
+ if (retval) {
+ err_msg("Error attaching BPF program\n");
+ return retval;
+ }
+ }
+
+ return 0;
+}
+
+void timerlat_analyze(struct osnoise_tool *tool, bool stopped)
+{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
+
+ if (stopped) {
+ if (!params->no_aa)
+ timerlat_auto_analysis(params->common.stop_us,
+ params->common.stop_total_us);
+ } else if (params->common.aa_only) {
+ char *max_lat;
+
+ /*
+ * If the trace did not stop with --aa-only, at least print
+ * the max known latency.
+ */
+ max_lat = tracefs_instance_file_read(trace_inst->inst, "tracing_max_latency", NULL);
+ if (max_lat) {
+ printf(" Max latency was %s\n", max_lat);
+ free(max_lat);
+ }
+ }
+}
+
+void timerlat_free(struct osnoise_tool *tool)
+{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
+ int nr_cpus, i;
+
+ timerlat_aa_destroy();
+ if (dma_latency_fd >= 0)
+ close(dma_latency_fd);
+ if (params->deepest_idle_state >= -1) {
+ for (i = 0; i < nr_cpus; i++) {
+ if (params->common.cpus &&
+ !CPU_ISSET(i, ¶ms->common.monitored_cpus))
+ continue;
+ restore_cpu_idle_disable_state(i);
+ }
+ }
+
+ osnoise_destroy_tool(tool->aa);
+
+ if (params->mode != TRACING_MODE_TRACEFS)
+ timerlat_bpf_destroy();
+ free_cpu_idle_disable_states();
+}
+
static void timerlat_usage(int err)
{
int i;
@@ -116,7 +269,7 @@ int timerlat_main(int argc, char *argv[])
* default cmdline.
*/
if (argc == 1) {
- timerlat_top_main(argc, argv);
+ run_tool(&timerlat_top_ops, argc, argv);
exit(0);
}
@@ -124,13 +277,13 @@ int timerlat_main(int argc, char *argv[])
timerlat_usage(0);
} else if (strncmp(argv[1], "-", 1) == 0) {
/* the user skipped the tool, call the default one */
- timerlat_top_main(argc, argv);
+ run_tool(&timerlat_top_ops, argc, argv);
exit(0);
} else if (strcmp(argv[1], "top") == 0) {
- timerlat_top_main(argc-1, &argv[1]);
+ run_tool(&timerlat_top_ops, argc-1, &argv[1]);
exit(0);
} else if (strcmp(argv[1], "hist") == 0) {
- timerlat_hist_main(argc-1, &argv[1]);
+ run_tool(&timerlat_hist_ops, argc-1, &argv[1]);
exit(0);
}
diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/timerlat.h
index 86cd9bac8855..fd6065f48bb7 100644
--- a/tools/tracing/rtla/src/timerlat.h
+++ b/tools/tracing/rtla/src/timerlat.h
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#include "actions.h"
#include "osnoise.h"
/*
@@ -26,18 +25,15 @@ struct timerlat_params {
int dma_latency;
int no_aa;
int dump_tasks;
- int user_workload;
- int user_data;
int deepest_idle_state;
- int aa_only;
enum timerlat_tracing_mode mode;
-
- struct actions threshold_actions;
- struct actions end_actions;
};
-int timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params);
+#define to_timerlat_params(ptr) container_of(ptr, struct timerlat_params, common)
-int timerlat_hist_main(int argc, char *argv[]);
-int timerlat_top_main(int argc, char *argv[]);
+int timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params);
int timerlat_main(int argc, char *argv[]);
+int timerlat_enable(struct osnoise_tool *tool);
+void timerlat_analyze(struct osnoise_tool *tool, bool stopped);
+void timerlat_free(struct osnoise_tool *tool);
+
diff --git a/tools/tracing/rtla/src/timerlat_bpf.c b/tools/tracing/rtla/src/timerlat_bpf.c
index 03be2606f54a..e97d16646bcd 100644
--- a/tools/tracing/rtla/src/timerlat_bpf.c
+++ b/tools/tracing/rtla/src/timerlat_bpf.c
@@ -25,7 +25,7 @@ int timerlat_bpf_init(struct timerlat_params *params)
bpf->rodata->entries = params->common.hist.entries;
bpf->rodata->irq_threshold = params->common.stop_us;
bpf->rodata->thread_threshold = params->common.stop_total_us;
- bpf->rodata->aa_only = params->aa_only;
+ bpf->rodata->aa_only = params->common.aa_only;
if (params->common.hist.entries != 0) {
/* Pass histogram options */
@@ -42,7 +42,7 @@ int timerlat_bpf_init(struct timerlat_params *params)
bpf_map__set_autocreate(bpf->maps.hist_user, false);
}
- if (params->aa_only) {
+ if (params->common.aa_only) {
/* Auto-analysis only, disable summary */
bpf_map__set_autocreate(bpf->maps.summary_irq, false);
bpf_map__set_autocreate(bpf->maps.summary_thread, false);
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index d339e2cffae2..a9154f83f1a9 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -16,7 +16,6 @@
#include "timerlat.h"
#include "timerlat_aa.h"
-#include "timerlat_u.h"
#include "timerlat_bpf.h"
struct timerlat_hist_cpu {
@@ -72,8 +71,12 @@ timerlat_free_histogram(struct timerlat_hist_data *data)
/* one set of histograms per CPU */
if (data->hist)
free(data->hist);
+}
- free(data);
+static void timerlat_free_histogram_tool(struct osnoise_tool *tool)
+{
+ timerlat_free_histogram(tool->data);
+ timerlat_free(tool);
}
/*
@@ -135,7 +138,7 @@ timerlat_hist_update(struct osnoise_tool *tool, int cpu,
unsigned long long context,
unsigned long long latency)
{
- struct timerlat_params *params = tool->params;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
struct timerlat_hist_data *data = tool->data;
int entries = data->entries;
int bucket;
@@ -282,7 +285,7 @@ static int timerlat_hist_bpf_pull_data(struct osnoise_tool *tool)
*/
static void timerlat_hist_header(struct osnoise_tool *tool)
{
- struct timerlat_params *params = tool->params;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
struct timerlat_hist_data *data = tool->data;
struct trace_seq *s = tool->trace.seq;
char duration[26];
@@ -315,7 +318,7 @@ static void timerlat_hist_header(struct osnoise_tool *tool)
if (!params->common.hist.no_thread)
trace_seq_printf(s, " Thr-%03d", cpu);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(s, " Usr-%03d", cpu);
}
trace_seq_printf(s, "\n");
@@ -371,7 +374,7 @@ timerlat_print_summary(struct timerlat_params *params,
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].thread_count);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].user_count);
}
@@ -399,7 +402,7 @@ timerlat_print_summary(struct timerlat_params *params,
data->hist[cpu].min_thread,
false);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
data->hist[cpu].user_count,
data->hist[cpu].min_user,
@@ -429,7 +432,7 @@ timerlat_print_summary(struct timerlat_params *params,
data->hist[cpu].sum_thread,
true);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
data->hist[cpu].user_count,
data->hist[cpu].sum_user,
@@ -459,7 +462,7 @@ timerlat_print_summary(struct timerlat_params *params,
data->hist[cpu].max_thread,
false);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
data->hist[cpu].user_count,
data->hist[cpu].max_user,
@@ -521,7 +524,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
if (!params->common.hist.no_thread)
trace_seq_printf(trace->seq, " Thr");
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(trace->seq, " Usr");
trace_seq_printf(trace->seq, "\n");
@@ -537,7 +540,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
trace_seq_printf(trace->seq, "%9llu ",
sum.thread_count);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(trace->seq, "%9llu ",
sum.user_count);
@@ -558,7 +561,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
sum.min_thread,
false);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
sum.user_count,
sum.min_user,
@@ -581,7 +584,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
sum.sum_thread,
true);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
sum.user_count,
sum.sum_user,
@@ -604,7 +607,7 @@ timerlat_print_stats_all(struct timerlat_params *params,
sum.max_thread,
false);
- if (params->user_data)
+ if (params->common.user_data)
format_summary_value(trace->seq,
sum.user_count,
sum.max_user,
@@ -619,8 +622,9 @@ timerlat_print_stats_all(struct timerlat_params *params,
* timerlat_print_stats - print data for each CPUs
*/
static void
-timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
+timerlat_print_stats(struct osnoise_tool *tool)
{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
struct timerlat_hist_data *data = tool->data;
struct trace_instance *trace = &tool->trace;
int bucket, cpu;
@@ -654,7 +658,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
data->hist[cpu].thread[bucket]);
}
- if (params->user_data) {
+ if (params->common.user_data) {
total += data->hist[cpu].user[bucket];
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].user[bucket]);
@@ -690,7 +694,7 @@ timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].thread[data->entries]);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(trace->seq, "%9d ",
data->hist[cpu].user[data->entries]);
}
@@ -780,7 +784,7 @@ static void timerlat_hist_usage(char *usage)
/*
* timerlat_hist_parse_args - allocs, parse and fill the cmd line parameters
*/
-static struct timerlat_params
+static struct common_params
*timerlat_hist_parse_args(int argc, char *argv[])
{
struct timerlat_params *params;
@@ -794,8 +798,8 @@ static struct timerlat_params
if (!params)
exit(1);
- actions_init(¶ms->threshold_actions);
- actions_init(¶ms->end_actions);
+ actions_init(¶ms->common.threshold_actions);
+ actions_init(¶ms->common.end_actions);
/* disabled by default */
params->dma_latency = -1;
@@ -975,10 +979,10 @@ static struct timerlat_params
trace_output = "timerlat_trace.txt";
break;
case 'u':
- params->user_workload = 1;
+ params->common.user_workload = 1;
/* fallback: -u implies in -U */
case 'U':
- params->user_data = 1;
+ params->common.user_data = 1;
break;
case '0': /* no irq */
params->common.hist.no_irq = 1;
@@ -1043,14 +1047,14 @@ static struct timerlat_params
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '\5':
- retval = actions_parse(¶ms->threshold_actions, optarg);
+ retval = actions_parse(¶ms->common.threshold_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case '\6':
- retval = actions_parse(¶ms->end_actions, optarg);
+ retval = actions_parse(¶ms->common.end_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
@@ -1062,7 +1066,7 @@ static struct timerlat_params
}
if (trace_output)
- actions_add_trace_output(¶ms->threshold_actions, trace_output);
+ actions_add_trace_output(¶ms->common.threshold_actions, trace_output);
if (geteuid()) {
err_msg("rtla needs root permission\n");
@@ -1081,7 +1085,7 @@ static struct timerlat_params
if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
- if (params->common.kernel_workload && params->user_workload)
+ if (params->common.kernel_workload && params->common.user_workload)
timerlat_hist_usage("--kernel-threads and --user-threads are mutually exclusive!");
/*
@@ -1089,19 +1093,21 @@ static struct timerlat_params
* mixed mode
*/
if (params->mode == TRACING_MODE_BPF &&
- (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
- params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
+ (params->common.threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->common.end_actions.present[ACTION_TRACE_OUTPUT] ||
+ !params->no_aa))
params->mode = TRACING_MODE_MIXED;
- return params;
+ return ¶ms->common;
}
/*
* timerlat_hist_apply_config - apply the hist configs to the initialized tool
*/
static int
-timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
+timerlat_hist_apply_config(struct osnoise_tool *tool)
{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
int retval;
retval = timerlat_apply_config(tool, params);
@@ -1118,7 +1124,7 @@ timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_params *pa
* timerlat_init_hist - initialize a timerlat hist tool with parameters
*/
static struct osnoise_tool
-*timerlat_init_hist(struct timerlat_params *params)
+*timerlat_init_hist(struct common_params *params)
{
struct osnoise_tool *tool;
int nr_cpus;
@@ -1129,13 +1135,11 @@ static struct osnoise_tool
if (!tool)
return NULL;
- tool->data = timerlat_alloc_histogram(nr_cpus, params->common.hist.entries,
- params->common.hist.bucket_size);
+ tool->data = timerlat_alloc_histogram(nr_cpus, params->hist.entries,
+ params->hist.bucket_size);
if (!tool->data)
goto out_err;
- tool->params = params;
-
tep_register_event_handler(tool->trace.tep, -1, "ftrace", "timerlat",
timerlat_hist_handler, tool);
@@ -1146,349 +1150,61 @@ static struct osnoise_tool
return NULL;
}
-static int stop_tracing;
-static struct trace_instance *hist_inst = NULL;
-static void stop_hist(int sig)
-{
- if (stop_tracing) {
- /*
- * Stop requested twice in a row; abort event processing and
- * exit immediately
- */
- tracefs_iterate_stop(hist_inst->inst);
- return;
- }
- stop_tracing = 1;
- if (hist_inst)
- trace_instance_stop(hist_inst);
-}
-
-/*
- * timerlat_hist_set_signals - handles the signal to stop the tool
- */
-static void
-timerlat_hist_set_signals(struct timerlat_params *params)
+static int timerlat_hist_bpf_main_loop(struct osnoise_tool *tool)
{
- signal(SIGINT, stop_hist);
- if (params->common.duration) {
- signal(SIGALRM, stop_hist);
- alarm(params->common.duration);
- }
-}
-
-int timerlat_hist_main(int argc, char *argv[])
-{
- struct timerlat_params *params;
- struct osnoise_tool *record = NULL;
- struct timerlat_u_params params_u;
- enum result return_value = ERROR;
- struct osnoise_tool *tool = NULL;
- struct osnoise_tool *aa = NULL;
- struct trace_instance *trace;
- int dma_latency_fd = -1;
- pthread_t timerlat_u;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
int retval;
- int nr_cpus, i;
-
- params = timerlat_hist_parse_args(argc, argv);
- if (!params)
- exit(1);
-
- tool = timerlat_init_hist(params);
- if (!tool) {
- err_msg("Could not init osnoise hist\n");
- goto out_exit;
- }
-
- trace = &tool->trace;
- /*
- * Save trace instance into global variable so that SIGINT can stop
- * the timerlat tracer.
- * Otherwise, rtla could loop indefinitely when overloaded.
- */
- hist_inst = trace;
-
- /*
- * Try to enable BPF, unless disabled explicitly.
- * If BPF enablement fails, fall back to tracefs mode.
- */
- if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
- debug_msg("RTLA_NO_BPF set, disabling BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- } else if (!tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
- debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- } else {
- retval = timerlat_bpf_init(params);
- if (retval) {
- debug_msg("Could not enable BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- }
- }
-
- retval = timerlat_hist_apply_config(tool, params);
- if (retval) {
- err_msg("Could not apply config\n");
- goto out_free;
- }
-
- retval = enable_timerlat(trace);
- if (retval) {
- err_msg("Failed to enable timerlat tracer\n");
- goto out_free;
- }
-
- if (params->common.set_sched) {
- retval = set_comm_sched_attr("timerlat/", ¶ms->common.sched_param);
- if (retval) {
- err_msg("Failed to set sched parameters\n");
- goto out_free;
- }
- }
-
- if (params->common.cgroup && !params->user_workload) {
- retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
- if (!retval) {
- err_msg("Failed to move threads to cgroup\n");
- goto out_free;
- }
- }
-
- if (params->dma_latency >= 0) {
- dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
- if (dma_latency_fd < 0) {
- err_msg("Could not set /dev/cpu_dma_latency.\n");
- goto out_free;
- }
- }
-
- if (params->deepest_idle_state >= -1) {
- if (!have_libcpupower_support()) {
- err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
- goto out_free;
- }
-
- nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
-
- for (i = 0; i < nr_cpus; i++) {
- if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
- continue;
- if (save_cpu_idle_disable_state(i) < 0) {
- err_msg("Could not save cpu idle state.\n");
- goto out_free;
- }
- if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
- err_msg("Could not set deepest cpu idle state.\n");
- goto out_free;
- }
- }
- }
-
- 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->threshold_actions.trace_output_inst = record->trace.inst;
- params->end_actions.trace_output_inst = record->trace.inst;
-
- if (params->common.events) {
- retval = trace_events_enable(&record->trace, params->common.events);
- if (retval)
- goto out_hist;
- }
- if (params->common.buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
- if (retval)
- goto out_hist;
- }
- }
+ while (!stop_tracing) {
+ timerlat_bpf_wait(-1);
- if (!params->no_aa) {
- aa = osnoise_init_tool("timerlat_aa");
- if (!aa)
- goto out_hist;
+ if (!stop_tracing) {
+ /* Threshold overflow, perform actions on threshold */
+ actions_perform(¶ms->common.threshold_actions);
- retval = timerlat_aa_init(aa, params->dump_tasks);
- if (retval) {
- err_msg("Failed to enable the auto analysis instance\n");
- goto out_hist;
- }
+ if (!params->common.threshold_actions.continue_flag)
+ /* continue flag not set, break */
+ break;
- retval = enable_timerlat(&aa->trace);
- if (retval) {
- err_msg("Failed to enable timerlat tracer\n");
- goto out_hist;
+ /* continue action reached, re-enable tracing */
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ if (tool->aa)
+ trace_instance_start(&tool->aa->trace);
+ timerlat_bpf_restart_tracing();
}
}
+ timerlat_bpf_detach();
- if (params->user_workload) {
- /* rtla asked to stop */
- params_u.should_run = 1;
- /* all threads left */
- params_u.stopped_running = 0;
-
- params_u.set = ¶ms->common.monitored_cpus;
- if (params->common.set_sched)
- params_u.sched_param = ¶ms->common.sched_param;
- else
- params_u.sched_param = NULL;
-
- params_u.cgroup_name = params->common.cgroup_name;
-
- retval = pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, ¶ms_u);
- if (retval)
- err_msg("Error creating timerlat user-space threads\n");
- }
-
- if (params->common.warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->common.warmup);
- sleep(params->common.warmup);
- if (stop_tracing)
- goto out_hist;
- }
-
- /*
- * Start the tracers here, after having set all instances.
- *
- * Let the trace instance start first for the case of hitting a stop
- * tracing while enabling other instances. The trace instance is the
- * one with most valuable information.
- */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
- if (params->mode == TRACING_MODE_TRACEFS) {
- trace_instance_start(trace);
- } else {
- retval = timerlat_bpf_attach();
- if (retval) {
- err_msg("Error attaching BPF program\n");
- goto out_hist;
- }
- }
-
- tool->start_time = time(NULL);
- timerlat_hist_set_signals(params);
-
- if (params->mode == TRACING_MODE_TRACEFS) {
- while (!stop_tracing) {
- sleep(params->common.sleep_time);
-
- retval = tracefs_iterate_raw_events(trace->tep,
- trace->inst,
- NULL,
- 0,
- collect_registered_events,
- trace);
- if (retval < 0) {
- err_msg("Error iterating on events\n");
- goto out_hist;
- }
-
- if (osnoise_trace_is_off(tool, record)) {
- actions_perform(¶ms->threshold_actions);
-
- if (!params->threshold_actions.continue_flag)
- /* continue flag not set, break */
- break;
-
- /* continue action reached, re-enable tracing */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
- trace_instance_start(trace);
- }
-
- /* is there still any user-threads ? */
- if (params->user_workload) {
- if (params_u.stopped_running) {
- debug_msg("timerlat user-space threads stopped!\n");
- break;
- }
- }
- }
- } else {
- while (!stop_tracing) {
- timerlat_bpf_wait(-1);
-
- if (!stop_tracing) {
- /* Threshold overflow, perform actions on threshold */
- actions_perform(¶ms->threshold_actions);
-
- if (!params->threshold_actions.continue_flag)
- /* continue flag not set, break */
- break;
-
- /* continue action reached, re-enable tracing */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
- timerlat_bpf_restart_tracing();
- }
- }
- }
-
- if (params->mode != TRACING_MODE_TRACEFS) {
- timerlat_bpf_detach();
- retval = timerlat_hist_bpf_pull_data(tool);
- if (retval) {
- err_msg("Error pulling BPF data\n");
- goto out_hist;
- }
- }
-
- if (params->user_workload && !params_u.stopped_running) {
- params_u.should_run = 0;
- sleep(1);
- }
-
- timerlat_print_stats(params, tool);
-
- actions_perform(¶ms->end_actions);
-
- return_value = PASSED;
+ retval = timerlat_hist_bpf_pull_data(tool);
+ if (retval)
+ err_msg("Error pulling BPF data\n");
- if (osnoise_trace_is_off(tool, record) && !stop_tracing) {
- printf("rtla timerlat hit stop tracing\n");
+ return retval;
+}
- if (!params->no_aa)
- timerlat_auto_analysis(params->common.stop_us,
- params->common.stop_total_us);
+static int timerlat_hist_main(struct osnoise_tool *tool)
+{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
+ int retval;
- return_value = FAILED;
- }
+ if (params->mode == TRACING_MODE_TRACEFS)
+ retval = hist_main_loop(tool);
+ else
+ retval = timerlat_hist_bpf_main_loop(tool);
-out_hist:
- timerlat_aa_destroy();
- if (dma_latency_fd >= 0)
- close(dma_latency_fd);
- if (params->deepest_idle_state >= -1) {
- for (i = 0; i < nr_cpus; i++) {
- if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
- continue;
- restore_cpu_idle_disable_state(i);
- }
- }
- trace_events_destroy(&record->trace, params->common.events);
- params->common.events = NULL;
-out_free:
- timerlat_free_histogram(tool->data);
- osnoise_destroy_tool(aa);
- osnoise_destroy_tool(record);
- osnoise_destroy_tool(tool);
- actions_destroy(¶ms->threshold_actions);
- actions_destroy(¶ms->end_actions);
- if (params->mode != TRACING_MODE_TRACEFS)
- timerlat_bpf_destroy();
- free(params);
- free_cpu_idle_disable_states();
-out_exit:
- exit(return_value);
+ return retval;
}
+
+struct tool_ops timerlat_hist_ops = {
+ .tracer = "timerlat",
+ .comm_prefix = "timerlat/",
+ .parse_args = timerlat_hist_parse_args,
+ .init_tool = timerlat_init_hist,
+ .apply_config = timerlat_hist_apply_config,
+ .enable = timerlat_enable,
+ .main = timerlat_hist_main,
+ .print_stats = timerlat_print_stats,
+ .analyze = timerlat_analyze,
+ .free = timerlat_free_histogram_tool,
+};
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index bb42697d2575..4f1ce72d6a05 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -17,7 +17,6 @@
#include "timerlat.h"
#include "timerlat_aa.h"
-#include "timerlat_u.h"
#include "timerlat_bpf.h"
struct timerlat_top_cpu {
@@ -49,13 +48,18 @@ struct timerlat_top_data {
/*
* timerlat_free_top - free runtime data
*/
-static void
-timerlat_free_top(struct timerlat_top_data *data)
+static void timerlat_free_top(struct timerlat_top_data *data)
{
free(data->cpu_data);
free(data);
}
+static void timerlat_free_top_tool(struct osnoise_tool *tool)
+{
+ timerlat_free_top(tool->data);
+ timerlat_free(tool);
+}
+
/*
* timerlat_alloc_histogram - alloc runtime data
*/
@@ -128,7 +132,7 @@ timerlat_top_update(struct osnoise_tool *tool, int cpu,
unsigned long long thread,
unsigned long long latency)
{
- struct timerlat_params *params = tool->params;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
struct timerlat_top_data *data = tool->data;
struct timerlat_top_cpu *cpu_data = &data->cpu_data[cpu];
@@ -164,15 +168,13 @@ timerlat_top_handler(struct trace_seq *s, struct tep_record *record,
struct tep_event *event, void *context)
{
struct trace_instance *trace = context;
- struct timerlat_params *params;
unsigned long long latency, thread;
struct osnoise_tool *top;
int cpu = record->cpu;
top = container_of(trace, struct osnoise_tool, trace);
- params = top->params;
- if (!params->aa_only) {
+ if (!top->params->aa_only) {
tep_get_field_val(s, event, "context", record, &thread, 1);
tep_get_field_val(s, event, "timer_latency", record, &latency, 1);
@@ -267,7 +269,7 @@ static void timerlat_top_header(struct timerlat_params *params, struct osnoise_t
trace_seq_printf(s, "\033[2;37;40m");
trace_seq_printf(s, " Timer Latency ");
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(s, " ");
if (pretty)
@@ -278,7 +280,7 @@ static void timerlat_top_header(struct timerlat_params *params, struct osnoise_t
params->common.output_divisor == 1 ? "ns" : "us",
params->common.output_divisor == 1 ? "ns" : "us");
- if (params->user_data) {
+ if (params->common.user_data) {
trace_seq_printf(s, " | Ret user Timer Latency (%s)",
params->common.output_divisor == 1 ? "ns" : "us");
}
@@ -288,7 +290,7 @@ static void timerlat_top_header(struct timerlat_params *params, struct osnoise_t
trace_seq_printf(s, "\033[2;30;47m");
trace_seq_printf(s, "CPU COUNT | cur min avg max | cur min avg max");
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(s, " | cur min avg max");
if (pretty)
@@ -303,8 +305,7 @@ static const char *no_value = " -";
*/
static void timerlat_top_print(struct osnoise_tool *top, int cpu)
{
-
- struct timerlat_params *params = top->params;
+ struct timerlat_params *params = to_timerlat_params(top->params);
struct timerlat_top_data *data = top->data;
struct timerlat_top_cpu *cpu_data = &data->cpu_data[cpu];
struct trace_seq *s = top->trace.seq;
@@ -339,7 +340,7 @@ static void timerlat_top_print(struct osnoise_tool *top, int cpu)
trace_seq_printf(s, "%9llu", cpu_data->max_thread);
}
- if (!params->user_data) {
+ if (!params->common.user_data) {
trace_seq_printf(s, "\n");
return;
}
@@ -364,7 +365,7 @@ static void
timerlat_top_print_sum(struct osnoise_tool *top, struct timerlat_top_cpu *summary)
{
const char *split = "----------------------------------------";
- struct timerlat_params *params = top->params;
+ struct timerlat_params *params = to_timerlat_params(top->params);
unsigned long long count = summary->irq_count;
struct trace_seq *s = top->trace.seq;
int e = 0;
@@ -381,7 +382,7 @@ timerlat_top_print_sum(struct osnoise_tool *top, struct timerlat_top_cpu *summar
}
trace_seq_printf(s, "%.*s|%.*s|%.*s", 15, split, 40, split, 39, split);
- if (params->user_data)
+ if (params->common.user_data)
trace_seq_printf(s, "-|%.*s", 39, split);
trace_seq_printf(s, "\n");
@@ -406,7 +407,7 @@ timerlat_top_print_sum(struct osnoise_tool *top, struct timerlat_top_cpu *summar
trace_seq_printf(s, "%9llu", summary->max_thread);
}
- if (!params->user_data) {
+ if (!params->common.user_data) {
trace_seq_printf(s, "\n");
return;
}
@@ -437,14 +438,15 @@ static void clear_terminal(struct trace_seq *seq)
* timerlat_print_stats - print data for all cpus
*/
static void
-timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *top)
+timerlat_print_stats(struct osnoise_tool *top)
{
+ struct timerlat_params *params = to_timerlat_params(top->params);
struct trace_instance *trace = &top->trace;
struct timerlat_top_cpu summary;
static int nr_cpus = -1;
int i;
- if (params->aa_only)
+ if (params->common.aa_only)
return;
if (nr_cpus == -1)
@@ -540,7 +542,7 @@ static void timerlat_top_usage(char *usage)
/*
* timerlat_top_parse_args - allocs, parse and fill the cmd line parameters
*/
-static struct timerlat_params
+static struct common_params
*timerlat_top_parse_args(int argc, char **argv)
{
struct timerlat_params *params;
@@ -554,8 +556,8 @@ static struct timerlat_params
if (!params)
exit(1);
- actions_init(¶ms->threshold_actions);
- actions_init(¶ms->end_actions);
+ actions_init(¶ms->common.threshold_actions);
+ actions_init(¶ms->common.end_actions);
/* disabled by default */
params->dma_latency = -1;
@@ -641,7 +643,7 @@ static struct timerlat_params
params->print_stack = auto_thresh;
/* set aa_only to avoid parsing the trace */
- params->aa_only = 1;
+ params->common.aa_only = 1;
break;
case 'c':
retval = parse_cpu_set(optarg, ¶ms->common.monitored_cpus);
@@ -731,10 +733,10 @@ static struct timerlat_params
trace_output = "timerlat_trace.txt";
break;
case 'u':
- params->user_workload = true;
+ params->common.user_workload = true;
/* fallback: -u implies -U */
case 'U':
- params->user_data = true;
+ params->common.user_data = true;
break;
case '0': /* trigger */
if (params->common.events) {
@@ -781,14 +783,14 @@ static struct timerlat_params
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '9':
- retval = actions_parse(¶ms->threshold_actions, optarg);
+ retval = actions_parse(¶ms->common.threshold_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case '\1':
- retval = actions_parse(¶ms->end_actions, optarg);
+ retval = actions_parse(¶ms->common.end_actions, optarg);
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
@@ -800,7 +802,7 @@ static struct timerlat_params
}
if (trace_output)
- actions_add_trace_output(¶ms->threshold_actions, trace_output);
+ actions_add_trace_output(¶ms->common.threshold_actions, trace_output);
if (geteuid()) {
err_msg("rtla needs root permission\n");
@@ -813,10 +815,10 @@ static struct timerlat_params
if (!params->common.stop_us && !params->common.stop_total_us)
params->no_aa = 1;
- if (params->no_aa && params->aa_only)
+ if (params->no_aa && params->common.aa_only)
timerlat_top_usage("--no-aa and --aa-only are mutually exclusive!");
- if (params->common.kernel_workload && params->user_workload)
+ if (params->common.kernel_workload && params->common.user_workload)
timerlat_top_usage("--kernel-threads and --user-threads are mutually exclusive!");
/*
@@ -824,19 +826,21 @@ static struct timerlat_params
* mixed mode
*/
if (params->mode == TRACING_MODE_BPF &&
- (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
- params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa))
+ (params->common.threshold_actions.present[ACTION_TRACE_OUTPUT] ||
+ params->common.end_actions.present[ACTION_TRACE_OUTPUT] ||
+ !params->no_aa))
params->mode = TRACING_MODE_MIXED;
- return params;
+ return ¶ms->common;
}
/*
* timerlat_top_apply_config - apply the top configs to the initialized tool
*/
static int
-timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_params *params)
+timerlat_top_apply_config(struct osnoise_tool *top)
{
+ struct timerlat_params *params = to_timerlat_params(top->params);
int retval;
retval = timerlat_apply_config(top, params);
@@ -856,7 +860,7 @@ timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_params *para
* timerlat_init_top - initialize a timerlat top tool with parameters
*/
static struct osnoise_tool
-*timerlat_init_top(struct timerlat_params *params)
+*timerlat_init_top(struct common_params *params)
{
struct osnoise_tool *top;
int nr_cpus;
@@ -871,8 +875,6 @@ static struct osnoise_tool
if (!top->data)
goto out_err;
- top->params = params;
-
tep_register_event_handler(top->trace.tep, -1, "ftrace", "timerlat",
timerlat_top_handler, top);
@@ -883,109 +885,16 @@ static struct osnoise_tool
return NULL;
}
-static int stop_tracing;
-static struct trace_instance *top_inst = NULL;
-static void stop_top(int sig)
-{
- if (stop_tracing) {
- /*
- * Stop requested twice in a row; abort event processing and
- * exit immediately
- */
- tracefs_iterate_stop(top_inst->inst);
- return;
- }
- stop_tracing = 1;
- if (top_inst)
- trace_instance_stop(top_inst);
-}
-
-/*
- * timerlat_top_set_signals - handles the signal to stop the tool
- */
-static void
-timerlat_top_set_signals(struct timerlat_params *params)
-{
- signal(SIGINT, stop_top);
- if (params->common.duration) {
- signal(SIGALRM, stop_top);
- alarm(params->common.duration);
- }
-}
-
-/*
- * timerlat_top_main_loop - main loop to process events
- */
-static int
-timerlat_top_main_loop(struct osnoise_tool *top,
- struct osnoise_tool *record,
- struct osnoise_tool *aa,
- struct timerlat_params *params,
- struct timerlat_u_params *params_u)
-{
- struct trace_instance *trace = &top->trace;
- int retval;
-
- while (!stop_tracing) {
- sleep(params->common.sleep_time);
-
- if (params->aa_only && !osnoise_trace_is_off(top, record))
- continue;
-
- retval = tracefs_iterate_raw_events(trace->tep,
- trace->inst,
- NULL,
- 0,
- collect_registered_events,
- trace);
- if (retval < 0) {
- err_msg("Error iterating on events\n");
- return retval;
- }
-
- if (!params->common.quiet)
- timerlat_print_stats(params, top);
-
- if (osnoise_trace_is_off(top, record)) {
- actions_perform(¶ms->threshold_actions);
-
- if (!params->threshold_actions.continue_flag)
- /* continue flag not set, break */
- break;
-
- /* continue action reached, re-enable tracing */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
- trace_instance_start(trace);
- }
-
- /* is there still any user-threads ? */
- if (params->user_workload) {
- if (params_u->stopped_running) {
- debug_msg("timerlat user space threads stopped!\n");
- break;
- }
- }
- }
-
- return 0;
-}
-
/*
* timerlat_top_bpf_main_loop - main loop to process events (BPF variant)
*/
static int
-timerlat_top_bpf_main_loop(struct osnoise_tool *top,
- struct osnoise_tool *record,
- struct osnoise_tool *aa,
- struct timerlat_params *params,
- struct timerlat_u_params *params_u)
+timerlat_top_bpf_main_loop(struct osnoise_tool *tool)
{
+ struct timerlat_params *params = to_timerlat_params(tool->params);
int retval, wait_retval;
- if (params->aa_only) {
+ if (params->common.aa_only) {
/* Auto-analysis only, just wait for stop tracing */
timerlat_bpf_wait(-1);
return 0;
@@ -996,34 +905,34 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
wait_retval = timerlat_bpf_wait(params->common.quiet ? -1 :
params->common.sleep_time);
- retval = timerlat_top_bpf_pull_data(top);
+ retval = timerlat_top_bpf_pull_data(tool);
if (retval) {
err_msg("Error pulling BPF data\n");
return retval;
}
if (!params->common.quiet)
- timerlat_print_stats(params, top);
+ timerlat_print_stats(tool);
if (wait_retval == 1) {
/* Stopping requested by tracer */
- actions_perform(¶ms->threshold_actions);
+ actions_perform(¶ms->common.threshold_actions);
- if (!params->threshold_actions.continue_flag)
+ if (!params->common.threshold_actions.continue_flag)
/* continue flag not set, break */
break;
/* continue action reached, re-enable tracing */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
+ if (tool->record)
+ trace_instance_start(&tool->record->trace);
+ if (tool->aa)
+ trace_instance_start(&tool->aa->trace);
timerlat_bpf_restart_tracing();
}
/* is there still any user-threads ? */
- if (params->user_workload) {
- if (params_u->stopped_running) {
+ if (params->common.user_workload) {
+ if (params->common.user.stopped_running) {
debug_msg("timerlat user space threads stopped!\n");
break;
}
@@ -1033,274 +942,30 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top,
return 0;
}
-int timerlat_top_main(int argc, char *argv[])
+static int timerlat_top_main_loop(struct osnoise_tool *tool)
{
- struct timerlat_params *params;
- struct osnoise_tool *record = NULL;
- struct timerlat_u_params params_u;
- enum result return_value = ERROR;
- struct osnoise_tool *top = NULL;
- struct osnoise_tool *aa = NULL;
- struct trace_instance *trace;
- int dma_latency_fd = -1;
- pthread_t timerlat_u;
- char *max_lat;
+ struct timerlat_params *params = to_timerlat_params(tool->params);
int retval;
- int nr_cpus, i;
-
- params = timerlat_top_parse_args(argc, argv);
- if (!params)
- exit(1);
-
- top = timerlat_init_top(params);
- if (!top) {
- err_msg("Could not init osnoise top\n");
- goto out_exit;
- }
-
- trace = &top->trace;
- /*
- * Save trace instance into global variable so that SIGINT can stop
- * the timerlat tracer.
- * Otherwise, rtla could loop indefinitely when overloaded.
- */
- top_inst = trace;
-
- /*
- * Try to enable BPF, unless disabled explicitly.
- * If BPF enablement fails, fall back to tracefs mode.
- */
- if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
- debug_msg("RTLA_NO_BPF set, disabling BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- } else if (!tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
- debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- } else {
- retval = timerlat_bpf_init(params);
- if (retval) {
- debug_msg("Could not enable BPF\n");
- params->mode = TRACING_MODE_TRACEFS;
- }
- }
-
- retval = timerlat_top_apply_config(top, params);
- if (retval) {
- err_msg("Could not apply config\n");
- goto out_free;
- }
- retval = enable_timerlat(trace);
- if (retval) {
- err_msg("Failed to enable timerlat tracer\n");
- goto out_free;
- }
-
- if (params->common.set_sched) {
- retval = set_comm_sched_attr("timerlat/", ¶ms->common.sched_param);
- if (retval) {
- err_msg("Failed to set sched parameters\n");
- goto out_free;
- }
- }
-
- if (params->common.cgroup && !params->user_data) {
- retval = set_comm_cgroup("timerlat/", params->common.cgroup_name);
- if (!retval) {
- err_msg("Failed to move threads to cgroup\n");
- goto out_free;
- }
- }
-
- if (params->dma_latency >= 0) {
- dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
- if (dma_latency_fd < 0) {
- err_msg("Could not set /dev/cpu_dma_latency.\n");
- goto out_free;
- }
- }
-
- if (params->deepest_idle_state >= -1) {
- if (!have_libcpupower_support()) {
- err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
- goto out_free;
- }
-
- nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
-
- for (i = 0; i < nr_cpus; i++) {
- if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
- continue;
- if (save_cpu_idle_disable_state(i) < 0) {
- err_msg("Could not save cpu idle state.\n");
- goto out_free;
- }
- if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
- err_msg("Could not set deepest cpu idle state.\n");
- goto out_free;
- }
- }
- }
-
- 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->threshold_actions.trace_output_inst = record->trace.inst;
- params->end_actions.trace_output_inst = record->trace.inst;
-
- if (params->common.events) {
- retval = trace_events_enable(&record->trace, params->common.events);
- if (retval)
- goto out_top;
- }
-
- if (params->common.buffer_size > 0) {
- retval = trace_set_buffer_size(&record->trace, params->common.buffer_size);
- if (retval)
- goto out_top;
- }
- }
-
- if (!params->no_aa) {
- aa = osnoise_init_tool("timerlat_aa");
- if (!aa)
- goto out_top;
-
- retval = timerlat_aa_init(aa, params->dump_tasks);
- if (retval) {
- err_msg("Failed to enable the auto analysis instance\n");
- goto out_top;
- }
-
- /* if it is re-using the main instance, there is no need to start it */
- if (aa != top) {
- retval = enable_timerlat(&aa->trace);
- if (retval) {
- err_msg("Failed to enable timerlat tracer\n");
- goto out_top;
- }
- }
- }
-
- if (params->user_workload) {
- /* rtla asked to stop */
- params_u.should_run = 1;
- /* all threads left */
- params_u.stopped_running = 0;
-
- params_u.set = ¶ms->common.monitored_cpus;
- if (params->common.set_sched)
- params_u.sched_param = ¶ms->common.sched_param;
- else
- params_u.sched_param = NULL;
-
- params_u.cgroup_name = params->common.cgroup_name;
-
- retval = pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, ¶ms_u);
- if (retval)
- err_msg("Error creating timerlat user-space threads\n");
- }
-
- if (params->common.warmup > 0) {
- debug_msg("Warming up for %d seconds\n", params->common.warmup);
- sleep(params->common.warmup);
- }
-
- /*
- * Start the tracers here, after having set all instances.
- *
- * Let the trace instance start first for the case of hitting a stop
- * tracing while enabling other instances. The trace instance is the
- * one with most valuable information.
- */
- if (record)
- trace_instance_start(&record->trace);
- if (!params->no_aa)
- trace_instance_start(&aa->trace);
if (params->mode == TRACING_MODE_TRACEFS) {
- trace_instance_start(trace);
+ retval = top_main_loop(tool);
} else {
- retval = timerlat_bpf_attach();
- if (retval) {
- err_msg("Error attaching BPF program\n");
- goto out_top;
- }
- }
-
- top->start_time = time(NULL);
- timerlat_top_set_signals(params);
-
- if (params->mode == TRACING_MODE_TRACEFS)
- retval = timerlat_top_main_loop(top, record, aa, params, ¶ms_u);
- else
- retval = timerlat_top_bpf_main_loop(top, record, aa, params, ¶ms_u);
-
- if (retval)
- goto out_top;
-
- if (params->mode != TRACING_MODE_TRACEFS)
+ retval = timerlat_top_bpf_main_loop(tool);
timerlat_bpf_detach();
-
- if (params->user_workload && !params_u.stopped_running) {
- params_u.should_run = 0;
- sleep(1);
}
- timerlat_print_stats(params, top);
-
- actions_perform(¶ms->end_actions);
-
- return_value = PASSED;
-
- if (osnoise_trace_is_off(top, record) && !stop_tracing) {
- printf("rtla timerlat hit stop tracing\n");
-
- if (!params->no_aa)
- timerlat_auto_analysis(params->common.stop_us,
- params->common.stop_total_us);
-
- return_value = FAILED;
- } else if (params->aa_only) {
- /*
- * If the trace did not stop with --aa-only, at least print the
- * max known latency.
- */
- max_lat = tracefs_instance_file_read(trace->inst, "tracing_max_latency", NULL);
- if (max_lat) {
- printf(" Max latency was %s\n", max_lat);
- free(max_lat);
- }
- }
-
-out_top:
- timerlat_aa_destroy();
- if (dma_latency_fd >= 0)
- close(dma_latency_fd);
- if (params->deepest_idle_state >= -1) {
- for (i = 0; i < nr_cpus; i++) {
- if (params->common.cpus && !CPU_ISSET(i, ¶ms->common.monitored_cpus))
- continue;
- restore_cpu_idle_disable_state(i);
- }
- }
- trace_events_destroy(&record->trace, params->common.events);
- params->common.events = NULL;
-out_free:
- timerlat_free_top(top->data);
- if (aa && aa != top)
- osnoise_destroy_tool(aa);
- osnoise_destroy_tool(record);
- osnoise_destroy_tool(top);
- actions_destroy(¶ms->threshold_actions);
- actions_destroy(¶ms->end_actions);
- if (params->mode != TRACING_MODE_TRACEFS)
- timerlat_bpf_destroy();
- free(params);
- free_cpu_idle_disable_states();
-out_exit:
- exit(return_value);
+ return retval;
}
+
+struct tool_ops timerlat_top_ops = {
+ .tracer = "timerlat",
+ .comm_prefix = "timerlat/",
+ .parse_args = timerlat_top_parse_args,
+ .init_tool = timerlat_init_top,
+ .apply_config = timerlat_top_apply_config,
+ .enable = timerlat_enable,
+ .main = timerlat_top_main_loop,
+ .print_stats = timerlat_print_stats,
+ .analyze = timerlat_analyze,
+ .free = timerlat_free_top_tool,
+};
diff --git a/tools/tracing/rtla/src/trace.h b/tools/tracing/rtla/src/trace.h
index 3cd40dd3f06c..1e5aee4b828d 100644
--- a/tools/tracing/rtla/src/trace.h
+++ b/tools/tracing/rtla/src/trace.h
@@ -30,9 +30,6 @@ struct trace_seq *get_trace_seq(void);
int enable_tracer_by_name(struct tracefs_instance *inst, const char *tracer_name);
void disable_tracer(struct tracefs_instance *inst);
-int enable_osnoise(struct trace_instance *trace);
-int enable_timerlat(struct trace_instance *trace);
-
struct tracefs_instance *create_instance(char *instance_name);
void destroy_instance(struct tracefs_instance *inst);
--
2.48.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 5/7] tools/rtla: Fix -A option name in test comment
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (3 preceding siblings ...)
2025-09-07 2:23 ` [PATCH v2 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top Crystal Wood
@ 2025-09-07 2:23 ` Crystal Wood
2025-09-07 2:23 ` [PATCH v2 6/7] tools/rtla: Add test engine support for unexpected output Crystal Wood
` (3 subsequent siblings)
8 siblings, 0 replies; 16+ messages in thread
From: Crystal Wood @ 2025-09-07 2:23 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
This was changed to --on-threshold when the patches were applied.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
tools/tracing/rtla/tests/timerlat.t | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/tracing/rtla/tests/timerlat.t b/tools/tracing/rtla/tests/timerlat.t
index c71aed5534bf..b5d1e7260a9b 100644
--- a/tools/tracing/rtla/tests/timerlat.t
+++ b/tools/tracing/rtla/tests/timerlat.t
@@ -47,9 +47,9 @@ check "trace output through -t" \
"timerlat hist -T 2 -t" 2 "^ Saving trace to timerlat_trace.txt$"
check "trace output through -t with custom filename" \
"timerlat hist -T 2 -t custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
-check "trace output through -A trace" \
+check "trace output through --on-threshold trace" \
"timerlat hist -T 2 --on-threshold trace" 2 "^ Saving trace to timerlat_trace.txt$"
-check "trace output through -A trace with custom filename" \
+check "trace output through --on-threshold trace with custom filename" \
"timerlat hist -T 2 --on-threshold trace,file=custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
check "exec command" \
"timerlat hist -T 2 --on-threshold shell,command='echo TestOutput'" 2 "^TestOutput$"
--
2.48.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 6/7] tools/rtla: Add test engine support for unexpected output
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (4 preceding siblings ...)
2025-09-07 2:23 ` [PATCH v2 5/7] tools/rtla: Fix -A option name in test comment Crystal Wood
@ 2025-09-07 2:23 ` Crystal Wood
2025-09-08 14:48 ` Crystal Wood
2025-09-07 2:23 ` [PATCH v2 7/7] tools/rtla: Add remaining support for osnoise actions Crystal Wood
` (2 subsequent siblings)
8 siblings, 1 reply; 16+ messages in thread
From: Crystal Wood @ 2025-09-07 2:23 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
Add a check() parameter to indicate which text must not appear in the
output.
Simplify the code so that we can print failures as they happen rather
than trying to figure out what went wrong after printing "not ok". This
also means that "not ok" gets printed after the info rather than before,
which seems more intuitive anyway.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
v2: Preserved the original ordering of "not ok" versus diagnostics as per
convention
---
tools/tracing/rtla/tests/engine.sh | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/tools/tracing/rtla/tests/engine.sh b/tools/tracing/rtla/tests/engine.sh
index a97d644ead99..c7de3d6ed6a8 100644
--- a/tools/tracing/rtla/tests/engine.sh
+++ b/tools/tracing/rtla/tests/engine.sh
@@ -43,6 +43,7 @@ check() {
tested_command=$1
expected_exitcode=${3:-0}
expected_output=$4
+ unexpected_output=$5
# Simple check: run rtla with given arguments and test exit code.
# If TEST_COUNT is set, run the test. Otherwise, just count.
ctr=$(($ctr + 1))
@@ -53,24 +54,33 @@ check() {
# Run rtla; in case of failure, include its output as comment
# in the test results.
result=$(eval stdbuf -oL $TIMEOUT "$RTLA" $2 2>&1); exitcode=$?
+ failbuf=''
+ fail=0
+
# Test if the results matches if requested
- if [ -n "$expected_output" ]
+ if [ -n "$expected_output" ] && ! grep -qE "$expected_output" <<< "$result"
then
- grep -E "$expected_output" <<< "$result" > /dev/null; grep_result=$?
- else
- grep_result=0
+ fail=1
+ failbuf+=$(printf "# Output match failed: \"%s\"" "$expected_output")
+ failbuf+=$'\n'
fi
- if [ $exitcode -eq $expected_exitcode ] && [ $grep_result -eq 0 ]
+ if [ -n "$unexpected_output" ] && grep -qE "$unexpected_output" <<< "$result"
+ then
+ fail=1
+ failbuf+=$(printf "# Output non-match failed: \"%s\"" "$unexpected_output")
+ failbuf+=$'\n'
+ fi
+
+ if [ $exitcode -eq $expected_exitcode ] && [ $fail -eq 0 ]
then
echo "ok $ctr - $1"
else
- echo "not ok $ctr - $1"
# Add rtla output and exit code as comments in case of failure
+ echo "not ok $ctr - $1"
+ echo -n "$failbuf"
echo "$result" | col -b | while read line; do echo "# $line"; done
printf "#\n# exit code %s\n" $exitcode
- [ -n "$expected_output" ] && [ $grep_result -ne 0 ] && \
- printf "# Output match failed: \"%s\"\n" "$expected_output"
fi
fi
}
--
2.48.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 7/7] tools/rtla: Add remaining support for osnoise actions
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (5 preceding siblings ...)
2025-09-07 2:23 ` [PATCH v2 6/7] tools/rtla: Add test engine support for unexpected output Crystal Wood
@ 2025-09-07 2:23 ` Crystal Wood
2025-09-09 11:25 ` [PATCH v2 0/7] tools/rtla: Code consolidation and " Tomas Glozar
2025-09-26 14:19 ` Tomas Glozar
8 siblings, 0 replies; 16+ messages in thread
From: Crystal Wood @ 2025-09-07 2:23 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin,
Crystal Wood
The basic functionality came with the consolidation; now hook up the
command line options, and add documentation and tests.
Signed-off-by: Crystal Wood <crwood@redhat.com>
---
v2: Changed osnoise --on-threshold performance note as requested by Tomas
---
Documentation/tools/rtla/common_options.rst | 61 +++++++++++++++
.../tools/rtla/common_osnoise_options.rst | 8 ++
.../tools/rtla/common_timerlat_options.rst | 74 +++----------------
Documentation/tools/rtla/rtla-hwnoise.rst | 2 +
.../tools/rtla/rtla-osnoise-hist.rst | 2 +
Documentation/tools/rtla/rtla-osnoise-top.rst | 2 +
.../tools/rtla/rtla-timerlat-hist.rst | 2 +
.../tools/rtla/rtla-timerlat-top.rst | 2 +
tools/tracing/rtla/src/actions.c | 8 +-
tools/tracing/rtla/src/actions.h | 2 +-
tools/tracing/rtla/src/osnoise_hist.c | 20 +++++
tools/tracing/rtla/src/osnoise_top.c | 20 +++++
tools/tracing/rtla/src/timerlat_hist.c | 6 +-
tools/tracing/rtla/src/timerlat_top.c | 6 +-
tools/tracing/rtla/tests/osnoise.t | 27 ++++++-
15 files changed, 168 insertions(+), 74 deletions(-)
diff --git a/Documentation/tools/rtla/common_options.rst b/Documentation/tools/rtla/common_options.rst
index 2dc1575210aa..77ef35d3f831 100644
--- a/Documentation/tools/rtla/common_options.rst
+++ b/Documentation/tools/rtla/common_options.rst
@@ -53,6 +53,67 @@
**--trace-buffer-size** *kB*
Set the per-cpu trace buffer size in kB for the tracing output.
+**--on-threshold** *action*
+
+ Defines an action to be executed when tracing is stopped on a latency threshold
+ specified by |threshold|.
+
+ Multiple --on-threshold actions may be specified, and they will be executed in
+ the order they are provided. If any action fails, subsequent actions in the list
+ will not be executed.
+
+ Supported actions are:
+
+ - *trace[,file=<filename>]*
+
+ Saves trace output, optionally taking a filename. Alternative to -t/--trace.
+ Note that nlike -t/--trace, specifying this multiple times will result in
+ the trace being saved multiple times.
+
+ - *signal,num=<sig>,pid=<pid>*
+
+ Sends signal to process. "parent" might be specified in place of pid to target
+ the parent process of rtla.
+
+ - *shell,command=<command>*
+
+ Execute shell command.
+
+ - *continue*
+
+ Continue tracing after actions are executed instead of stopping.
+
+ Example:
+
+ $ rtla |tool| |thresharg| 20 --on-threshold trace
+ --on-threshold shell,command="grep ipi_send |tracer|\_trace.txt"
+ --on-threshold signal,num=2,pid=parent
+
+ This will save a trace with the default filename "|tracer|\_trace.txt", print its
+ lines that contain the text "ipi_send" on standard output, and send signal 2
+ (SIGINT) to the parent process.
+
+ Performance Considerations:
+
+ |actionsperf|
+
+**--on-end** *action*
+
+ Defines an action to be executed at the end of tracing.
+
+ Multiple --on-end actions can be specified, and they will be executed in the order
+ they are provided. If any action fails, subsequent actions in the list will not be
+ executed.
+
+ See the documentation for **--on-threshold** for the list of supported actions, with
+ the exception that *continue* has no effect.
+
+ Example:
+
+ $ rtla |tool| -d 5s --on-end trace
+
+ This runs rtla with the default options, and saves trace output at the end.
+
**-h**, **--help**
Print help menu.
diff --git a/Documentation/tools/rtla/common_osnoise_options.rst b/Documentation/tools/rtla/common_osnoise_options.rst
index d73de2d58f5f..bd3c4f499193 100644
--- a/Documentation/tools/rtla/common_osnoise_options.rst
+++ b/Documentation/tools/rtla/common_osnoise_options.rst
@@ -1,3 +1,11 @@
+.. |threshold| replace:: **-a/--auto**, **-s/--stop**, or **-S/--stop-total**
+.. |thresharg| replace:: -s
+.. |tracer| replace:: osnoise
+
+.. |actionsperf| replace::
+ Due to implementational limitations, actions might be delayed
+ up to one second after tracing is stopped.
+
**-a**, **--auto** *us*
Set the automatic trace mode. This mode sets some commonly used options
diff --git a/Documentation/tools/rtla/common_timerlat_options.rst b/Documentation/tools/rtla/common_timerlat_options.rst
index 7854368f1827..1f5d024b53aa 100644
--- a/Documentation/tools/rtla/common_timerlat_options.rst
+++ b/Documentation/tools/rtla/common_timerlat_options.rst
@@ -1,3 +1,13 @@
+.. |threshold| replace:: **-a/--auto**, **-i/--irq**, or **-T/--thread**
+.. |thresharg| replace:: -T
+.. |tracer| replace:: timerlat
+
+.. |actionsperf| replace::
+ For time-sensitive actions, it is recommended to run **rtla timerlat** with BPF
+ support and RT priority. Note that due to implementational limitations, actions
+ might be delayed up to one second after tracing is stopped if BPF mode is not
+ available or disabled.
+
**-a**, **--auto** *us*
Set the automatic trace mode. This mode sets some commonly used options
@@ -55,67 +65,3 @@
Set timerlat to run without workload, waiting for the user to dispatch a per-cpu
task that waits for a new period on the tracing/osnoise/per_cpu/cpu$ID/timerlat_fd.
See linux/tools/rtla/sample/timerlat_load.py for an example of user-load code.
-
-**--on-threshold** *action*
-
- Defines an action to be executed when tracing is stopped on a latency threshold
- specified by **-i/--irq** or **-T/--thread**.
-
- Multiple --on-threshold actions may be specified, and they will be executed in
- the order they are provided. If any action fails, subsequent actions in the list
- will not be executed.
-
- Supported actions are:
-
- - *trace[,file=<filename>]*
-
- Saves trace output, optionally taking a filename. Alternative to -t/--trace.
- Note that nlike -t/--trace, specifying this multiple times will result in
- the trace being saved multiple times.
-
- - *signal,num=<sig>,pid=<pid>*
-
- Sends signal to process. "parent" might be specified in place of pid to target
- the parent process of rtla.
-
- - *shell,command=<command>*
-
- Execute shell command.
-
- - *continue*
-
- Continue tracing after actions are executed instead of stopping.
-
- Example:
-
- $ rtla timerlat -T 20 --on-threshold trace
- --on-threshold shell,command="grep ipi_send timerlat_trace.txt"
- --on-threshold signal,num=2,pid=parent
-
- This will save a trace with the default filename "timerlat_trace.txt", print its
- lines that contain the text "ipi_send" on standard output, and send signal 2
- (SIGINT) to the parent process.
-
- Performance Considerations:
-
- For time-sensitive actions, it is recommended to run **rtla timerlat** with BPF
- support and RT priority. Note that due to implementational limitations, actions
- might be delayed up to one second after tracing is stopped if BPF mode is not
- available or disabled.
-
-**--on-end** *action*
-
- Defines an action to be executed at the end of **rtla timerlat** tracing.
-
- Multiple --on-end actions can be specified, and they will be executed in the order
- they are provided. If any action fails, subsequent actions in the list will not be
- executed.
-
- See the documentation for **--on-threshold** for the list of supported actions, with
- the exception that *continue* has no effect.
-
- Example:
-
- $ rtla timerlat -d 5s --on-end trace
-
- This runs rtla timerlat with default options and save trace output at the end.
diff --git a/Documentation/tools/rtla/rtla-hwnoise.rst b/Documentation/tools/rtla/rtla-hwnoise.rst
index fb1c52bbc00b..3a7163c02ac8 100644
--- a/Documentation/tools/rtla/rtla-hwnoise.rst
+++ b/Documentation/tools/rtla/rtla-hwnoise.rst
@@ -1,5 +1,7 @@
.. SPDX-License-Identifier: GPL-2.0
+.. |tool| replace:: hwnoise
+
============
rtla-hwnoise
============
diff --git a/Documentation/tools/rtla/rtla-osnoise-hist.rst b/Documentation/tools/rtla/rtla-osnoise-hist.rst
index f2e79d22c4c4..1fc60ef26106 100644
--- a/Documentation/tools/rtla/rtla-osnoise-hist.rst
+++ b/Documentation/tools/rtla/rtla-osnoise-hist.rst
@@ -1,3 +1,5 @@
+.. |tool| replace:: osnoise hist
+
===================
rtla-osnoise-hist
===================
diff --git a/Documentation/tools/rtla/rtla-osnoise-top.rst b/Documentation/tools/rtla/rtla-osnoise-top.rst
index 5d75d1394516..b1cbd7bcd4ae 100644
--- a/Documentation/tools/rtla/rtla-osnoise-top.rst
+++ b/Documentation/tools/rtla/rtla-osnoise-top.rst
@@ -1,3 +1,5 @@
+.. |tool| replace:: osnoise top
+
===================
rtla-osnoise-top
===================
diff --git a/Documentation/tools/rtla/rtla-timerlat-hist.rst b/Documentation/tools/rtla/rtla-timerlat-hist.rst
index b2d8726271b3..4923a362129b 100644
--- a/Documentation/tools/rtla/rtla-timerlat-hist.rst
+++ b/Documentation/tools/rtla/rtla-timerlat-hist.rst
@@ -1,3 +1,5 @@
+.. |tool| replace:: timerlat hist
+
=====================
rtla-timerlat-hist
=====================
diff --git a/Documentation/tools/rtla/rtla-timerlat-top.rst b/Documentation/tools/rtla/rtla-timerlat-top.rst
index ab6cb60c9083..50968cdd2095 100644
--- a/Documentation/tools/rtla/rtla-timerlat-top.rst
+++ b/Documentation/tools/rtla/rtla-timerlat-top.rst
@@ -1,3 +1,5 @@
+.. |tool| replace:: timerlat top
+
====================
rtla-timerlat-top
====================
diff --git a/tools/tracing/rtla/src/actions.c b/tools/tracing/rtla/src/actions.c
index aaf0808125d7..991139f9069f 100644
--- a/tools/tracing/rtla/src/actions.c
+++ b/tools/tracing/rtla/src/actions.c
@@ -127,17 +127,17 @@ actions_add_continue(struct actions *self)
* actions_parse - add an action based on text specification
*/
int
-actions_parse(struct actions *self, const char *trigger)
+actions_parse(struct actions *self, const char *trigger, const char *tracefn)
{
enum action_type type = ACTION_NONE;
- char *token;
+ const char *token;
char trigger_c[strlen(trigger)];
/* For ACTION_SIGNAL */
int signal = 0, pid = 0;
/* For ACTION_TRACE_OUTPUT */
- char *trace_output;
+ const char *trace_output;
strcpy(trigger_c, trigger);
token = strtok(trigger_c, ",");
@@ -160,7 +160,7 @@ actions_parse(struct actions *self, const char *trigger)
case ACTION_TRACE_OUTPUT:
/* Takes no argument */
if (token == NULL)
- trace_output = "timerlat_trace.txt";
+ trace_output = tracefn;
else {
if (strlen(token) > 5 && strncmp(token, "file=", 5) == 0) {
trace_output = token + 5;
diff --git a/tools/tracing/rtla/src/actions.h b/tools/tracing/rtla/src/actions.h
index b10a19d55c49..a4f9b570775b 100644
--- a/tools/tracing/rtla/src/actions.h
+++ b/tools/tracing/rtla/src/actions.h
@@ -48,5 +48,5 @@ int actions_add_trace_output(struct actions *self, const char *trace_output);
int actions_add_signal(struct actions *self, int signal, int pid);
int actions_add_shell(struct actions *self, const char *command);
int actions_add_continue(struct actions *self);
-int actions_parse(struct actions *self, const char *trigger);
+int actions_parse(struct actions *self, const char *trigger, const char *tracefn);
int actions_perform(struct actions *self);
diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
index 2c2cdd467a67..dffb6d0a98d7 100644
--- a/tools/tracing/rtla/src/osnoise_hist.c
+++ b/tools/tracing/rtla/src/osnoise_hist.c
@@ -462,6 +462,8 @@ static void osnoise_hist_usage(char *usage)
" in nanoseconds",
" --warm-up: let the workload run for s seconds before collecting data",
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
+ " --on-threshold <action>: define action to be executed at stop-total threshold, multiple are allowed",
+ " --on-end <action>: define action to be executed at measurement end, multiple are allowed",
NULL,
};
@@ -531,6 +533,8 @@ static struct common_params
{"filter", required_argument, 0, '5'},
{"warm-up", required_argument, 0, '6'},
{"trace-buffer-size", required_argument, 0, '7'},
+ {"on-threshold", required_argument, 0, '8'},
+ {"on-end", required_argument, 0, '9'},
{0, 0, 0, 0}
};
@@ -692,6 +696,22 @@ static struct common_params
case '7':
params->common.buffer_size = get_llong_from_str(optarg);
break;
+ case '8':
+ retval = actions_parse(¶ms->common.threshold_actions, optarg,
+ "osnoise_trace.txt");
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case '9':
+ retval = actions_parse(¶ms->common.end_actions, optarg,
+ "osnoise_trace.txt");
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
default:
osnoise_hist_usage("Invalid option");
}
diff --git a/tools/tracing/rtla/src/osnoise_top.c b/tools/tracing/rtla/src/osnoise_top.c
index 5a56c276f9da..95418f7ecc96 100644
--- a/tools/tracing/rtla/src/osnoise_top.c
+++ b/tools/tracing/rtla/src/osnoise_top.c
@@ -291,6 +291,8 @@ static void osnoise_top_usage(struct osnoise_params *params, char *usage)
" in nanoseconds",
" --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",
+ " --on-threshold <action>: define action to be executed at stop-total threshold, multiple are allowed",
+ " --on-end: define action to be executed at measurement end, multiple are allowed",
NULL,
};
@@ -371,6 +373,8 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
{"filter", required_argument, 0, '1'},
{"warm-up", required_argument, 0, '2'},
{"trace-buffer-size", required_argument, 0, '3'},
+ {"on-threshold", required_argument, 0, '4'},
+ {"on-end", required_argument, 0, '5'},
{0, 0, 0, 0}
};
@@ -511,6 +515,22 @@ struct common_params *osnoise_top_parse_args(int argc, char **argv)
case '3':
params->common.buffer_size = get_llong_from_str(optarg);
break;
+ case '4':
+ retval = actions_parse(¶ms->common.threshold_actions, optarg,
+ "osnoise_trace.txt");
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case '5':
+ retval = actions_parse(¶ms->common.end_actions, optarg,
+ "osnoise_trace.txt");
+ if (retval) {
+ err_msg("Invalid action %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
default:
osnoise_top_usage(params, "Invalid option");
}
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index a9154f83f1a9..606c1688057b 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -1047,14 +1047,16 @@ static struct common_params
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '\5':
- retval = actions_parse(¶ms->common.threshold_actions, optarg);
+ retval = actions_parse(¶ms->common.threshold_actions, optarg,
+ "timerlat_trace.txt");
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case '\6':
- retval = actions_parse(¶ms->common.end_actions, optarg);
+ retval = actions_parse(¶ms->common.end_actions, optarg,
+ "timerlat_trace.txt");
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 4f1ce72d6a05..fc479a0dcb59 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -783,14 +783,16 @@ static struct common_params
params->deepest_idle_state = get_llong_from_str(optarg);
break;
case '9':
- retval = actions_parse(¶ms->common.threshold_actions, optarg);
+ retval = actions_parse(¶ms->common.threshold_actions, optarg,
+ "timerlat_trace.txt");
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
}
break;
case '\1':
- retval = actions_parse(¶ms->common.end_actions, optarg);
+ retval = actions_parse(¶ms->common.end_actions, optarg,
+ "timerlat_trace.txt");
if (retval) {
err_msg("Invalid action %s\n", optarg);
exit(EXIT_FAILURE);
diff --git a/tools/tracing/rtla/tests/osnoise.t b/tools/tracing/rtla/tests/osnoise.t
index 7574ec6a5a53..e3c89d45a6bb 100644
--- a/tools/tracing/rtla/tests/osnoise.t
+++ b/tools/tracing/rtla/tests/osnoise.t
@@ -8,7 +8,8 @@ set_timeout 2m
check "verify help page" \
"osnoise --help" 0 "osnoise version"
check "verify the --priority/-P param" \
- "osnoise top -P F:1 -c 0 -r 900000 -d 10s -q"
+ "osnoise top -P F:1 -c 0 -r 900000 -d 10s -q -S 1 --on-threshold shell,command=\"tests/scripts/check-priority.sh osnoise/ SCHED_FIFO 1\"" \
+ 2 "Priorities are set correctly"
check "verify the --stop/-s param" \
"osnoise top -s 30 -T 1" 2 "osnoise hit stop tracing"
check "verify the --trace param" \
@@ -22,4 +23,28 @@ check "verify the --entries/-E param" \
check_with_osnoise_options "apply default period" \
"osnoise hist -s 1" 2 period_us=600000000
+# Actions tests
+check "trace output through -t with custom filename" \
+ "osnoise hist -S 2 -t custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
+check "trace output through --on-threshold trace" \
+ "osnoise hist -S 2 --on-threshold trace" 2 "^ Saving trace to osnoise_trace.txt$"
+check "trace output through --on-threshold trace with custom filename" \
+ "osnoise hist -S 2 --on-threshold trace,file=custom_filename.txt" 2 "^ Saving trace to custom_filename.txt$"
+check "exec command" \
+ "osnoise hist -S 2 --on-threshold shell,command='echo TestOutput'" 2 "^TestOutput$"
+check "multiple actions" \
+ "osnoise hist -S 2 --on-threshold shell,command='echo -n 1' --on-threshold shell,command='echo 2'" 2 "^12$"
+check "hist stop at failed action" \
+ "osnoise hist -S 2 --on-threshold shell,command='echo -n 1; false' --on-threshold shell,command='echo -n 2'" 2 "^1# RTLA osnoise histogram$"
+check "top stop at failed action" \
+ "timerlat top -T 2 --on-threshold shell,command='echo -n abc; false' --on-threshold shell,command='echo -n defgh'" 2 "^abc" "defgh"
+check "hist with continue" \
+ "osnoise hist -S 2 -d 1s --on-threshold shell,command='echo TestOutput' --on-threshold continue" 0 "^TestOutput$"
+check "top with continue" \
+ "osnoise top -q -S 2 -d 1s --on-threshold shell,command='echo TestOutput' --on-threshold continue" 0 "^TestOutput$"
+check "hist with trace output at end" \
+ "osnoise hist -d 1s --on-end trace" 0 "^ Saving trace to osnoise_trace.txt$"
+check "top with trace output at end" \
+ "osnoise top -d 1s --on-end trace" 0 "^ Saving trace to osnoise_trace.txt$"
+
test_end
--
2.48.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top
2025-09-07 2:23 ` [PATCH v2 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top Crystal Wood
@ 2025-09-07 19:51 ` Costa Shulyupin
2025-09-08 13:53 ` Costa Shulyupin
0 siblings, 1 reply; 16+ messages in thread
From: Costa Shulyupin @ 2025-09-07 19:51 UTC (permalink / raw)
To: Crystal Wood; +Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Tomas Glozar
On Sun, 7 Sept 2025 at 05:23, Crystal Wood <crwood@redhat.com> wrote:
> -static struct osnoise_params
> +static struct common_params
> *osnoise_hist_parse_args(int argc, char *argv[])
> -static struct timerlat_params
> +static struct common_params
> *timerlat_hist_parse_args(int argc, char *argv[])
> -static struct timerlat_params
> +static struct common_params
> *timerlat_top_parse_args(int argc, char **argv)
> {
Why do you replace specific params with common params, breaking the hierarchy?
common_params is meant to remain at the lower level - tool-agnostic
and reusable across tools.
Costa
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top
2025-09-07 19:51 ` Costa Shulyupin
@ 2025-09-08 13:53 ` Costa Shulyupin
0 siblings, 0 replies; 16+ messages in thread
From: Costa Shulyupin @ 2025-09-08 13:53 UTC (permalink / raw)
To: Crystal Wood; +Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Tomas Glozar
On Sun, 7 Sept 2025 at 22:51, Costa Shulyupin <costa.shul@redhat.com> wrote:
>
> On Sun, 7 Sept 2025 at 05:23, Crystal Wood <crwood@redhat.com> wrote:
> > -static struct osnoise_params
> > +static struct common_params
> > *osnoise_hist_parse_args(int argc, char *argv[])
...
> Why do you replace specific params with common params, breaking the hierarchy?
> common_params is meant to remain at the lower level - tool-agnostic
> and reusable across tools.
I see. You use it as an abstraction.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 6/7] tools/rtla: Add test engine support for unexpected output
2025-09-07 2:23 ` [PATCH v2 6/7] tools/rtla: Add test engine support for unexpected output Crystal Wood
@ 2025-09-08 14:48 ` Crystal Wood
0 siblings, 0 replies; 16+ messages in thread
From: Crystal Wood @ 2025-09-08 14:48 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-trace-kernel, John Kacur, Tomas Glozar, Costa Shulyupin
On Sat, 2025-09-06 at 21:23 -0500, Crystal Wood wrote:
> Add a check() parameter to indicate which text must not appear in the
> output.
>
> Simplify the code so that we can print failures as they happen rather
> than trying to figure out what went wrong after printing "not ok". This
> also means that "not ok" gets printed after the info rather than before,
> which seems more intuitive anyway.
>
> Signed-off-by: Crystal Wood <crwood@redhat.com>
> ---
> v2: Preserved the original ordering of "not ok" versus diagnostics as per
> convention
Oops, forgot to edit the actual commit message to reflect the v2 update.
If there's no other need for a respin, please just remove the second
paragraph when committing.
Thanks,
Crystal
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (6 preceding siblings ...)
2025-09-07 2:23 ` [PATCH v2 7/7] tools/rtla: Add remaining support for osnoise actions Crystal Wood
@ 2025-09-09 11:25 ` Tomas Glozar
2025-09-26 14:19 ` Tomas Glozar
8 siblings, 0 replies; 16+ messages in thread
From: Tomas Glozar @ 2025-09-09 11:25 UTC (permalink / raw)
To: Crystal Wood
Cc: Steven Rostedt, linux-trace-kernel, John Kacur, Costa Shulyupin
ne 7. 9. 2025 v 4:23 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> v2: minor changes from Tomas's feedback
>
Thank you! Looks good now. (The help message for rtla-osnoise-top
shows --on-end without the argument, but that is my typo (it's also in
timerlat), let's just fix that later.)
> v1: https://lore.kernel.org/linux-trace-kernel/20250821035719.137161-1-crwood@redhat.com/T/#t
>
> Costa Shulyupin (1):
> tools/rtla: Consolidate common parameters into shared structure
>
> Crystal Wood (6):
> tools/rtla: Move top/hist params into common struct
> tools/rtla: Create common_apply_config()
> tools/rtla: Consolidate code between osnoise/timerlat and hist/top
> tools/rtla: Fix -A option name in test comment
> tools/rtla: Add test engine support for unexpected output
> tools/rtla: Add remaining support for osnoise action
>
> Documentation/tools/rtla/common_options.rst | 61 ++
> .../tools/rtla/common_osnoise_options.rst | 8 +
> .../tools/rtla/common_timerlat_options.rst | 74 +-
> Documentation/tools/rtla/rtla-hwnoise.rst | 2 +
> .../tools/rtla/rtla-osnoise-hist.rst | 2 +
> Documentation/tools/rtla/rtla-osnoise-top.rst | 2 +
> .../tools/rtla/rtla-timerlat-hist.rst | 2 +
> .../tools/rtla/rtla-timerlat-top.rst | 2 +
> tools/tracing/rtla/src/Build | 1 +
> tools/tracing/rtla/src/actions.c | 8 +-
> tools/tracing/rtla/src/actions.h | 2 +-
> tools/tracing/rtla/src/common.c | 344 ++++++++++
> tools/tracing/rtla/src/common.h | 154 +++++
> tools/tracing/rtla/src/osnoise.c | 101 ++-
> tools/tracing/rtla/src/osnoise.h | 114 +---
> tools/tracing/rtla/src/osnoise_hist.c | 369 ++++------
> tools/tracing/rtla/src/osnoise_top.c | 303 +++------
> tools/tracing/rtla/src/timerlat.c | 210 ++++--
> tools/tracing/rtla/src/timerlat.h | 55 +-
> tools/tracing/rtla/src/timerlat_bpf.c | 22 +-
> tools/tracing/rtla/src/timerlat_hist.c | 642 +++++-------------
> tools/tracing/rtla/src/timerlat_top.c | 568 ++++------------
> tools/tracing/rtla/src/trace.h | 3 -
> tools/tracing/rtla/tests/engine.sh | 26 +-
> tools/tracing/rtla/tests/osnoise.t | 27 +-
> tools/tracing/rtla/tests/timerlat.t | 4 +-
> 26 files changed, 1395 insertions(+), 1711 deletions(-)
> create mode 100644 tools/tracing/rtla/src/common.c
> create mode 100644 tools/tracing/rtla/src/common.h
>
> --
> 2.48.1
>
Reviewed-by: Tomas Glozar <tglozar@redhat.com>
Tomas
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
` (7 preceding siblings ...)
2025-09-09 11:25 ` [PATCH v2 0/7] tools/rtla: Code consolidation and " Tomas Glozar
@ 2025-09-26 14:19 ` Tomas Glozar
2025-09-27 8:44 ` Steven Rostedt
8 siblings, 1 reply; 16+ messages in thread
From: Tomas Glozar @ 2025-09-26 14:19 UTC (permalink / raw)
To: Steven Rostedt
Cc: Crystal Wood, linux-trace-kernel, John Kacur, Costa Shulyupin
Hi Steven,
ne 7. 9. 2025 v 4:23 odesílatel Crystal Wood <crwood@redhat.com> napsal:
>
> Consolidate code between osnoise/timerlat and top/hist for easier
> maintenance and less future divergence.
>
> As a consequence, actions work on osnoise as well as timerlat, so
> expose it to the user, document it, and test it.
>
> v2: minor changes from Tomas's feedback
>
> v1: https://lore.kernel.org/linux-trace-kernel/20250821035719.137161-1-crwood@redhat.com/T/#t
>
> Costa Shulyupin (1):
> tools/rtla: Consolidate common parameters into shared structure
>
> Crystal Wood (6):
> tools/rtla: Move top/hist params into common struct
> tools/rtla: Create common_apply_config()
> tools/rtla: Consolidate code between osnoise/timerlat and hist/top
> tools/rtla: Fix -A option name in test comment
> tools/rtla: Add test engine support for unexpected output
> tools/rtla: Add remaining support for osnoise actions
>
> Documentation/tools/rtla/common_options.rst | 61 ++
> .../tools/rtla/common_osnoise_options.rst | 8 +
> .../tools/rtla/common_timerlat_options.rst | 74 +-
> Documentation/tools/rtla/rtla-hwnoise.rst | 2 +
> .../tools/rtla/rtla-osnoise-hist.rst | 2 +
> Documentation/tools/rtla/rtla-osnoise-top.rst | 2 +
> .../tools/rtla/rtla-timerlat-hist.rst | 2 +
> .../tools/rtla/rtla-timerlat-top.rst | 2 +
> tools/tracing/rtla/src/Build | 1 +
> tools/tracing/rtla/src/actions.c | 8 +-
> tools/tracing/rtla/src/actions.h | 2 +-
> tools/tracing/rtla/src/common.c | 344 ++++++++++
> tools/tracing/rtla/src/common.h | 154 +++++
> tools/tracing/rtla/src/osnoise.c | 101 ++-
> tools/tracing/rtla/src/osnoise.h | 114 +---
> tools/tracing/rtla/src/osnoise_hist.c | 369 ++++------
> tools/tracing/rtla/src/osnoise_top.c | 303 +++------
> tools/tracing/rtla/src/timerlat.c | 210 ++++--
> tools/tracing/rtla/src/timerlat.h | 55 +-
> tools/tracing/rtla/src/timerlat_bpf.c | 22 +-
> tools/tracing/rtla/src/timerlat_hist.c | 642 +++++-------------
> tools/tracing/rtla/src/timerlat_top.c | 568 ++++------------
> tools/tracing/rtla/src/trace.h | 3 -
> tools/tracing/rtla/tests/engine.sh | 26 +-
> tools/tracing/rtla/tests/osnoise.t | 27 +-
> tools/tracing/rtla/tests/timerlat.t | 4 +-
> 26 files changed, 1395 insertions(+), 1711 deletions(-)
> create mode 100644 tools/tracing/rtla/src/common.c
> create mode 100644 tools/tracing/rtla/src/common.h
>
> --
> 2.48.1
>
Can you take this patchset? (As a major change, this should go to
linux-next first I guess, not sure if the timing is right for that, my
knowledge on upstream kernel workflow is still a bit flaky).
I reviewed it already, but it seems that patchwork doesn't understand
Reviewed-by on a cover letter (even though b4 understands it). I did
Reviewed-by on the original patches where I didn't request any
changes, but v2 did not preserve that, so I put it on the cover
letter.
Tomas
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions
2025-09-26 14:19 ` Tomas Glozar
@ 2025-09-27 8:44 ` Steven Rostedt
2025-09-27 9:47 ` Steven Rostedt
0 siblings, 1 reply; 16+ messages in thread
From: Steven Rostedt @ 2025-09-27 8:44 UTC (permalink / raw)
To: Tomas Glozar
Cc: Crystal Wood, linux-trace-kernel, John Kacur, Costa Shulyupin
On Fri, 26 Sep 2025 16:19:28 +0200
Tomas Glozar <tglozar@redhat.com> wrote:
> Can you take this patchset? (As a major change, this should go to
> linux-next first I guess, not sure if the timing is right for that, my
> knowledge on upstream kernel workflow is still a bit flaky).
Normally, new code now would be a bit late for the merge window, but
code in the tools directory isn't as strict. Thus, this is fine to push
for the next merge window. I'll pull it in and send it to linux-next.
>
> I reviewed it already, but it seems that patchwork doesn't understand
> Reviewed-by on a cover letter (even though b4 understands it). I did
> Reviewed-by on the original patches where I didn't request any
> changes, but v2 did not preserve that, so I put it on the cover
> letter.
I'll add the Reviewed by manually if need be.
Thanks,
-- Steve
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions
2025-09-27 8:44 ` Steven Rostedt
@ 2025-09-27 9:47 ` Steven Rostedt
2025-09-27 10:09 ` Steven Rostedt
0 siblings, 1 reply; 16+ messages in thread
From: Steven Rostedt @ 2025-09-27 9:47 UTC (permalink / raw)
To: Tomas Glozar
Cc: Crystal Wood, linux-trace-kernel, John Kacur, Costa Shulyupin
On Sat, 27 Sep 2025 04:44:54 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> Normally, new code now would be a bit late for the merge window, but
> code in the tools directory isn't as strict. Thus, this is fine to push
> for the next merge window. I'll pull it in and send it to linux-next.
>
I applied the patches and then ran "make check" and triggered this:
tests/osnoise.t ... 13/17
not ok 13 - top stop at failed action
# Output match failed: "^abc"
# Output non-match failed: "defgh"
# Timer Latency
# 0 00:00:01 | IRQ Timer Latency (us) | Thread Timer Latency (us) | Ret user Timer Latency (us)
# CPU COUNT | cur min avg max | cur min avg max | cur min avg max
# 0 #1 | 3401 3401 3401 3401 | - - - - | - - - -
# 1 #1 | 2361 2361 2361 2361 | 2414 2414 2414 2414 | - - - -
# 2 #1 | 3079 3079 3079 3079 | - - - - | - - - -
# 3 #1 | 3538 3538 3538 3538 | 3586 3586 3586 3586 | - - - -
# 4 #1 | 3771 3771 3771 3771 | 3816 3816 3816 3816 | - - - -
# 5 #1 | 3487 3487 3487 3487 | 3536 3536 3536 3536 | - - - -
# 6 #1 | 3060 3060 3060 3060 | 3108 3108 3108 3108 | - - - -
# 7 #1 | 3677 3677 3677 3677 | 3723 3723 3723 3723 | - - - -
# ---------------|----------------------------------------|----------------------------------------|---------------------------------------
# defghALL #8 e0 | 2361 3296 3771 | 2414 3363 3816 | - - - | Timer Latency
# 0 00:00:02 | IRQ Timer Latency (us) | Thread Timer Latency (us) | Ret user Timer Latency (us)
# CPU COUNT | cur min avg max | cur min avg max | cur min avg max
# 0 #1 | 3401 3401 3401 3401 | - - - - | - - - -
# 1 #1 | 2361 2361 2361 2361 | 2414 2414 2414 2414 | - - - -
# 2 #1 | 3079 3079 3079 3079 | - - - - | - - - -
# 3 #1 | 3538 3538 3538 3538 | 3586 3586 3586 3586 | - - - -
# 4 #1 | 3771 3771 3771 3771 | 3816 3816 3816 3816 | - - - -
# 5 #1 | 3487 3487 3487 3487 | 3536 3536 3536 3536 | - - - -
# 6 #1 | 3060 3060 3060 3060 | 3108 3108 3108 3108 | - - - -
# 7 #1 | 3677 3677 3677 3677 | 3723 3723 3723 3723 | - - - -
# ---------------|----------------------------------------|----------------------------------------|---------------------------------------
# ALL #8 e0 | 2361 3296 3771 | 2414 3363 3816 | - - - |timerlat hit stop tracing
# ## CPU 1 hit stop tracing, analyzing it ##
# IRQ handler delay: (exit from idle) 2353.51 us (97.47 %)
# IRQ latency: 2361.99 us
# Timerlat IRQ duration: 29.36 us (1.22 %)
# Blocking thread: 8.87 us (0.37 %)
# swapper/1:0 8.87 us
# Softirq interference 9.90 us (0.41 %)
# SCHED:7 5.28 us
# RCU:9 4.62 us
# ------------------------------------------------------------------------
# Thread latency: 2414.68 us (100%)
# ## CPU 3 hit stop tracing, analyzing it ##
# IRQ handler delay: (exit from idle) 3528.33 us (98.39 %)
# IRQ latency: 3538.74 us
# Timerlat IRQ duration: 27.43 us (0.76 %)
# Blocking thread: 16.54 us (0.46 %)
# swapper/3:0 16.54 us
# ------------------------------------------------------------------------
# Thread latency: 3586.07 us (100%)
# ## CPU 4 hit stop tracing, analyzing it ##
# IRQ handler delay: (exit from idle) 3761.22 us (98.56 %)
# IRQ latency: 3771.21 us
# Timerlat IRQ duration: 25.32 us (0.66 %)
# Blocking thread: 16.38 us (0.43 %)
# swapper/4:0 16.38 us
# ------------------------------------------------------------------------
# Thread latency: 3816.32 us (100%)
# ## CPU 5 hit stop tracing, analyzing it ##
# IRQ handler delay: (exit from idle) 3475.39 us (98.28 %)
# IRQ latency: 3487.59 us
# Timerlat IRQ duration: 28.35 us (0.80 %)
# Blocking thread: 17.70 us (0.50 %)
# swapper/5:0 17.70 us
# ------------------------------------------------------------------------
# Thread latency: 3536.22 us (100%)
# ## CPU 6 hit stop tracing, analyzing it ##
# IRQ handler delay: (exit from idle) 3049.27 us (98.10 %)
# IRQ latency: 3060.32 us
# Timerlat IRQ duration: 27.52 us (0.89 %)
# Blocking thread: 17.06 us (0.55 %)
# swapper/6:0 17.06 us
# ------------------------------------------------------------------------
# Thread latency: 3108.31 us (100%)
# ## CPU 7 hit stop tracing, analyzing it ##
# IRQ handler delay: (exit from idle) 3667.57 us (98.49 %)
# IRQ latency: 3677.37 us
# Timerlat IRQ duration: 25.59 us (0.69 %)
# Blocking thread: 16.84 us (0.45 %)
# swapper/7:0 16.84 us
# ------------------------------------------------------------------------
# Thread latency: 3723.75 us (100%)
#
# Max timerlat IRQ latency from idle: 3771.21 us in cpu 4
#
# exit code 2
Is this expected?
-- Steve
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions
2025-09-27 9:47 ` Steven Rostedt
@ 2025-09-27 10:09 ` Steven Rostedt
0 siblings, 0 replies; 16+ messages in thread
From: Steven Rostedt @ 2025-09-27 10:09 UTC (permalink / raw)
To: Tomas Glozar
Cc: Crystal Wood, linux-trace-kernel, John Kacur, Costa Shulyupin
On Sat, 27 Sep 2025 05:47:41 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> I applied the patches and then ran "make check" and triggered this:
>
> tests/osnoise.t ... 13/17
> not ok 13 - top stop at failed action
> # Output match failed: "^abc"
> # Output non-match failed: "defgh"
Hmm, after applying the two fixes this appears to go away.
-- Steve
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-09-27 10:10 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-07 2:23 [PATCH v2 0/7] tools/rtla: Code consolidation and osnoise actions Crystal Wood
2025-09-07 2:23 ` [PATCH v2 1/7] tools/rtla: Consolidate common parameters into shared structure Crystal Wood
2025-09-07 2:23 ` [PATCH v2 2/7] tools/rtla: Move top/hist params into common struct Crystal Wood
2025-09-07 2:23 ` [PATCH v2 3/7] tools/rtla: Create common_apply_config() Crystal Wood
2025-09-07 2:23 ` [PATCH v2 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top Crystal Wood
2025-09-07 19:51 ` Costa Shulyupin
2025-09-08 13:53 ` Costa Shulyupin
2025-09-07 2:23 ` [PATCH v2 5/7] tools/rtla: Fix -A option name in test comment Crystal Wood
2025-09-07 2:23 ` [PATCH v2 6/7] tools/rtla: Add test engine support for unexpected output Crystal Wood
2025-09-08 14:48 ` Crystal Wood
2025-09-07 2:23 ` [PATCH v2 7/7] tools/rtla: Add remaining support for osnoise actions Crystal Wood
2025-09-09 11:25 ` [PATCH v2 0/7] tools/rtla: Code consolidation and " Tomas Glozar
2025-09-26 14:19 ` Tomas Glozar
2025-09-27 8:44 ` Steven Rostedt
2025-09-27 9:47 ` Steven Rostedt
2025-09-27 10:09 ` Steven Rostedt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox