From nobody Wed Oct 1 21:27:15 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 99C0216132F for ; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; cv=none; b=VWYg2qjNPHXFGfWZQbRfCXzH3m6XbOdoo/bvHej9HoL4GlQVp7ClzvHd6zZb1Y6sNlftutQd5I4glwVhkt4zkkvD55uIhXctSl1XUL03hsyWTgVM92WFAqZz/IQHzW6VFlpEzWzl0TZxwprpjnuWOYPOSVh1SiqCl3kKQ1wyktM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; c=relaxed/simple; bh=VTVSvstmjy0jmEur838qZYYVS+TMaTV7zn7Yi3QAR98=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=gIKylIhIamckH6otpeIUlWcFnlbLVRzagnTTQZlbFVCdV4hMNQ/IxAFwBlrVHU0+Mwo1OzScRrs2YEXPx/XIx+xPurFolyJq3ZDuqZChAU2gNZPvTWSqylOPIx3K8cRZkiduOsUTu2IrAa2MXpOG8jLFxroFJqdTdFGDW+paF/Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=i6L4XmfZ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="i6L4XmfZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DD3D4C4CEF0; Tue, 30 Sep 2025 21:45:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1759268718; bh=VTVSvstmjy0jmEur838qZYYVS+TMaTV7zn7Yi3QAR98=; h=Date:From:To:Cc:Subject:References:From; b=i6L4XmfZ25K6QOqG0Mlo+8vRbaH/XkNUpU0VEIIGsRBhsPbiT0JBk49NIsOA36tHk qsARi3Kqec93/Pky49ltoLj/X4Gr0pRapj+nW/YWyEFI1c21tPYNYnSVeFycHFDm+E EY8l9xry31S+R53n7dOJ0N6y5X3uQin839wTAxWdIvyoJF/6OQslnmrwWxa+Fgic1F KaDuCvNqPXzxcF7ZyBgRF8Z1/ve/9O0B9z3kW64V7mb2BtARWQyfPy77OgnCtvrXrR H/Pj1uT5bU+LOFGKJuh2m+bEbN+vw89x73rEIAy2aOvTvKTmQU3bjuLPvTlncGvsrh 76XpSZELXiLdQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1v3iBS-0000000DUu7-1k2W; Tue, 30 Sep 2025 17:46:54 -0400 Message-ID: <20250930214654.270276531@kernel.org> User-Agent: quilt/0.68 Date: Tue, 30 Sep 2025 17:46:31 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Costa Shulyupin , Crystal Wood Subject: [for-next][PATCH 1/7] tools/rtla: Consolidate common parameters into shared structure References: <20250930214630.332381812@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Costa Shulyupin 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. Cc: John Kacur Link: https://lore.kernel.org/20250907022325.243930-2-crwood@redhat.com Reviewed-by: Tomas Glozar Signed-off-by: Costa Shulyupin Signed-off-by: Crystal Wood Signed-off-by: Steven Rostedt (Google) --- 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/commo= n.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_p= arams + */ +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/osno= ise.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, str= uct osnoise_params *params) { int retval; =20 - if (!params->sleep_time) - params->sleep_time =3D 1; + if (!params->common.sleep_time) + params->common.sleep_time =3D 1; =20 - retval =3D osnoise_set_cpus(tool->context, params->cpus ? params->cpus : = "all"); + retval =3D 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, str= uct osnoise_params *params) goto out_err; } =20 - retval =3D osnoise_set_stop_us(tool->context, params->stop_us); + retval =3D osnoise_set_stop_us(tool->context, params->common.stop_us); if (retval) { err_msg("Failed to set stop us\n"); goto out_err; } =20 - retval =3D osnoise_set_stop_total_us(tool->context, params->stop_total_us= ); + retval =3D osnoise_set_stop_total_us(tool->context, params->common.stop_t= otal_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, str= uct osnoise_params *params) goto out_err; } =20 - if (params->hk_cpus) { - retval =3D sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), - ¶ms->hk_cpu_set); + if (params->common.hk_cpus) { + retval =3D sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set), + ¶ms->common.hk_cpu_set); if (retval =3D=3D -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, struc= t 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); } =20 retval =3D osnoise_set_workload(tool->context, true); diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osno= ise.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 =20 -#include "utils.h" +#include "common.h" #include "trace.h" =20 enum osnoise_mode { @@ -10,26 +10,11 @@ enum osnoise_mode { }; =20 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 *to= ol) trace_seq_printf(s, "Index"); =20 for (cpu =3D 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_cpu= s)) continue; =20 if (!data->hist[cpu].count) @@ -274,7 +274,7 @@ osnoise_print_summary(struct osnoise_params *params, trace_seq_printf(trace->seq, "count:"); =20 for (cpu =3D 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_cpu= s)) continue; =20 if (!data->hist[cpu].count) @@ -288,7 +288,7 @@ osnoise_print_summary(struct osnoise_params *params, trace_seq_printf(trace->seq, "min: "); =20 for (cpu =3D 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_cpu= s)) continue; =20 if (!data->hist[cpu].count) @@ -303,7 +303,7 @@ osnoise_print_summary(struct osnoise_params *params, trace_seq_printf(trace->seq, "avg: "); =20 for (cpu =3D 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_cpu= s)) continue; =20 if (!data->hist[cpu].count) @@ -321,7 +321,7 @@ osnoise_print_summary(struct osnoise_params *params, trace_seq_printf(trace->seq, "max: "); =20 for (cpu =3D 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_cpu= s)) continue; =20 if (!data->hist[cpu].count) @@ -357,7 +357,7 @@ osnoise_print_stats(struct osnoise_params *params, stru= ct osnoise_tool *tool) bucket * data->bucket_size); =20 for (cpu =3D 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_cp= us)) continue; =20 if (!data->hist[cpu].count) @@ -395,7 +395,7 @@ osnoise_print_stats(struct osnoise_params *params, stru= ct osnoise_tool *tool) trace_seq_printf(trace->seq, "over: "); =20 for (cpu =3D 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_cpu= s)) continue; =20 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 =3D get_llong_from_str(optarg); + params->common.stop_us =3D get_llong_from_str(optarg); =20 /* set sample threshold to 1 */ params->threshold =3D 1; @@ -552,27 +552,27 @@ static struct osnoise_params osnoise_hist_usage("Bucket size needs to be > 0 and <=3D 1000000\n"); break; case 'c': - retval =3D parse_cpu_set(optarg, ¶ms->monitored_cpus); + retval =3D parse_cpu_set(optarg, ¶ms->common.monitored_cpus); if (retval) osnoise_hist_usage("\nInvalid -c cpu list\n"); - params->cpus =3D optarg; + params->common.cpus =3D optarg; break; case 'C': - params->cgroup =3D 1; + params->common.cgroup =3D 1; if (!optarg) { /* will inherit this cgroup */ - params->cgroup_name =3D NULL; + params->common.cgroup_name =3D NULL; } else if (*optarg =3D=3D '=3D') { /* skip the =3D */ - params->cgroup_name =3D ++optarg; + params->common.cgroup_name =3D ++optarg; } break; case 'D': config_debug =3D 1; break; case 'd': - params->duration =3D parse_seconds_duration(optarg); - if (!params->duration) + params->common.duration =3D 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); } =20 - if (params->events) - tevent->next =3D params->events; + if (params->common.events) + tevent->next =3D params->common.events; =20 - params->events =3D tevent; + params->common.events =3D tevent; break; case 'E': params->entries =3D get_llong_from_str(optarg); @@ -597,8 +597,8 @@ static struct osnoise_params osnoise_hist_usage(NULL); break; case 'H': - params->hk_cpus =3D 1; - retval =3D parse_cpu_set(optarg, ¶ms->hk_cpu_set); + params->common.hk_cpus =3D 1; + retval =3D 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 =3D parse_prio(optarg, ¶ms->sched_param); + retval =3D parse_prio(optarg, ¶ms->common.sched_param); if (retval =3D=3D -1) osnoise_hist_usage("Invalid -P priority"); - params->set_sched =3D 1; + params->common.set_sched =3D 1; break; case 'r': params->runtime =3D 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 =3D get_llong_from_str(optarg); + params->common.stop_us =3D get_llong_from_str(optarg); break; case 'S': - params->stop_total_us =3D get_llong_from_str(optarg); + params->common.stop_total_us =3D get_llong_from_str(optarg); break; case 'T': params->threshold =3D get_llong_from_str(optarg); @@ -653,8 +653,8 @@ static struct osnoise_params params->with_zeros =3D 1; break; case '4': /* trigger */ - if (params->events) { - retval =3D trace_event_add_trigger(params->events, optarg); + if (params->common.events) { + retval =3D 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 =3D trace_event_add_filter(params->events, optarg); + if (params->common.events) { + retval =3D 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 =3D get_llong_from_str(optarg); + params->common.warmup =3D get_llong_from_str(optarg); break; case '7': - params->buffer_size =3D get_llong_from_str(optarg); + params->common.buffer_size =3D 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); } } =20 @@ -798,16 +798,16 @@ int osnoise_hist_main(int argc, char *argv[]) if (retval) goto out_destroy; =20 - if (params->set_sched) { - retval =3D set_comm_sched_attr("osnoise/", ¶ms->sched_param); + if (params->common.set_sched) { + retval =3D set_comm_sched_attr("osnoise/", ¶ms->common.sched_param); if (retval) { err_msg("Failed to set sched parameters\n"); goto out_free; } } =20 - if (params->cgroup) { - retval =3D set_comm_cgroup("timerlat/", params->cgroup_name); + if (params->common.cgroup) { + retval =3D 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; } =20 - if (params->events) { - retval =3D trace_events_enable(&record->trace, params->events); + if (params->common.events) { + retval =3D trace_events_enable(&record->trace, params->common.events); if (retval) goto out_hist; } =20 - if (params->buffer_size > 0) { - retval =3D trace_set_buffer_size(&record->trace, params->buffer_size); + if (params->common.buffer_size > 0) { + retval =3D 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); =20 - 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; =20 @@ -868,7 +868,7 @@ int osnoise_hist_main(int argc, char *argv[]) osnoise_hist_set_signals(params); =20 while (!stop_tracing) { - sleep(params->sleep_time); + sleep(params->common.sleep_time); =20 retval =3D tracefs_iterate_raw_events(trace->tep, trace->inst, @@ -899,8 +899,8 @@ int osnoise_hist_main(int argc, char *argv[]) } =20 out_hist: - trace_events_destroy(&record->trace, params->events); - params->events =3D NULL; + trace_events_destroy(&record->trace, params->common.events); + params->common.events =3D 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, stru= ct osnoise_tool *top) osnoise_top_header(top); =20 for (i =3D 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 =3D get_llong_from_str(optarg); + params->common.stop_us =3D get_llong_from_str(optarg); =20 /* set sample threshold to 1 */ params->threshold =3D 1; @@ -387,27 +387,27 @@ struct osnoise_params *osnoise_top_parse_args(int arg= c, char **argv) =20 break; case 'c': - retval =3D parse_cpu_set(optarg, ¶ms->monitored_cpus); + retval =3D parse_cpu_set(optarg, ¶ms->common.monitored_cpus); if (retval) osnoise_top_usage(params, "\nInvalid -c cpu list\n"); - params->cpus =3D optarg; + params->common.cpus =3D optarg; break; case 'C': - params->cgroup =3D 1; + params->common.cgroup =3D 1; if (!optarg) { /* will inherit this cgroup */ - params->cgroup_name =3D NULL; + params->common.cgroup_name =3D NULL; } else if (*optarg =3D=3D '=3D') { /* skip the =3D */ - params->cgroup_name =3D ++optarg; + params->common.cgroup_name =3D ++optarg; } break; case 'D': config_debug =3D 1; break; case 'd': - params->duration =3D parse_seconds_duration(optarg); - if (!params->duration) + params->common.duration =3D 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); } =20 - if (params->events) - tevent->next =3D params->events; - params->events =3D tevent; + if (params->common.events) + tevent->next =3D params->common.events; + params->common.events =3D tevent; =20 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 =3D 1; - retval =3D parse_cpu_set(optarg, ¶ms->hk_cpu_set); + params->common.hk_cpus =3D 1; + retval =3D 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 arg= c, char **argv) osnoise_top_usage(params, "Period longer than 10 s\n"); break; case 'P': - retval =3D parse_prio(optarg, ¶ms->sched_param); + retval =3D parse_prio(optarg, ¶ms->common.sched_param); if (retval =3D=3D -1) osnoise_top_usage(params, "Invalid -P priority"); - params->set_sched =3D 1; + params->common.set_sched =3D 1; break; case 'q': params->quiet =3D 1; @@ -454,10 +454,10 @@ struct osnoise_params *osnoise_top_parse_args(int arg= c, char **argv) osnoise_top_usage(params, "Runtime shorter than 100 us\n"); break; case 's': - params->stop_us =3D get_llong_from_str(optarg); + params->common.stop_us =3D get_llong_from_str(optarg); break; case 'S': - params->stop_total_us =3D get_llong_from_str(optarg); + params->common.stop_total_us =3D 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 =3D get_llong_from_str(optarg); break; case '0': /* trigger */ - if (params->events) { - retval =3D trace_event_add_trigger(params->events, optarg); + if (params->common.events) { + retval =3D 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 =3D trace_event_add_filter(params->events, optarg); + if (params->common.events) { + retval =3D 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 arg= c, char **argv) } break; case '2': - params->warmup =3D get_llong_from_str(optarg); + params->common.warmup =3D get_llong_from_str(optarg); break; case '3': - params->buffer_size =3D get_llong_from_str(optarg); + params->common.buffer_size =3D 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); } } =20 @@ -622,16 +622,16 @@ int osnoise_top_main(int argc, char **argv) goto out_free; } =20 - if (params->set_sched) { - retval =3D set_comm_sched_attr("osnoise/", ¶ms->sched_param); + if (params->common.set_sched) { + retval =3D set_comm_sched_attr("osnoise/", ¶ms->common.sched_param); if (retval) { err_msg("Failed to set sched parameters\n"); goto out_free; } } =20 - if (params->cgroup) { - retval =3D set_comm_cgroup("osnoise/", params->cgroup_name); + if (params->common.cgroup) { + retval =3D 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; } =20 - if (params->events) { - retval =3D trace_events_enable(&record->trace, params->events); + if (params->common.events) { + retval =3D trace_events_enable(&record->trace, params->common.events); if (retval) goto out_top; } =20 - if (params->buffer_size > 0) { - retval =3D trace_set_buffer_size(&record->trace, params->buffer_size); + if (params->common.buffer_size > 0) { + retval =3D 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); =20 - 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; =20 @@ -692,7 +692,7 @@ int osnoise_top_main(int argc, char **argv) osnoise_top_set_signals(params); =20 while (!stop_tracing) { - sleep(params->sleep_time); + sleep(params->common.sleep_time); =20 retval =3D tracefs_iterate_raw_events(trace->tep, trace->inst, @@ -725,8 +725,8 @@ int osnoise_top_main(int argc, char **argv) } =20 out_top: - trace_events_destroy(&record->trace, params->events); - params->events =3D NULL; + trace_events_destroy(&record->trace, params->common.events); + params->common.events =3D 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/tim= erlat.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; =20 - if (!params->sleep_time) - params->sleep_time =3D 1; + if (!params->common.sleep_time) + params->common.sleep_time =3D 1; =20 - retval =3D osnoise_set_cpus(tool->context, params->cpus ? params->cpus : = "all"); + retval =3D 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; } =20 - if (!params->cpus) { + if (!params->common.cpus) { for (i =3D 0; i < sysconf(_SC_NPROCESSORS_CONF); i++) - CPU_SET(i, ¶ms->monitored_cpus); + CPU_SET(i, ¶ms->common.monitored_cpus); } =20 if (params->mode !=3D 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 =3D osnoise_set_stop_us(tool->context, params->stop_us); + retval =3D osnoise_set_stop_us(tool->context, params->common.stop_us); if (retval) { err_msg("Failed to set stop us\n"); goto out_err; } =20 - retval =3D osnoise_set_stop_total_us(tool->context, params->stop_total_u= s); + retval =3D 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; } =20 - if (params->hk_cpus) { - retval =3D sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), - ¶ms->hk_cpu_set); + if (params->common.hk_cpus) { + retval =3D sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set), + ¶ms->common.hk_cpu_set); if (retval =3D=3D -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 t= imerlat_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); } =20 /* diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/tim= erlat.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 { }; =20 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; =20 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 =3D params->output_divisor; bpf->rodata->entries =3D params->entries; - bpf->rodata->irq_threshold =3D params->stop_us; - bpf->rodata->thread_threshold =3D params->stop_total_us; + bpf->rodata->irq_threshold =3D params->common.stop_us; + bpf->rodata->thread_threshold =3D params->common.stop_total_us; bpf->rodata->aa_only =3D params->aa_only; =20 if (params->entries !=3D 0) { diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/sr= c/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 *t= ool) trace_seq_printf(s, "Index"); =20 for (cpu =3D 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_cpu= s)) continue; =20 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:"); =20 for (cpu =3D 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_cpu= s)) continue; =20 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: "); =20 for (cpu =3D 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_cpu= s)) continue; =20 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: "); =20 for (cpu =3D 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_cpu= s)) continue; =20 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: "); =20 for (cpu =3D 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_cpu= s)) continue; =20 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 =3D ~0; =20 for (cpu =3D 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_cpu= s)) continue; =20 if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count) @@ -636,7 +636,7 @@ timerlat_print_stats(struct timerlat_params *params, st= ruct osnoise_tool *tool) bucket * data->bucket_size); =20 for (cpu =3D 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_cp= us)) continue; =20 if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count) @@ -676,7 +676,7 @@ timerlat_print_stats(struct timerlat_params *params, st= ruct osnoise_tool *tool) trace_seq_printf(trace->seq, "over: "); =20 for (cpu =3D 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_cpu= s)) continue; =20 if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count) @@ -867,8 +867,8 @@ static struct timerlat_params auto_thresh =3D get_llong_from_str(optarg); =20 /* set thread stop to auto_thresh */ - params->stop_total_us =3D auto_thresh; - params->stop_us =3D auto_thresh; + params->common.stop_total_us =3D auto_thresh; + params->common.stop_us =3D auto_thresh; =20 /* get stack trace */ params->print_stack =3D auto_thresh; @@ -878,19 +878,19 @@ static struct timerlat_params =20 break; case 'c': - retval =3D parse_cpu_set(optarg, ¶ms->monitored_cpus); + retval =3D parse_cpu_set(optarg, ¶ms->common.monitored_cpus); if (retval) timerlat_hist_usage("\nInvalid -c cpu list\n"); - params->cpus =3D optarg; + params->common.cpus =3D optarg; break; case 'C': - params->cgroup =3D 1; + params->common.cgroup =3D 1; if (!optarg) { /* will inherit this cgroup */ - params->cgroup_name =3D NULL; + params->common.cgroup_name =3D NULL; } else if (*optarg =3D=3D '=3D') { /* skip the =3D */ - params->cgroup_name =3D ++optarg; + params->common.cgroup_name =3D ++optarg; } break; case 'b': @@ -902,8 +902,8 @@ static struct timerlat_params config_debug =3D 1; break; case 'd': - params->duration =3D parse_seconds_duration(optarg); - if (!params->duration) + params->common.duration =3D 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); } =20 - if (params->events) - tevent->next =3D params->events; + if (params->common.events) + tevent->next =3D params->common.events; =20 - params->events =3D tevent; + params->common.events =3D tevent; break; case 'E': params->entries =3D get_llong_from_str(optarg); @@ -928,15 +928,15 @@ static struct timerlat_params timerlat_hist_usage(NULL); break; case 'H': - params->hk_cpus =3D 1; - retval =3D parse_cpu_set(optarg, ¶ms->hk_cpu_set); + params->common.hk_cpus =3D 1; + retval =3D 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 =3D get_llong_from_str(optarg); + params->common.stop_us =3D get_llong_from_str(optarg); break; case 'k': params->kernel_workload =3D 1; @@ -950,16 +950,16 @@ static struct timerlat_params timerlat_hist_usage("Period longer than 1 s\n"); break; case 'P': - retval =3D parse_prio(optarg, ¶ms->sched_param); + retval =3D parse_prio(optarg, ¶ms->common.sched_param); if (retval =3D=3D -1) timerlat_hist_usage("Invalid -P priority"); - params->set_sched =3D 1; + params->common.set_sched =3D 1; break; case 's': params->print_stack =3D get_llong_from_str(optarg); break; case 'T': - params->stop_total_us =3D get_llong_from_str(optarg); + params->common.stop_total_us =3D get_llong_from_str(optarg); break; case 't': if (optarg) { @@ -997,8 +997,8 @@ static struct timerlat_params params->with_zeros =3D 1; break; case '6': /* trigger */ - if (params->events) { - retval =3D trace_event_add_trigger(params->events, optarg); + if (params->common.events) { + retval =3D 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 =3D trace_event_add_filter(params->events, optarg); + if (params->common.events) { + retval =3D 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 =3D 1; break; case '\2': - params->warmup =3D get_llong_from_str(optarg); + params->common.warmup =3D get_llong_from_str(optarg); break; case '\3': - params->buffer_size =3D get_llong_from_str(optarg); + params->common.buffer_size =3D get_llong_from_str(optarg); break; case '\4': params->deepest_idle_state =3D 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 =3D 1; =20 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); } } =20 @@ -1235,16 +1235,16 @@ int timerlat_hist_main(int argc, char *argv[]) goto out_free; } =20 - if (params->set_sched) { - retval =3D set_comm_sched_attr("timerlat/", ¶ms->sched_param); + if (params->common.set_sched) { + retval =3D set_comm_sched_attr("timerlat/", ¶ms->common.sched_param); if (retval) { err_msg("Failed to set sched parameters\n"); goto out_free; } } =20 - if (params->cgroup && !params->user_workload) { - retval =3D set_comm_cgroup("timerlat/", params->cgroup_name); + if (params->common.cgroup && !params->user_workload) { + retval =3D 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 =3D sysconf(_SC_NPROCESSORS_CONF); =20 for (i =3D 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 =3D record->trace.inst; params->end_actions.trace_output_inst =3D record->trace.inst; =20 - if (params->events) { - retval =3D trace_events_enable(&record->trace, params->events); + if (params->common.events) { + retval =3D trace_events_enable(&record->trace, params->common.events); if (retval) goto out_hist; } =20 - if (params->buffer_size > 0) { - retval =3D trace_set_buffer_size(&record->trace, params->buffer_size); + if (params->common.buffer_size > 0) { + retval =3D 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 =3D 0; =20 - params_u.set =3D ¶ms->monitored_cpus; - if (params->set_sched) - params_u.sched_param =3D ¶ms->sched_param; + params_u.set =3D ¶ms->common.monitored_cpus; + if (params->common.set_sched) + params_u.sched_param =3D ¶ms->common.sched_param; else params_u.sched_param =3D NULL; =20 - params_u.cgroup_name =3D params->cgroup_name; + params_u.cgroup_name =3D params->common.cgroup_name; =20 retval =3D pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, &par= ams_u); if (retval) err_msg("Error creating timerlat user-space threads\n"); } =20 - 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[]) =20 if (params->mode =3D=3D TRACING_MODE_TRACEFS) { while (!stop_tracing) { - sleep(params->sleep_time); + sleep(params->common.sleep_time); =20 retval =3D 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"); =20 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); =20 return_value =3D FAILED; } @@ -1467,13 +1468,13 @@ int timerlat_hist_main(int argc, char *argv[]) close(dma_latency_fd); if (params->deepest_idle_state >=3D -1) { for (i =3D 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 =3D NULL; + trace_events_destroy(&record->trace, params->common.events); + params->common.events =3D 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, st= ruct osnoise_tool *top) timerlat_top_header(params, top); =20 for (i =3D 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 =3D get_llong_from_str(optarg); =20 /* set thread stop to auto_thresh */ - params->stop_total_us =3D auto_thresh; - params->stop_us =3D auto_thresh; + params->common.stop_total_us =3D auto_thresh; + params->common.stop_us =3D auto_thresh; =20 /* get stack trace */ params->print_stack =3D auto_thresh; @@ -633,8 +633,8 @@ static struct timerlat_params auto_thresh =3D get_llong_from_str(optarg); =20 /* set thread stop to auto_thresh */ - params->stop_total_us =3D auto_thresh; - params->stop_us =3D auto_thresh; + params->common.stop_total_us =3D auto_thresh; + params->common.stop_us =3D auto_thresh; =20 /* get stack trace */ params->print_stack =3D auto_thresh; @@ -643,27 +643,27 @@ static struct timerlat_params params->aa_only =3D 1; break; case 'c': - retval =3D parse_cpu_set(optarg, ¶ms->monitored_cpus); + retval =3D parse_cpu_set(optarg, ¶ms->common.monitored_cpus); if (retval) timerlat_top_usage("\nInvalid -c cpu list\n"); - params->cpus =3D optarg; + params->common.cpus =3D optarg; break; case 'C': - params->cgroup =3D 1; + params->common.cgroup =3D 1; if (!optarg) { /* will inherit this cgroup */ - params->cgroup_name =3D NULL; + params->common.cgroup_name =3D NULL; } else if (*optarg =3D=3D '=3D') { /* skip the =3D */ - params->cgroup_name =3D ++optarg; + params->common.cgroup_name =3D ++optarg; } break; case 'D': config_debug =3D 1; break; case 'd': - params->duration =3D parse_seconds_duration(optarg); - if (!params->duration) + params->common.duration =3D 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); } =20 - if (params->events) - tevent->next =3D params->events; - params->events =3D tevent; + if (params->common.events) + tevent->next =3D params->common.events; + params->common.events =3D tevent; break; case 'h': case '?': timerlat_top_usage(NULL); break; case 'H': - params->hk_cpus =3D 1; - retval =3D parse_cpu_set(optarg, ¶ms->hk_cpu_set); + params->common.hk_cpus =3D 1; + retval =3D 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 =3D get_llong_from_str(optarg); + params->common.stop_us =3D get_llong_from_str(optarg); break; case 'k': params->kernel_workload =3D true; @@ -704,10 +704,10 @@ static struct timerlat_params timerlat_top_usage("Period longer than 1 s\n"); break; case 'P': - retval =3D parse_prio(optarg, ¶ms->sched_param); + retval =3D parse_prio(optarg, ¶ms->common.sched_param); if (retval =3D=3D -1) timerlat_top_usage("Invalid -P priority"); - params->set_sched =3D 1; + params->common.set_sched =3D 1; break; case 'q': params->quiet =3D 1; @@ -716,7 +716,7 @@ static struct timerlat_params params->print_stack =3D get_llong_from_str(optarg); break; case 'T': - params->stop_total_us =3D get_llong_from_str(optarg); + params->common.stop_total_us =3D get_llong_from_str(optarg); break; case 't': if (optarg) { @@ -736,8 +736,8 @@ static struct timerlat_params params->user_data =3D true; break; case '0': /* trigger */ - if (params->events) { - retval =3D trace_event_add_trigger(params->events, optarg); + if (params->common.events) { + retval =3D 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 =3D trace_event_add_filter(params->events, optarg); + if (params->common.events) { + retval =3D 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 =3D 1; break; case '6': - params->warmup =3D get_llong_from_str(optarg); + params->common.warmup =3D get_llong_from_str(optarg); break; case '7': - params->buffer_size =3D get_llong_from_str(optarg); + params->common.buffer_size =3D get_llong_from_str(optarg); break; case '8': params->deepest_idle_state =3D 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 =3D 1; =20 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); } } =20 @@ -926,7 +926,7 @@ timerlat_top_main_loop(struct osnoise_tool *top, int retval; =20 while (!stop_tracing) { - sleep(params->sleep_time); + sleep(params->common.sleep_time); =20 if (params->aa_only && !osnoise_trace_is_off(top, record)) continue; @@ -992,7 +992,7 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top, =20 /* Pull and display data in a loop */ while (!stop_tracing) { - wait_retval =3D timerlat_bpf_wait(params->quiet ? -1 : params->sleep_tim= e); + wait_retval =3D timerlat_bpf_wait(params->quiet ? -1 : params->common.sl= eep_time); =20 retval =3D timerlat_top_bpf_pull_data(top); if (retval) { @@ -1094,16 +1094,16 @@ int timerlat_top_main(int argc, char *argv[]) goto out_free; } =20 - if (params->set_sched) { - retval =3D set_comm_sched_attr("timerlat/", ¶ms->sched_param); + if (params->common.set_sched) { + retval =3D set_comm_sched_attr("timerlat/", ¶ms->common.sched_param); if (retval) { err_msg("Failed to set sched parameters\n"); goto out_free; } } =20 - if (params->cgroup && !params->user_data) { - retval =3D set_comm_cgroup("timerlat/", params->cgroup_name); + if (params->common.cgroup && !params->user_data) { + retval =3D 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 =3D sysconf(_SC_NPROCESSORS_CONF); =20 for (i =3D 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 =3D record->trace.inst; params->end_actions.trace_output_inst =3D record->trace.inst; =20 - if (params->events) { - retval =3D trace_events_enable(&record->trace, params->events); + if (params->common.events) { + retval =3D trace_events_enable(&record->trace, params->common.events); if (retval) goto out_top; } =20 - if (params->buffer_size > 0) { - retval =3D trace_set_buffer_size(&record->trace, params->buffer_size); + if (params->common.buffer_size > 0) { + retval =3D 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 =3D 0; =20 - params_u.set =3D ¶ms->monitored_cpus; - if (params->set_sched) - params_u.sched_param =3D ¶ms->sched_param; + params_u.set =3D ¶ms->common.monitored_cpus; + if (params->common.set_sched) + params_u.sched_param =3D ¶ms->common.sched_param; else params_u.sched_param =3D NULL; =20 - params_u.cgroup_name =3D params->cgroup_name; + params_u.cgroup_name =3D params->common.cgroup_name; =20 retval =3D pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, &par= ams_u); if (retval) err_msg("Error creating timerlat user-space threads\n"); } =20 - 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); } =20 /* @@ -1258,7 +1258,8 @@ int timerlat_top_main(int argc, char *argv[]) printf("rtla timerlat hit stop tracing\n"); =20 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); =20 return_value =3D 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 >=3D -1) { for (i =3D 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 =3D NULL; + trace_events_destroy(&record->trace, params->common.events); + params->common.events =3D NULL; out_free: timerlat_free_top(top->data); if (aa && aa !=3D top) --=20 2.50.1 From nobody Wed Oct 1 21:27:15 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B33D91EBA14 for ; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; cv=none; b=UPGbQM4t4Zl4IXWT7va/FVjxZd2BRoKORuygCscA80zZi7FcClT+efMD5Y4CEP+j00s36KCuztCkoTEtJI0nhZtHjoYrBoWahe2FBT3/wlz5a9H41wpSDEzB3C7N+XPS7yxU4Ktuo90/qOcfQKL306KS+3Lvbd0/t1qdsj3iB9Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; c=relaxed/simple; bh=7Y6DFGm+uDBhtp5PhCGRL0+YUzPoPYOls9LhzYm01vM=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=Bhtx+9OcRNsO82k6pvUV24Kcwi/K2HM+hFR56Gn/rKZVjFuVrfMbmYLKGHVKDXsbo48tCGMbJfUR02gur2bW7di7ds5SPYCt10Xu0RSyosJils7SVFd9vFlfzE8NCgHD8HliTFbHi1YliCsNDKoH6ieOtIT2YhuELGjriyAQhW0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SzKXxxjD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SzKXxxjD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 167B6C4CEF7; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1759268718; bh=7Y6DFGm+uDBhtp5PhCGRL0+YUzPoPYOls9LhzYm01vM=; h=Date:From:To:Cc:Subject:References:From; b=SzKXxxjDY38vo2/CVI+rpo4lRk9Fo6YgjT2gi1UWVf6yia8QXPxIlpEfRdXOhn3L8 WjREZqIZhWwaaytBR+C3HcxgDu607+vqfTPJThPW6AEynfDFWk8l7+xmgXqxFjOQir tmJz7evVP0a2w4F2Iz2YWX2nB9CnBxMFLfn7aF/s90X4yH7l1063HUvbv2SvVN6uGS QMbiJnsk0+4d0aWMoiU6v91ZR11PcTvgNWj0XG5PJeA/Ah/qK39vyf5zqlT9HrENOB iSTPbcV5m8bwVnGAf/kCszXt0RVS9oeKf4apF5c17BH1nEfv7mXRVLnCJUqs1I0e7n Uejp7kHNR3wkQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1v3iBS-0000000DUuc-2RRr; Tue, 30 Sep 2025 17:46:54 -0400 Message-ID: <20250930214654.437180042@kernel.org> User-Agent: quilt/0.68 Date: Tue, 30 Sep 2025 17:46:32 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Costa Shulyupin , Crystal Wood Subject: [for-next][PATCH 2/7] tools/rtla: Move top/hist params into common struct References: <20250930214630.332381812@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: 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. Cc: John Kacur Cc: Costa Shulyupin Link: https://lore.kernel.org/20250907022325.243930-3-crwood@redhat.com Reviewed-by: Tomas Glozar Signed-off-by: Crystal Wood Signed-off-by: Steven Rostedt (Google) --- 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/commo= n.h index 0a44cfaa7c0b..276dfbc7f955 100644 --- a/tools/tracing/rtla/src/common.h +++ b/tools/tracing/rtla/src/common.h @@ -3,6 +3,17 @@ =20 #include "utils.h" =20 +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_p= arams */ @@ -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/osno= ise.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; }; =20 /* 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; =20 - if (params->output_divisor) - duration =3D duration / params->output_divisor; + if (params->common.output_divisor) + duration =3D duration / params->common.output_divisor; =20 bucket =3D duration / data->bucket_size; =20 @@ -146,7 +146,7 @@ static int osnoise_init_trace_hist(struct osnoise_tool = *tool) /* * Set the size of the bucket. */ - bucket_size =3D params->output_divisor * params->bucket_size; + bucket_size =3D params->common.output_divisor * params->common.hist.bucke= t_size; snprintf(buff, sizeof(buff), "duration.buckets=3D%d", bucket_size); =20 data->trace_hist =3D tracefs_hist_alloc(tool->trace.tep, "osnoise", "samp= le_threshold", @@ -228,18 +228,18 @@ static void osnoise_hist_header(struct osnoise_tool *= tool) char duration[26]; int cpu; =20 - if (params->no_header) + if (params->common.hist.no_header) return; =20 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 =3D=3D 1 ? "nanoseconds" : "microseconds", - params->output_divisor =3D=3D 1 ? "ns" : "us"); + params->common.output_divisor =3D=3D 1 ? "nanoseconds" : "microseconds", + params->common.output_divisor =3D=3D 1 ? "ns" : "us"); =20 trace_seq_printf(s, "# Duration: %s\n", duration); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(s, "Index"); =20 for (cpu =3D 0; cpu < data->nr_cpus; cpu++) { @@ -267,10 +267,10 @@ osnoise_print_summary(struct osnoise_params *params, { int cpu; =20 - if (params->no_summary) + if (params->common.hist.no_summary) return; =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "count:"); =20 for (cpu =3D 0; cpu < data->nr_cpus; cpu++) { @@ -284,7 +284,7 @@ osnoise_print_summary(struct osnoise_params *params, } trace_seq_printf(trace->seq, "\n"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "min: "); =20 for (cpu =3D 0; cpu < data->nr_cpus; cpu++) { @@ -299,7 +299,7 @@ osnoise_print_summary(struct osnoise_params *params, } trace_seq_printf(trace->seq, "\n"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "avg: "); =20 for (cpu =3D 0; cpu < data->nr_cpus; cpu++) { @@ -317,7 +317,7 @@ osnoise_print_summary(struct osnoise_params *params, } trace_seq_printf(trace->seq, "\n"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "max: "); =20 for (cpu =3D 0; cpu < data->nr_cpus; cpu++) { @@ -352,7 +352,7 @@ osnoise_print_stats(struct osnoise_params *params, stru= ct osnoise_tool *tool) for (bucket =3D 0; bucket < data->entries; bucket++) { total =3D 0; =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "%-6d", bucket * data->bucket_size); =20 @@ -367,7 +367,7 @@ osnoise_print_stats(struct osnoise_params *params, stru= ct osnoise_tool *tool) trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].samples[bucket]); } =20 - if (total =3D=3D 0 && !params->with_zeros) { + if (total =3D=3D 0 && !params->common.hist.with_zeros) { trace_seq_reset(trace->seq); continue; } @@ -391,7 +391,7 @@ osnoise_print_stats(struct osnoise_params *params, stru= ct osnoise_tool *tool) return; } =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "over: "); =20 for (cpu =3D 0; cpu < data->nr_cpus; cpu++) { @@ -490,9 +490,9 @@ static struct osnoise_params exit(1); =20 /* display data in microseconds */ - params->output_divisor =3D 1000; - params->bucket_size =3D 1; - params->entries =3D 256; + params->common.output_divisor =3D 1000; + params->common.hist.bucket_size =3D 1; + params->common.hist.entries =3D 256; =20 while (1) { static struct option long_options[] =3D { @@ -547,8 +547,9 @@ static struct osnoise_params =20 break; case 'b': - params->bucket_size =3D get_llong_from_str(optarg); - if ((params->bucket_size =3D=3D 0) || (params->bucket_size >=3D 1000000= )) + params->common.hist.bucket_size =3D get_llong_from_str(optarg); + if (params->common.hist.bucket_size =3D=3D 0 || + params->common.hist.bucket_size >=3D 1000000) osnoise_hist_usage("Bucket size needs to be > 0 and <=3D 1000000\n"); break; case 'c': @@ -588,8 +589,9 @@ static struct osnoise_params params->common.events =3D tevent; break; case 'E': - params->entries =3D get_llong_from_str(optarg); - if ((params->entries < 10) || (params->entries > 9999999)) + params->common.hist.entries =3D 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 =3D "osnoise_trace.txt"; break; case '0': /* no header */ - params->no_header =3D 1; + params->common.hist.no_header =3D 1; break; case '1': /* no summary */ - params->no_summary =3D 1; + params->common.hist.no_summary =3D 1; break; case '2': /* no index */ - params->no_index =3D 1; + params->common.hist.no_index =3D 1; break; case '3': /* with zeros */ - params->with_zeros =3D 1; + params->common.hist.with_zeros =3D 1; break; case '4': /* trigger */ if (params->common.events) { @@ -690,7 +692,7 @@ static struct osnoise_params exit(EXIT_FAILURE); } =20 - 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 ma= ke sense"); =20 return params; @@ -729,7 +731,8 @@ static struct osnoise_tool if (!tool) return NULL; =20 - tool->data =3D osnoise_alloc_histogram(nr_cpus, params->entries, params->= bucket_size); + tool->data =3D osnoise_alloc_histogram(nr_cpus, params->common.hist.entri= es, + params->common.hist.bucket_size); if (!tool->data) goto out_err; =20 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 *t= op) { struct osnoise_params *params =3D top->params; struct trace_seq *s =3D top->trace.seq; + bool pretty =3D params->common.pretty_output; char duration[26]; =20 get_duration(top->start_time, duration, sizeof(duration)); =20 - if (params->pretty_output) + if (pretty) trace_seq_printf(s, "\033[2;37;40m"); =20 trace_seq_printf(s, " "); @@ -143,13 +144,13 @@ static void osnoise_top_header(struct osnoise_tool *t= op) =20 trace_seq_printf(s, " "); =20 - if (params->pretty_output) + if (pretty) trace_seq_printf(s, "\033[0;0;0m"); trace_seq_printf(s, "\n"); =20 trace_seq_printf(s, "duration: %9s | time is in us\n", duration); =20 - if (params->pretty_output) + if (pretty) trace_seq_printf(s, "\033[2;30;47m"); =20 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"); =20 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, stru= ct osnoise_tool *top) if (nr_cpus =3D=3D -1) nr_cpus =3D sysconf(_SC_NPROCESSORS_CONF); =20 - if (!params->quiet) + if (!params->common.quiet) clear_terminal(trace->seq); =20 osnoise_top_header(top); @@ -446,7 +447,7 @@ struct osnoise_params *osnoise_top_parse_args(int argc,= char **argv) params->common.set_sched =3D 1; break; case 'q': - params->quiet =3D 1; + params->common.quiet =3D 1; break; case 'r': params->runtime =3D get_llong_from_str(optarg); @@ -534,8 +535,8 @@ osnoise_top_apply_config(struct osnoise_tool *tool, str= uct osnoise_params *param } } =20 - if (isatty(STDOUT_FILENO) && !params->quiet) - params->pretty_output =3D 1; + if (isatty(STDOUT_FILENO) && !params->common.quiet) + params->common.pretty_output =3D 1; =20 return 0; =20 @@ -705,7 +706,7 @@ int osnoise_top_main(int argc, char **argv) goto out_top; } =20 - if (!params->quiet) + if (!params->common.quiet) osnoise_print_stats(params, tool); =20 if (osnoise_trace_is_off(tool, record)) diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/tim= erlat.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; =20 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; - }; - }; }; =20 int timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_param= s *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; =20 /* Pass common options */ - bpf->rodata->output_divisor =3D params->output_divisor; - bpf->rodata->entries =3D params->entries; + bpf->rodata->output_divisor =3D params->common.output_divisor; + bpf->rodata->entries =3D params->common.hist.entries; bpf->rodata->irq_threshold =3D params->common.stop_us; bpf->rodata->thread_threshold =3D params->common.stop_total_us; bpf->rodata->aa_only =3D params->aa_only; =20 - if (params->entries !=3D 0) { + if (params->common.hist.entries !=3D 0) { /* Pass histogram options */ - bpf->rodata->bucket_size =3D params->bucket_size; + bpf->rodata->bucket_size =3D params->common.hist.bucket_size; =20 /* 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.entr= ies); + bpf_map__set_max_entries(bpf->maps.hist_user, params->common.hist.entrie= s); } 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/sr= c/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; =20 - if (params->output_divisor) - latency =3D latency / params->output_divisor; + if (params->common.output_divisor) + latency =3D latency / params->common.output_divisor; =20 bucket =3D latency / data->bucket_size; =20 @@ -288,18 +288,18 @@ static void timerlat_hist_header(struct osnoise_tool = *tool) char duration[26]; int cpu; =20 - if (params->no_header) + if (params->common.hist.no_header) return; =20 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 =3D=3D 1 ? "nanoseconds" : "microseconds", - params->output_divisor =3D=3D 1 ? "ns" : "us"); + params->common.output_divisor =3D=3D 1 ? "nanoseconds" : "microseconds", + params->common.output_divisor =3D=3D 1 ? "ns" : "us"); =20 trace_seq_printf(s, "# Duration: %s\n", duration); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(s, "Index"); =20 for (cpu =3D 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; =20 - if (!params->no_irq) + if (!params->common.hist.no_irq) trace_seq_printf(s, " IRQ-%03d", cpu); =20 - if (!params->no_thread) + if (!params->common.hist.no_thread) trace_seq_printf(s, " Thr-%03d", cpu); =20 if (params->user_data) @@ -350,10 +350,10 @@ timerlat_print_summary(struct timerlat_params *params, { int cpu; =20 - if (params->no_summary) + if (params->common.hist.no_summary) return; =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "count:"); =20 for (cpu =3D 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; =20 - if (!params->no_irq) + if (!params->common.hist.no_irq) trace_seq_printf(trace->seq, "%9llu ", data->hist[cpu].irq_count); =20 - if (!params->no_thread) + if (!params->common.hist.no_thread) trace_seq_printf(trace->seq, "%9llu ", data->hist[cpu].thread_count); =20 @@ -377,7 +377,7 @@ timerlat_print_summary(struct timerlat_params *params, } trace_seq_printf(trace->seq, "\n"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "min: "); =20 for (cpu =3D 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; =20 - 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); =20 - 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"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "avg: "); =20 for (cpu =3D 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; =20 - 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); =20 - 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"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "max: "); =20 for (cpu =3D 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; =20 - 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); =20 - 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; =20 - if (params->no_summary) + if (params->common.hist.no_summary) return; =20 memset(&sum, 0, sizeof(sum)); @@ -512,13 +512,13 @@ timerlat_print_stats_all(struct timerlat_params *para= ms, update_max(&sum.max_user, &cpu_data->max_user); } =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "ALL: "); =20 - if (!params->no_irq) + if (!params->common.hist.no_irq) trace_seq_printf(trace->seq, " IRQ"); =20 - if (!params->no_thread) + if (!params->common.hist.no_thread) trace_seq_printf(trace->seq, " Thr"); =20 if (params->user_data) @@ -526,14 +526,14 @@ timerlat_print_stats_all(struct timerlat_params *para= ms, =20 trace_seq_printf(trace->seq, "\n"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "count:"); =20 - if (!params->no_irq) + if (!params->common.hist.no_irq) trace_seq_printf(trace->seq, "%9llu ", sum.irq_count); =20 - if (!params->no_thread) + if (!params->common.hist.no_thread) trace_seq_printf(trace->seq, "%9llu ", sum.thread_count); =20 @@ -543,16 +543,16 @@ timerlat_print_stats_all(struct timerlat_params *para= ms, =20 trace_seq_printf(trace->seq, "\n"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "min: "); =20 - if (!params->no_irq) + if (!params->common.hist.no_irq) format_summary_value(trace->seq, sum.irq_count, sum.min_irq, false); =20 - 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 *para= ms, =20 trace_seq_printf(trace->seq, "\n"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "avg: "); =20 - if (!params->no_irq) + if (!params->common.hist.no_irq) format_summary_value(trace->seq, sum.irq_count, sum.sum_irq, true); =20 - 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 *para= ms, =20 trace_seq_printf(trace->seq, "\n"); =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "max: "); =20 - if (!params->no_irq) + if (!params->common.hist.no_irq) format_summary_value(trace->seq, sum.irq_count, sum.max_irq, false); =20 - 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, st= ruct osnoise_tool *tool) for (bucket =3D 0; bucket < data->entries; bucket++) { total =3D 0; =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "%-6d", bucket * data->bucket_size); =20 @@ -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; =20 - if (!params->no_irq) { + if (!params->common.hist.no_irq) { total +=3D data->hist[cpu].irq[bucket]; trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].irq[bucket]); } =20 - if (!params->no_thread) { + if (!params->common.hist.no_thread) { total +=3D 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, st= ruct osnoise_tool *tool) =20 } =20 - if (total =3D=3D 0 && !params->with_zeros) { + if (total =3D=3D 0 && !params->common.hist.with_zeros) { trace_seq_reset(trace->seq); continue; } @@ -672,7 +672,7 @@ timerlat_print_stats(struct timerlat_params *params, st= ruct osnoise_tool *tool) trace_seq_reset(trace->seq); } =20 - if (!params->no_index) + if (!params->common.hist.no_index) trace_seq_printf(trace->seq, "over: "); =20 for (cpu =3D 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; =20 - if (!params->no_irq) + if (!params->common.hist.no_irq) trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].irq[data->entries]); =20 - if (!params->no_thread) + if (!params->common.hist.no_thread) trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].thread[data->entries]); =20 @@ -804,9 +804,9 @@ static struct timerlat_params params->deepest_idle_state =3D -2; =20 /* display data in microseconds */ - params->output_divisor =3D 1000; - params->bucket_size =3D 1; - params->entries =3D 256; + params->common.output_divisor =3D 1000; + params->common.hist.bucket_size =3D 1; + params->common.hist.entries =3D 256; =20 /* default to BPF mode */ params->mode =3D TRACING_MODE_BPF; @@ -894,8 +894,9 @@ static struct timerlat_params } break; case 'b': - params->bucket_size =3D get_llong_from_str(optarg); - if ((params->bucket_size =3D=3D 0) || (params->bucket_size >=3D 1000000= )) + params->common.hist.bucket_size =3D get_llong_from_str(optarg); + if (params->common.hist.bucket_size =3D=3D 0 || + params->common.hist.bucket_size >=3D 1000000) timerlat_hist_usage("Bucket size needs to be > 0 and <=3D 1000000\n"); break; case 'D': @@ -919,9 +920,10 @@ static struct timerlat_params params->common.events =3D tevent; break; case 'E': - params->entries =3D 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 =3D 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 =3D 1; break; case 'n': - params->output_divisor =3D 1; + params->common.output_divisor =3D 1; break; case 'p': params->timerlat_period_us =3D get_llong_from_str(optarg); @@ -979,22 +981,22 @@ static struct timerlat_params params->user_data =3D 1; break; case '0': /* no irq */ - params->no_irq =3D 1; + params->common.hist.no_irq =3D 1; break; case '1': /* no thread */ - params->no_thread =3D 1; + params->common.hist.no_thread =3D 1; break; case '2': /* no header */ - params->no_header =3D 1; + params->common.hist.no_header =3D 1; break; case '3': /* no summary */ - params->no_summary =3D 1; + params->common.hist.no_summary =3D 1; break; case '4': /* no index */ - params->no_index =3D 1; + params->common.hist.no_index =3D 1; break; case '5': /* with zeros */ - params->with_zeros =3D 1; + params->common.hist.with_zeros =3D 1; break; case '6': /* trigger */ if (params->common.events) { @@ -1067,10 +1069,10 @@ static struct timerlat_params exit(EXIT_FAILURE); } =20 - 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 he= re"); =20 - 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 n= ot make sense"); =20 /* @@ -1127,7 +1129,8 @@ static struct osnoise_tool if (!tool) return NULL; =20 - tool->data =3D timerlat_alloc_histogram(nr_cpus, params->entries, params-= >bucket_size); + tool->data =3D timerlat_alloc_histogram(nr_cpus, params->common.hist.entr= ies, + params->common.hist.bucket_size); if (!tool->data) goto out_err; =20 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 =3D tool->data; struct timerlat_top_cpu *cpu_data =3D &data->cpu_data[cpu]; =20 - if (params->output_divisor) - latency =3D latency / params->output_divisor; + if (params->common.output_divisor) + latency =3D latency / params->common.output_divisor; =20 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 osn= oise_tool *top) { struct trace_seq *s =3D top->trace.seq; + bool pretty =3D params->common.pretty_output; char duration[26]; =20 get_duration(top->start_time, duration, sizeof(duration)); =20 - if (params->pretty_output) + if (pretty) trace_seq_printf(s, "\033[2;37;40m"); =20 trace_seq_printf(s, " Timer Latency = "); if (params->user_data) trace_seq_printf(s, " "); =20 - if (params->pretty_output) + if (pretty) trace_seq_printf(s, "\033[0;0;0m"); trace_seq_printf(s, "\n"); =20 trace_seq_printf(s, "%-6s | IRQ Timer Latency (%s) | = Thread Timer Latency (%s)", duration, - params->output_divisor =3D=3D 1 ? "ns" : "us", - params->output_divisor =3D=3D 1 ? "ns" : "us"); + params->common.output_divisor =3D=3D 1 ? "ns" : "us", + params->common.output_divisor =3D=3D 1 ? "ns" : "us"); =20 if (params->user_data) { trace_seq_printf(s, " | Ret user Timer Latency (%s)", - params->output_divisor =3D=3D 1 ? "ns" : "us"); + params->common.output_divisor =3D=3D 1 ? "ns" : "us"); } =20 trace_seq_printf(s, "\n"); - if (params->pretty_output) + if (pretty) trace_seq_printf(s, "\033[2;30;47m"); =20 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"); =20 - 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, st= ruct osnoise_tool *top) if (nr_cpus =3D=3D -1) nr_cpus =3D sysconf(_SC_NPROCESSORS_CONF); =20 - if (!params->quiet) + if (!params->common.quiet) clear_terminal(trace->seq); =20 timerlat_top_reset_sum(&summary); @@ -563,7 +564,7 @@ static struct timerlat_params params->deepest_idle_state =3D -2; =20 /* display data in microseconds */ - params->output_divisor =3D 1000; + params->common.output_divisor =3D 1000; =20 /* default to BPF mode */ params->mode =3D TRACING_MODE_BPF; @@ -696,7 +697,7 @@ static struct timerlat_params params->kernel_workload =3D true; break; case 'n': - params->output_divisor =3D 1; + params->common.output_divisor =3D 1; break; case 'p': params->timerlat_period_us =3D get_llong_from_str(optarg); @@ -710,7 +711,7 @@ static struct timerlat_params params->common.set_sched =3D 1; break; case 'q': - params->quiet =3D 1; + params->common.quiet =3D 1; break; case 's': params->print_stack =3D get_llong_from_str(optarg); @@ -842,8 +843,8 @@ timerlat_top_apply_config(struct osnoise_tool *top, str= uct timerlat_params *para if (retval) goto out_err; =20 - if (isatty(STDOUT_FILENO) && !params->quiet) - params->pretty_output =3D 1; + if (isatty(STDOUT_FILENO) && !params->common.quiet) + params->common.pretty_output =3D 1; =20 return 0; =20 @@ -942,7 +943,7 @@ timerlat_top_main_loop(struct osnoise_tool *top, return retval; } =20 - if (!params->quiet) + if (!params->common.quiet) timerlat_print_stats(params, top); =20 if (osnoise_trace_is_off(top, record)) { @@ -992,7 +993,8 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top, =20 /* Pull and display data in a loop */ while (!stop_tracing) { - wait_retval =3D timerlat_bpf_wait(params->quiet ? -1 : params->common.sl= eep_time); + wait_retval =3D timerlat_bpf_wait(params->common.quiet ? -1 : + params->common.sleep_time); =20 retval =3D timerlat_top_bpf_pull_data(top); if (retval) { @@ -1000,7 +1002,7 @@ timerlat_top_bpf_main_loop(struct osnoise_tool *top, return retval; } =20 - if (!params->quiet) + if (!params->common.quiet) timerlat_print_stats(params, top); =20 if (wait_retval =3D=3D 1) { --=20 2.50.1 From nobody Wed Oct 1 21:27:15 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D0E72243367 for ; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; cv=none; b=aOuKiTHprQxzDqxDk8I1IBFPA7JHl7CWaHPyR4PzJH/mML9Jom/pK41fJ5Ge2hcpb/zEwQVZ3Of99bPmxUsa7D+8ZnJwQqT+3OtsZybQNcSA825Dpcz6/t6mwY9qhtfF07VIitK0mIk1UlCnhCXmIr3EYPC5ddd+pmt0R5nNBb8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; c=relaxed/simple; bh=3l7AYllKSu3VON3a1IlVakLvTWXPoDSXroDXjOVK2Zo=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=mBmVx+YgoEqUb5JYCxtcDMNv9uh5gb8z+d7Of7GAp6DI3rRapjp3XlSnSkeDFFB9BSIX+gRXexyfQzxK4xnhlmaQgjDLGXhPGeoUhO2dYBlVIxDSHW7jIN9eQnVY4vf5f9xJlWfu4ylx3uOZi95CJmv0GYWa2cCwptymU7LVnd0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QEwKAyVh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QEwKAyVh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2BCBCC116C6; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1759268718; bh=3l7AYllKSu3VON3a1IlVakLvTWXPoDSXroDXjOVK2Zo=; h=Date:From:To:Cc:Subject:References:From; b=QEwKAyVhkVrLe6OYmdt65FLFECbUS7Ec9tS0GuMbF3SsB/xIHNsLm8KhijMuXpGEb cuqds9M68ut3VNPVN5j8z+YdelSGxNCAMHhAD45ESjdbkZnG4CBeo8Vehk6F+Q54fp NBebV8SexNI9eJ+ipTV3N5qzchkcHrFjzMSp51Qn0Ecup+vY8K0Og/oP6fqzlN0CQj 2DkxjX51HxYiYUSJqUzwlz6Kot2Vy+A+Zc1/QD+d1RLEyalEo01rgryJ5HBk5udrL3 /kqQ6llKC/B85clRW1o0HEHwCbPsDpeHF1Hr6KDUJJI5Ar1bFYJmxXVdspojI3L86q 2lT/cMQAPhDEw== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1v3iBS-0000000DUv8-389f; Tue, 30 Sep 2025 17:46:54 -0400 Message-ID: <20250930214654.602648274@kernel.org> User-Agent: quilt/0.68 Date: Tue, 30 Sep 2025 17:46:33 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Costa Shulyupin , Crystal Wood Subject: [for-next][PATCH 3/7] tools/rtla: Create common_apply_config() References: <20250930214630.332381812@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: 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. Cc: John Kacur Cc: Costa Shulyupin Link: https://lore.kernel.org/20250907022325.243930-4-crwood@redhat.com Reviewed-by: Tomas Glozar Signed-off-by: Crystal Wood Signed-off-by: Steven Rostedt (Google) --- 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 +=3D trace.o rtla-y +=3D utils.o rtla-y +=3D actions.o +rtla-y +=3D common.o rtla-y +=3D osnoise.o rtla-y +=3D osnoise_top.o rtla-y +=3D osnoise_hist.o diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/commo= n.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 +#include "common.h" + +/* + * common_apply_config - apply common configs to the initialized tool + */ +int +common_apply_config(struct osnoise_tool *tool, struct common_params *param= s) +{ + int retval, i; + + if (!params->sleep_time) + params->sleep_time =3D 1; + + retval =3D 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 =3D 0; i < sysconf(_SC_NPROCESSORS_CONF); i++) + CPU_SET(i, ¶ms->monitored_cpus); + } + + if (params->hk_cpus) { + retval =3D sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), + ¶ms->hk_cpu_set); + if (retval =3D=3D -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 =3D 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/commo= n.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 =20 +#include "trace.h" #include "utils.h" =20 +/* + * 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 *p= arams); diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osno= ise.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 *t= ool) } =20 /* - * 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 *par= ams) { int retval; =20 - if (!params->common.sleep_time) - params->common.sleep_time =3D 1; - - retval =3D 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 =3D true; =20 if (params->runtime || params->period) { retval =3D osnoise_set_runtime_period(tool->context, @@ -1169,31 +1162,7 @@ osnoise_apply_config(struct osnoise_tool *tool, stru= ct osnoise_params *params) goto out_err; } =20 - if (params->common.hk_cpus) { - retval =3D sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set), - ¶ms->common.hk_cpu_set); - if (retval =3D=3D -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 =3D 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); =20 out_err: return -1; diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osno= ise.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 =20 #include "common.h" -#include "trace.h" =20 enum osnoise_mode { MODE_OSNOISE =3D 0, @@ -18,53 +17,6 @@ struct osnoise_params { enum osnoise_mode mode; }; =20 -/* - * 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); =20 -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 *con= text, long long print_stack); =20 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/tim= erlat.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 *p= arams) { - int retval, i; - - if (!params->common.sleep_time) - params->common.sleep_time =3D 1; - - retval =3D 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 =3D 0; i < sysconf(_SC_NPROCESSORS_CONF); i++) - CPU_SET(i, ¶ms->common.monitored_cpus); - } + int retval; =20 if (params->mode !=3D TRACING_MODE_BPF) { /* @@ -75,29 +61,11 @@ timerlat_apply_config(struct osnoise_tool *tool, struct= timerlat_params *params) goto out_err; } =20 - if (params->common.hk_cpus) { - retval =3D sched_setaffinity(getpid(), sizeof(params->common.hk_cpu_set), - ¶ms->common.hk_cpu_set); - if (retval =3D=3D -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 =3D 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, struc= t timerlat_params *params) params->user_data =3D 1; } else { debug_msg("User-space interface not detected, setting kernel-threads\n"= ); - params->kernel_workload =3D 1; + params->common.kernel_workload =3D 1; } } =20 - /* - * 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 =3D 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); =20 out_err: return -1; diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/tim= erlat.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/sr= c/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 =3D get_llong_from_str(optarg); break; case 'k': - params->kernel_workload =3D 1; + params->common.kernel_workload =3D 1; break; case 'n': params->common.output_divisor =3D 1; @@ -1081,7 +1081,7 @@ static struct timerlat_params if (!params->common.stop_us && !params->common.stop_total_us) params->no_aa =3D 1; =20 - 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 ex= clusive!"); =20 /* 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 =3D get_llong_from_str(optarg); break; case 'k': - params->kernel_workload =3D true; + params->common.kernel_workload =3D true; break; case 'n': params->common.output_divisor =3D 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!"); =20 - 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 exc= lusive!"); =20 /* --=20 2.50.1 From nobody Wed Oct 1 21:27:15 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EF06025A354 for ; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268719; cv=none; b=ARUSEEPAKbD8iCYDaxJjf0MMDA6vzFkxRUjqt4/QkxX9qjZG1KQ0fHPP6bkUcbu3BOwbqGnKJD1y7hscPfIAyTU7NpCKCDhj1DTlFjEqcJiAfyJCRCEDuoMNTZnKMkddqu9Vjc7bA4fM92nALixWtaDvtysVl+0SyCc640mbvIk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268719; c=relaxed/simple; bh=uLnaPCPqCSmjjQ8kHOTgJ2MxqZ4MbfIU0wECs6eYzTs=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=R6XiY13nP8hEigwAK0qVtHJMmFvKbge/GHw6vzn+qefI49O97gVhOAXUNAgH5bR0NdnLJvFBQqvfikm7Tf2ryGsugXz4SSBSRDtG9I1DSav+nVEoexTWMB/fcAYa7Qd275osEcZ4EToMkHpSGGgs8JN4qLItksr8wMKwq5YhB+M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vOpp6iEl; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="vOpp6iEl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 707BFC116D0; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1759268718; bh=uLnaPCPqCSmjjQ8kHOTgJ2MxqZ4MbfIU0wECs6eYzTs=; h=Date:From:To:Cc:Subject:References:From; b=vOpp6iElv4GgvocBoc+5rg+rSS5MKt6VzN+ylMg7EErRbOwsR/AquTcqfDTtmyqYD jwZ2NgrhGK38GjUkFQuURYC/3kRVgB8Mb9uvVbDE16AgN0p0EE+5YM5W26rXGZ+VTK oXNAdpWNckSI2NVU9BPxfA1BhsOdGudgKf3WdgnujbQ9okNJ/AWd7vwdyqHAbnGESr p+PWdOrwI5jCJCddi5hiytoM5KXRcYP2USXyXONF59j8js33yXDtNYia/Q0b4t6zak fyoEmbAyqBeSH6pppQnV8IrxzbYrmuBT673+X08pepa5yFjhb3iktYUCAqsFsi+p0e d7FhYy7y6TjrQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1v3iBS-0000000DUvc-3s1z; Tue, 30 Sep 2025 17:46:54 -0400 Message-ID: <20250930214654.769882897@kernel.org> User-Agent: quilt/0.68 Date: Tue, 30 Sep 2025 17:46:34 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Costa Shulyupin , Crystal Wood Subject: [for-next][PATCH 4/7] tools/rtla: Consolidate code between osnoise/timerlat and hist/top References: <20250930214630.332381812@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: 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. Cc: John Kacur Cc: Costa Shulyupin Link: https://lore.kernel.org/20250907022325.243930-5-crwood@redhat.com Reviewed-by: Tomas Glozar Signed-off-by: Crystal Wood Signed-off-by: Steven Rostedt (Google) --- 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/commo= n.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 =20 +#include +#include +#include #include #include "common.h" =20 +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 =3D 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 c= ommon_params *params) return -1; } =20 + +int run_tool(struct tool_ops *ops, int argc, char *argv[]) +{ + struct common_params *params; + enum result return_value =3D ERROR; + struct osnoise_tool *tool; + bool stopped; + int retval; + + params =3D ops->parse_args(argc, argv); + if (!params) + exit(1); + + tool =3D ops->init_tool(params); + if (!tool) { + err_msg("Could not init osnoise tool\n"); + goto out_exit; + } + tool->ops =3D ops; + tool->params =3D params; + + /* + * Save trace instance into global variable so that SIGINT can stop + * the timerlat tracer. + * Otherwise, rtla could loop indefinitely when overloaded. + */ + trace_inst =3D &tool->trace; + + retval =3D ops->apply_config(tool); + if (retval) { + err_msg("Could not apply config\n"); + goto out_free; + } + + retval =3D 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 =3D 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 =3D 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 =3D 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 =3D tool->record->trace.inst; + params->end_actions.trace_output_inst =3D tool->record->trace.inst; + + if (params->events) { + retval =3D trace_events_enable(&tool->record->trace, params->events); + if (retval) + goto out_trace; + } + + if (params->buffer_size > 0) { + retval =3D trace_set_buffer_size(&tool->record->trace, params->buffer_s= ize); + if (retval) + goto out_trace; + } + } + + if (params->user_workload) { + pthread_t user_thread; + + /* rtla asked to stop */ + params->user.should_run =3D 1; + /* all threads left */ + params->user.stopped_running =3D 0; + + params->user.set =3D ¶ms->monitored_cpus; + if (params->set_sched) + params->user.sched_param =3D ¶ms->sched_param; + else + params->user.sched_param =3D NULL; + + params->user.cgroup_name =3D params->cgroup_name; + + retval =3D pthread_create(&user_thread, NULL, timerlat_u_dispatcher, &pa= rams->user); + if (retval) + err_msg("Error creating timerlat user-space threads\n"); + } + + retval =3D ops->enable(tool); + if (retval) + goto out_trace; + + tool->start_time =3D time(NULL); + set_signals(params); + + retval =3D ops->main(tool); + if (retval) + goto out_trace; + + if (params->user_workload && !params->user.stopped_running) { + params->user.should_run =3D 0; + sleep(1); + } + + ops->print_stats(tool); + + actions_perform(¶ms->end_actions); + + return_value =3D PASSED; + + stopped =3D osnoise_trace_is_off(tool, tool->record) && !stop_tracing; + if (stopped) { + printf("%s hit stop tracing\n", ops->tracer); + return_value =3D FAILED; + } + + if (ops->analyze) + ops->analyze(tool, stopped); + +out_trace: + trace_events_destroy(&tool->record->trace, params->events); + params->events =3D 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 =3D tool->params; + struct trace_instance *trace =3D &tool->trace; + struct osnoise_tool *record =3D tool->record; + int retval; + + while (!stop_tracing) { + sleep(params->sleep_time); + + if (params->aa_only && !osnoise_trace_is_off(tool, record)) + continue; + + retval =3D 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 =3D tool->params; + struct trace_instance *trace =3D &tool->trace; + int retval =3D 0; + + while (!stop_tracing) { + sleep(params->sleep_time); + + retval =3D 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/commo= n.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 =20 +#include "actions.h" +#include "timerlat_u.h" #include "trace.h" #include "utils.h" =20 @@ -51,16 +53,8 @@ struct osnoise_context { int opt_workload; }; =20 -/* - * 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; =20 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); }; =20 int osnoise_set_cpus(struct osnoise_context *context, char *cpus); @@ -111,4 +144,11 @@ void osnoise_restore_cpus(struct osnoise_context *cont= ext); =20 int osnoise_set_workload(struct osnoise_context *context, bool onoff); =20 +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 *p= arams); +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/osno= ise.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_contex= t *context) context->orig_opt_workload =3D OSNOISE_OPTION_INIT_VAL; } =20 -/* - * 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 =3D (1 << 0), FLAG_CONTEXT_DELETED =3D (1 << 1), @@ -1056,7 +1040,7 @@ struct osnoise_tool *osnoise_init_tool(char *tool_nam= e) /* * 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, stru= ct osnoise_params *params) return -1; } =20 +int osnoise_enable(struct osnoise_tool *tool) +{ + struct osnoise_params *params =3D 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 =3D 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 =3D=3D 1) { - osnoise_top_main(argc, argv); + run_tool(&osnoise_top_ops, argc, argv); exit(0); } =20 @@ -1209,13 +1231,13 @@ int osnoise_main(int argc, char *argv[]) osnoise_usage(0); } else if (strncmp(argv[1], "-", 1) =3D=3D 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") =3D=3D 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") =3D=3D 0) { - osnoise_hist_main(argc-1, &argv[1]); + run_tool(&osnoise_hist_ops, argc-1, &argv[1]); exit(0); } =20 @@ -1226,6 +1248,6 @@ int osnoise_main(int argc, char *argv[]) =20 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/osno= ise.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 { =20 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; }; =20 +#define to_osnoise_params(ptr) container_of(ptr, struct osnoise_params, co= mmon) + /* * *_INIT_VALs are also invalid values, they are used to * communicate errors. @@ -54,14 +55,17 @@ int osnoise_set_print_stack(struct osnoise_context *con= text, long long print_stack); =20 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); =20 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); } =20 +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 cp= u, unsigned long long duration, int count) { - struct osnoise_params *params =3D tool->params; + struct osnoise_params *params =3D to_osnoise_params(tool->params); struct osnoise_hist_data *data =3D tool->data; unsigned long long total_duration; int entries =3D data->entries; @@ -137,7 +142,7 @@ static void osnoise_destroy_trace_hist(struct osnoise_t= ool *tool) */ static int osnoise_init_trace_hist(struct osnoise_tool *tool) { - struct osnoise_params *params =3D tool->params; + struct osnoise_params *params =3D to_osnoise_params(tool->params); struct osnoise_hist_data *data =3D 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 =3D tool->params; + struct osnoise_params *params =3D to_osnoise_params(tool->params); struct osnoise_hist_data *data =3D tool->data; struct trace_seq *s =3D 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 *to= ol) +osnoise_print_stats(struct osnoise_tool *tool) { + struct osnoise_params *params =3D to_osnoise_params(tool->params); struct osnoise_hist_data *data =3D tool->data; struct trace_instance *trace =3D &tool->trace; int has_samples =3D 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 =3D NULL; =20 params =3D calloc(1, sizeof(*params)); if (!params) exit(1); =20 + actions_init(¶ms->common.threshold_actions); + actions_init(¶ms->common.end_actions); + /* display data in microseconds */ params->common.output_divisor =3D 1000; params->common.hist.bucket_size =3D 1; @@ -543,7 +553,7 @@ static struct osnoise_params params->threshold =3D 1; =20 /* set trace */ - params->trace_output =3D "osnoise_trace.txt"; + trace_output =3D "osnoise_trace.txt"; =20 break; case 'b': @@ -634,13 +644,13 @@ static struct osnoise_params case 't': if (optarg) { if (optarg[0] =3D=3D '=3D') - params->trace_output =3D &optarg[1]; + trace_output =3D &optarg[1]; else - params->trace_output =3D &optarg[0]; + trace_output =3D &optarg[0]; } else if (optind < argc && argv[optind][0] !=3D '0') - params->trace_output =3D argv[optind]; + trace_output =3D argv[optind]; else - params->trace_output =3D "osnoise_trace.txt"; + trace_output =3D "osnoise_trace.txt"; break; case '0': /* no header */ params->common.hist.no_header =3D 1; @@ -687,6 +697,9 @@ static struct osnoise_params } } =20 + 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 ma= ke sense"); =20 - return params; + return ¶ms->common; } =20 /* * osnoise_hist_apply_config - apply the hist configs to the initialized t= ool */ 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 =3D 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)); } =20 /* * 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; =20 - tool->data =3D osnoise_alloc_histogram(nr_cpus, params->common.hist.entri= es, - params->common.hist.bucket_size); + tool->data =3D osnoise_alloc_histogram(nr_cpus, params->hist.entries, + params->hist.bucket_size); if (!tool->data) goto out_err; =20 - tool->params =3D params; - return tool; =20 out_err: @@ -745,171 +747,35 @@ static struct osnoise_tool return NULL; } =20 -static int stop_tracing; -static void stop_hist(int sig) -{ - stop_tracing =3D 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 =3D NULL; - struct osnoise_tool *tool =3D NULL; - enum result return_value =3D ERROR; - struct trace_instance *trace; int retval; =20 - params =3D osnoise_hist_parse_args(argc, argv); - if (!params) - exit(1); - - tool =3D osnoise_init_hist(params); - if (!tool) { - err_msg("Could not init osnoise hist\n"); - goto out_exit; - } - - retval =3D osnoise_hist_apply_config(tool, params); - if (retval) { - err_msg("Could not apply config\n"); - goto out_destroy; - } - - trace =3D &tool->trace; - - retval =3D enable_osnoise(trace); - if (retval) { - err_msg("Failed to enable osnoise tracer\n"); - goto out_destroy; - } - retval =3D osnoise_init_trace_hist(tool); if (retval) - goto out_destroy; + return retval; =20 - if (params->common.set_sched) { - retval =3D 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 =3D 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 =3D osnoise_init_trace_tool("osnoise"); - if (!record) { - err_msg("Failed to enable the trace instance\n"); - goto out_free; - } - - if (params->common.events) { - retval =3D trace_events_enable(&record->trace, params->common.events); - if (retval) - goto out_hist; - } - - if (params->common.buffer_size > 0) { - retval =3D 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 =3D tracefs_instance_file_write(trace->inst, "trace", ""); - if (retval < 0) { - debug_msg("Error cleaning up the buffer"); - goto out_hist; - } - - } - - tool->start_time =3D time(NULL); - osnoise_hist_set_signals(params); - - while (!stop_tracing) { - sleep(params->common.sleep_time); - - retval =3D 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); +} =20 - if (osnoise_trace_is_off(tool, record)) - break; - } +static int osnoise_hist_main_loop(struct osnoise_tool *tool) +{ + int retval; =20 + retval =3D hist_main_loop(tool); osnoise_read_trace_hist(tool); =20 - osnoise_print_stats(params, tool); - - return_value =3D 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 =3D FAILED; - } - -out_hist: - trace_events_destroy(&record->trace, params->common.events); - params->common.events =3D 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 =3D { + .tracer =3D "osnoise", + .comm_prefix =3D "osnoise/", + .parse_args =3D osnoise_hist_parse_args, + .init_tool =3D osnoise_init_hist, + .apply_config =3D osnoise_hist_apply_config, + .enable =3D osnoise_hist_enable, + .main =3D osnoise_hist_main_loop, + .print_stats =3D osnoise_print_stats, + .free =3D 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); } =20 +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_rec= ord *record, */ static void osnoise_top_header(struct osnoise_tool *top) { - struct osnoise_params *params =3D top->params; + struct osnoise_params *params =3D to_osnoise_params(top->params); struct trace_seq *s =3D top->trace.seq; bool pretty =3D 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 =3D tool->params; + struct osnoise_params *params =3D to_osnoise_params(tool->params); struct trace_seq *s =3D 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 *to= p) +osnoise_print_stats(struct osnoise_tool *top) { + struct osnoise_params *params =3D to_osnoise_params(top->params); struct trace_instance *trace =3D &top->trace; static int nr_cpus =3D -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 =3D NULL; =20 params =3D calloc(1, sizeof(*params)); if (!params) exit(1); =20 + actions_init(¶ms->common.threshold_actions); + actions_init(¶ms->common.end_actions); + if (strcmp(argv[0], "hwnoise") =3D=3D 0) { params->mode =3D MODE_HWNOISE; /* @@ -384,7 +393,7 @@ struct osnoise_params *osnoise_top_parse_args(int argc,= char **argv) params->threshold =3D 1; =20 /* set trace */ - params->trace_output =3D "osnoise_trace.txt"; + trace_output =3D "osnoise_trace.txt"; =20 break; case 'c': @@ -463,13 +472,13 @@ struct osnoise_params *osnoise_top_parse_args(int arg= c, char **argv) case 't': if (optarg) { if (optarg[0] =3D=3D '=3D') - params->trace_output =3D &optarg[1]; + trace_output =3D &optarg[1]; else - params->trace_output =3D &optarg[0]; + trace_output =3D &optarg[0]; } else if (optind < argc && argv[optind][0] !=3D '-') - params->trace_output =3D argv[optind]; + trace_output =3D argv[optind]; else - params->trace_output =3D "osnoise_trace.txt"; + trace_output =3D "osnoise_trace.txt"; break; case 'T': params->threshold =3D get_llong_from_str(optarg); @@ -507,20 +516,24 @@ struct osnoise_params *osnoise_top_parse_args(int arg= c, char **argv) } } =20 + 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); } =20 - return params; + return ¶ms->common; } =20 /* * 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 =3D to_osnoise_params(tool->params); int retval; =20 retval =3D osnoise_apply_config(tool, params); @@ -547,7 +560,7 @@ osnoise_top_apply_config(struct osnoise_tool *tool, str= uct 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; } =20 - tool->params =3D params; - tep_register_event_handler(tool->trace.tep, -1, "ftrace", "osnoise", osnoise_top_handler, NULL); =20 return tool; } =20 -static int stop_tracing; -static void stop_top(int sig) -{ - stop_tracing =3D 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 =3D NULL; - struct osnoise_tool *tool =3D NULL; - enum result return_value =3D ERROR; - struct trace_instance *trace; - int retval; - - params =3D osnoise_top_parse_args(argc, argv); - if (!params) - exit(1); - - tool =3D osnoise_init_top(params); - if (!tool) { - err_msg("Could not init osnoise top\n"); - goto out_exit; - } - - retval =3D osnoise_top_apply_config(tool, params); - if (retval) { - err_msg("Could not apply config\n"); - goto out_free; - } - - trace =3D &tool->trace; - - retval =3D enable_osnoise(trace); - if (retval) { - err_msg("Failed to enable osnoise tracer\n"); - goto out_free; - } - - if (params->common.set_sched) { - retval =3D 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 =3D 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 =3D osnoise_init_trace_tool("osnoise"); - if (!record) { - err_msg("Failed to enable the trace instance\n"); - goto out_free; - } - - if (params->common.events) { - retval =3D trace_events_enable(&record->trace, params->common.events); - if (retval) - goto out_top; - } - - if (params->common.buffer_size > 0) { - retval =3D 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 =3D tracefs_instance_file_write(trace->inst, "trace", ""); - if (retval < 0) { - debug_msg("Error cleaning up the buffer"); - goto out_top; - } - - } - - tool->start_time =3D time(NULL); - osnoise_top_set_signals(params); - - while (!stop_tracing) { - sleep(params->common.sleep_time); - - retval =3D 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 =3D 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 =3D FAILED; - } - -out_top: - trace_events_destroy(&record->trace, params->common.events); - params->common.events =3D 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 =3D { + .tracer =3D "osnoise", + .comm_prefix =3D "osnoise/", + .parse_args =3D osnoise_top_parse_args, + .init_tool =3D osnoise_init_top, + .apply_config =3D osnoise_top_apply_config, + .enable =3D osnoise_enable, + .main =3D top_main_loop, + .print_stats =3D osnoise_print_stats, + .free =3D osnoise_free_top_tool, +}; diff --git a/tools/tracing/rtla/src/timerlat.c b/tools/tracing/rtla/src/tim= erlat.c index e4bf58db1dd2..b69212874127 100644 --- a/tools/tracing/rtla/src/timerlat.c +++ b/tools/tracing/rtla/src/timerlat.c @@ -15,9 +15,13 @@ #include =20 #include "timerlat.h" +#include "timerlat_aa.h" +#include "timerlat_bpf.h" =20 #define DEFAULT_TIMERLAT_PERIOD 1000 /* 1ms */ =20 +static int dma_latency_fd =3D -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; =20 + /* + * 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) =3D= =3D 0) { + debug_msg("RTLA_NO_BPF set, disabling BPF\n"); + params->mode =3D 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 =3D TRACING_MODE_TRACEFS; + } else { + retval =3D timerlat_bpf_init(params); + if (retval) { + debug_msg("Could not enable BPF\n"); + params->mode =3D TRACING_MODE_TRACEFS; + } + } + if (params->mode !=3D 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 =3D 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 =3D 1; - params->user_data =3D 1; + params->common.user_workload =3D 1; + params->common.user_data =3D 1; } else { debug_msg("User-space interface not detected, setting kernel-threads\n"= ); params->common.kernel_workload =3D 1; @@ -83,6 +105,137 @@ timerlat_apply_config(struct osnoise_tool *tool, struc= t timerlat_params *params) return -1; } =20 +int timerlat_enable(struct osnoise_tool *tool) +{ + struct timerlat_params *params =3D to_timerlat_params(tool->params); + int retval, nr_cpus, i; + + if (params->dma_latency >=3D 0) { + dma_latency_fd =3D 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 >=3D -1) { + if (!have_libcpupower_support()) { + err_msg("rtla built without libcpupower, --deepest-idle-state is not su= pported\n"); + return -1; + } + + nr_cpus =3D sysconf(_SC_NPROCESSORS_CONF); + + for (i =3D 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 =3D osnoise_init_tool("timerlat_aa"); + if (!tool->aa) + return -1; + + retval =3D timerlat_aa_init(tool->aa, params->dump_tasks); + if (retval) { + err_msg("Failed to enable the auto analysis instance\n"); + return retval; + } + + retval =3D 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 =3D=3D TRACING_MODE_TRACEFS) { + trace_instance_start(&tool->trace); + } else { + retval =3D 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 =3D 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 =3D tracefs_instance_file_read(trace_inst->inst, "tracing_max_la= tency", 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 =3D to_timerlat_params(tool->params); + int nr_cpus, i; + + timerlat_aa_destroy(); + if (dma_latency_fd >=3D 0) + close(dma_latency_fd); + if (params->deepest_idle_state >=3D -1) { + for (i =3D 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 !=3D 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 =3D=3D 1) { - timerlat_top_main(argc, argv); + run_tool(&timerlat_top_ops, argc, argv); exit(0); } =20 @@ -124,13 +277,13 @@ int timerlat_main(int argc, char *argv[]) timerlat_usage(0); } else if (strncmp(argv[1], "-", 1) =3D=3D 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") =3D=3D 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") =3D=3D 0) { - timerlat_hist_main(argc-1, &argv[1]); + run_tool(&timerlat_hist_ops, argc-1, &argv[1]); exit(0); } =20 diff --git a/tools/tracing/rtla/src/timerlat.h b/tools/tracing/rtla/src/tim= erlat.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" =20 /* @@ -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; }; =20 -int timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_param= s *params); +#define to_timerlat_params(ptr) container_of(ptr, struct timerlat_params, = common) =20 -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_param= s *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 =3D params->common.hist.entries; bpf->rodata->irq_threshold =3D params->common.stop_us; bpf->rodata->thread_threshold =3D params->common.stop_total_us; - bpf->rodata->aa_only =3D params->aa_only; + bpf->rodata->aa_only =3D params->common.aa_only; =20 if (params->common.hist.entries !=3D 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); } =20 - 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/sr= c/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 @@ =20 #include "timerlat.h" #include "timerlat_aa.h" -#include "timerlat_u.h" #include "timerlat_bpf.h" =20 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); +} =20 - free(data); +static void timerlat_free_histogram_tool(struct osnoise_tool *tool) +{ + timerlat_free_histogram(tool->data); + timerlat_free(tool); } =20 /* @@ -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 =3D tool->params; + struct timerlat_params *params =3D to_timerlat_params(tool->params); struct timerlat_hist_data *data =3D tool->data; int entries =3D data->entries; int bucket; @@ -282,7 +285,7 @@ static int timerlat_hist_bpf_pull_data(struct osnoise_t= ool *tool) */ static void timerlat_hist_header(struct osnoise_tool *tool) { - struct timerlat_params *params =3D tool->params; + struct timerlat_params *params =3D to_timerlat_params(tool->params); struct timerlat_hist_data *data =3D tool->data; struct trace_seq *s =3D tool->trace.seq; char duration[26]; @@ -315,7 +318,7 @@ static void timerlat_hist_header(struct osnoise_tool *t= ool) if (!params->common.hist.no_thread) trace_seq_printf(s, " Thr-%03d", cpu); =20 - 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); =20 - 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); =20 - 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); =20 - 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); =20 - 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"); =20 - if (params->user_data) + if (params->common.user_data) trace_seq_printf(trace->seq, " Usr"); =20 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); =20 - if (params->user_data) + if (params->common.user_data) trace_seq_printf(trace->seq, "%9llu ", sum.user_count); =20 @@ -558,7 +561,7 @@ timerlat_print_stats_all(struct timerlat_params *params, sum.min_thread, false); =20 - 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); =20 - 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); =20 - 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 =3D to_timerlat_params(tool->params); struct timerlat_hist_data *data =3D tool->data; struct trace_instance *trace =3D &tool->trace; int bucket, cpu; @@ -654,7 +658,7 @@ timerlat_print_stats(struct timerlat_params *params, st= ruct osnoise_tool *tool) data->hist[cpu].thread[bucket]); } =20 - if (params->user_data) { + if (params->common.user_data) { total +=3D 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, st= ruct osnoise_tool *tool) trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].thread[data->entries]); =20 - 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 paramete= rs */ -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); =20 - actions_init(¶ms->threshold_actions); - actions_init(¶ms->end_actions); + actions_init(¶ms->common.threshold_actions); + actions_init(¶ms->common.end_actions); =20 /* disabled by default */ params->dma_latency =3D -1; @@ -975,10 +979,10 @@ static struct timerlat_params trace_output =3D "timerlat_trace.txt"; break; case 'u': - params->user_workload =3D 1; + params->common.user_workload =3D 1; /* fallback: -u implies in -U */ case 'U': - params->user_data =3D 1; + params->common.user_data =3D 1; break; case '0': /* no irq */ params->common.hist.no_irq =3D 1; @@ -1043,14 +1047,14 @@ static struct timerlat_params params->deepest_idle_state =3D get_llong_from_str(optarg); break; case '\5': - retval =3D actions_parse(¶ms->threshold_actions, optarg); + retval =3D actions_parse(¶ms->common.threshold_actions, optarg); if (retval) { err_msg("Invalid action %s\n", optarg); exit(EXIT_FAILURE); } break; case '\6': - retval =3D actions_parse(¶ms->end_actions, optarg); + retval =3D 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 } =20 if (trace_output) - actions_add_trace_output(¶ms->threshold_actions, trace_output); + actions_add_trace_output(¶ms->common.threshold_actions, trace_output= ); =20 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 =3D 1; =20 - 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 ex= clusive!"); =20 /* @@ -1089,19 +1093,21 @@ static struct timerlat_params * mixed mode */ if (params->mode =3D=3D 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 =3D TRACING_MODE_MIXED; =20 - return params; + return ¶ms->common; } =20 /* * timerlat_hist_apply_config - apply the hist configs to the initialized = tool */ static int -timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_para= ms *params) +timerlat_hist_apply_config(struct osnoise_tool *tool) { + struct timerlat_params *params =3D to_timerlat_params(tool->params); int retval; =20 retval =3D 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; =20 - tool->data =3D timerlat_alloc_histogram(nr_cpus, params->common.hist.entr= ies, - params->common.hist.bucket_size); + tool->data =3D timerlat_alloc_histogram(nr_cpus, params->hist.entries, + params->hist.bucket_size); if (!tool->data) goto out_err; =20 - tool->params =3D params; - tep_register_event_handler(tool->trace.tep, -1, "ftrace", "timerlat", timerlat_hist_handler, tool); =20 @@ -1146,349 +1150,61 @@ static struct osnoise_tool return NULL; } =20 -static int stop_tracing; -static struct trace_instance *hist_inst =3D 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 =3D 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 =3D NULL; - struct timerlat_u_params params_u; - enum result return_value =3D ERROR; - struct osnoise_tool *tool =3D NULL; - struct osnoise_tool *aa =3D NULL; - struct trace_instance *trace; - int dma_latency_fd =3D -1; - pthread_t timerlat_u; + struct timerlat_params *params =3D to_timerlat_params(tool->params); int retval; - int nr_cpus, i; - - params =3D timerlat_hist_parse_args(argc, argv); - if (!params) - exit(1); - - tool =3D timerlat_init_hist(params); - if (!tool) { - err_msg("Could not init osnoise hist\n"); - goto out_exit; - } - - trace =3D &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 =3D 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) =3D= =3D 0) { - debug_msg("RTLA_NO_BPF set, disabling BPF\n"); - params->mode =3D TRACING_MODE_TRACEFS; - } else if (!tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sampl= e")) { - debug_msg("osnoise:timerlat_sample missing, disabling BPF\n"); - params->mode =3D TRACING_MODE_TRACEFS; - } else { - retval =3D timerlat_bpf_init(params); - if (retval) { - debug_msg("Could not enable BPF\n"); - params->mode =3D TRACING_MODE_TRACEFS; - } - } - - retval =3D timerlat_hist_apply_config(tool, params); - if (retval) { - err_msg("Could not apply config\n"); - goto out_free; - } - - retval =3D enable_timerlat(trace); - if (retval) { - err_msg("Failed to enable timerlat tracer\n"); - goto out_free; - } - - if (params->common.set_sched) { - retval =3D 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 =3D 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 >=3D 0) { - dma_latency_fd =3D 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 >=3D -1) { - if (!have_libcpupower_support()) { - err_msg("rtla built without libcpupower, --deepest-idle-state is not su= pported\n"); - goto out_free; - } - - nr_cpus =3D sysconf(_SC_NPROCESSORS_CONF); - - for (i =3D 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 =3D 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 =3D record->trace.inst; - params->end_actions.trace_output_inst =3D record->trace.inst; - - if (params->common.events) { - retval =3D trace_events_enable(&record->trace, params->common.events); - if (retval) - goto out_hist; - } =20 - if (params->common.buffer_size > 0) { - retval =3D trace_set_buffer_size(&record->trace, params->common.buffer_= size); - if (retval) - goto out_hist; - } - } + while (!stop_tracing) { + timerlat_bpf_wait(-1); =20 - if (!params->no_aa) { - aa =3D 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); =20 - retval =3D 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; =20 - retval =3D 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(); =20 - if (params->user_workload) { - /* rtla asked to stop */ - params_u.should_run =3D 1; - /* all threads left */ - params_u.stopped_running =3D 0; - - params_u.set =3D ¶ms->common.monitored_cpus; - if (params->common.set_sched) - params_u.sched_param =3D ¶ms->common.sched_param; - else - params_u.sched_param =3D NULL; - - params_u.cgroup_name =3D params->common.cgroup_name; - - retval =3D pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, &par= ams_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 =3D=3D TRACING_MODE_TRACEFS) { - trace_instance_start(trace); - } else { - retval =3D timerlat_bpf_attach(); - if (retval) { - err_msg("Error attaching BPF program\n"); - goto out_hist; - } - } - - tool->start_time =3D time(NULL); - timerlat_hist_set_signals(params); - - if (params->mode =3D=3D TRACING_MODE_TRACEFS) { - while (!stop_tracing) { - sleep(params->common.sleep_time); - - retval =3D 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 !=3D TRACING_MODE_TRACEFS) { - timerlat_bpf_detach(); - retval =3D 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 =3D 0; - sleep(1); - } - - timerlat_print_stats(params, tool); - - actions_perform(¶ms->end_actions); - - return_value =3D PASSED; + retval =3D timerlat_hist_bpf_pull_data(tool); + if (retval) + err_msg("Error pulling BPF data\n"); =20 - if (osnoise_trace_is_off(tool, record) && !stop_tracing) { - printf("rtla timerlat hit stop tracing\n"); + return retval; +} =20 - 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 =3D to_timerlat_params(tool->params); + int retval; =20 - return_value =3D FAILED; - } + if (params->mode =3D=3D TRACING_MODE_TRACEFS) + retval =3D hist_main_loop(tool); + else + retval =3D timerlat_hist_bpf_main_loop(tool); =20 -out_hist: - timerlat_aa_destroy(); - if (dma_latency_fd >=3D 0) - close(dma_latency_fd); - if (params->deepest_idle_state >=3D -1) { - for (i =3D 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 =3D 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 !=3D 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 =3D { + .tracer =3D "timerlat", + .comm_prefix =3D "timerlat/", + .parse_args =3D timerlat_hist_parse_args, + .init_tool =3D timerlat_init_hist, + .apply_config =3D timerlat_hist_apply_config, + .enable =3D timerlat_enable, + .main =3D timerlat_hist_main, + .print_stats =3D timerlat_print_stats, + .analyze =3D timerlat_analyze, + .free =3D 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 @@ =20 #include "timerlat.h" #include "timerlat_aa.h" -#include "timerlat_u.h" #include "timerlat_bpf.h" =20 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); } =20 +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 =3D tool->params; + struct timerlat_params *params =3D to_timerlat_params(tool->params); struct timerlat_top_data *data =3D tool->data; struct timerlat_top_cpu *cpu_data =3D &data->cpu_data[cpu]; =20 @@ -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 =3D context; - struct timerlat_params *params; unsigned long long latency, thread; struct osnoise_tool *top; int cpu =3D record->cpu; =20 top =3D container_of(trace, struct osnoise_tool, trace); - params =3D top->params; =20 - 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); =20 @@ -267,7 +269,7 @@ static void timerlat_top_header(struct timerlat_params = *params, struct osnoise_t trace_seq_printf(s, "\033[2;37;40m"); =20 trace_seq_printf(s, " Timer Latency = "); - if (params->user_data) + if (params->common.user_data) trace_seq_printf(s, " "); =20 if (pretty) @@ -278,7 +280,7 @@ static void timerlat_top_header(struct timerlat_params = *params, struct osnoise_t params->common.output_divisor =3D=3D 1 ? "ns" : "us", params->common.output_divisor =3D=3D 1 ? "ns" : "us"); =20 - if (params->user_data) { + if (params->common.user_data) { trace_seq_printf(s, " | Ret user Timer Latency (%s)", params->common.output_divisor =3D=3D 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"); =20 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"); =20 if (pretty) @@ -303,8 +305,7 @@ static const char *no_value =3D " -"; */ static void timerlat_top_print(struct osnoise_tool *top, int cpu) { - - struct timerlat_params *params =3D top->params; + struct timerlat_params *params =3D to_timerlat_params(top->params); struct timerlat_top_data *data =3D top->data; struct timerlat_top_cpu *cpu_data =3D &data->cpu_data[cpu]; struct trace_seq *s =3D 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); } =20 - 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 =3D "----------------------------------------"; - struct timerlat_params *params =3D top->params; + struct timerlat_params *params =3D to_timerlat_params(top->params); unsigned long long count =3D summary->irq_count; struct trace_seq *s =3D top->trace.seq; int e =3D 0; @@ -381,7 +382,7 @@ timerlat_top_print_sum(struct osnoise_tool *top, struct= timerlat_top_cpu *summar } =20 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"); =20 @@ -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); } =20 - 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 =3D to_timerlat_params(top->params); struct trace_instance *trace =3D &top->trace; struct timerlat_top_cpu summary; static int nr_cpus =3D -1; int i; =20 - if (params->aa_only) + if (params->common.aa_only) return; =20 if (nr_cpus =3D=3D -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); =20 - actions_init(¶ms->threshold_actions); - actions_init(¶ms->end_actions); + actions_init(¶ms->common.threshold_actions); + actions_init(¶ms->common.end_actions); =20 /* disabled by default */ params->dma_latency =3D -1; @@ -641,7 +643,7 @@ static struct timerlat_params params->print_stack =3D auto_thresh; =20 /* set aa_only to avoid parsing the trace */ - params->aa_only =3D 1; + params->common.aa_only =3D 1; break; case 'c': retval =3D parse_cpu_set(optarg, ¶ms->common.monitored_cpus); @@ -731,10 +733,10 @@ static struct timerlat_params trace_output =3D "timerlat_trace.txt"; break; case 'u': - params->user_workload =3D true; + params->common.user_workload =3D true; /* fallback: -u implies -U */ case 'U': - params->user_data =3D true; + params->common.user_data =3D true; break; case '0': /* trigger */ if (params->common.events) { @@ -781,14 +783,14 @@ static struct timerlat_params params->deepest_idle_state =3D get_llong_from_str(optarg); break; case '9': - retval =3D actions_parse(¶ms->threshold_actions, optarg); + retval =3D actions_parse(¶ms->common.threshold_actions, optarg); if (retval) { err_msg("Invalid action %s\n", optarg); exit(EXIT_FAILURE); } break; case '\1': - retval =3D actions_parse(¶ms->end_actions, optarg); + retval =3D 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 } =20 if (trace_output) - actions_add_trace_output(¶ms->threshold_actions, trace_output); + actions_add_trace_output(¶ms->common.threshold_actions, trace_output= ); =20 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 =3D 1; =20 - 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!"); =20 - 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 exc= lusive!"); =20 /* @@ -824,19 +826,21 @@ static struct timerlat_params * mixed mode */ if (params->mode =3D=3D 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 =3D TRACING_MODE_MIXED; =20 - return params; + return ¶ms->common; } =20 /* * timerlat_top_apply_config - apply the top configs to the initialized to= ol */ 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 =3D to_timerlat_params(top->params); int retval; =20 retval =3D timerlat_apply_config(top, params); @@ -856,7 +860,7 @@ timerlat_top_apply_config(struct osnoise_tool *top, str= uct 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; =20 - top->params =3D params; - tep_register_event_handler(top->trace.tep, -1, "ftrace", "timerlat", timerlat_top_handler, top); =20 @@ -883,109 +885,16 @@ static struct osnoise_tool return NULL; } =20 -static int stop_tracing; -static struct trace_instance *top_inst =3D 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 =3D 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 =3D &top->trace; - int retval; - - while (!stop_tracing) { - sleep(params->common.sleep_time); - - if (params->aa_only && !osnoise_trace_is_off(top, record)) - continue; - - retval =3D 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 =3D to_timerlat_params(tool->params); int retval, wait_retval; =20 - 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 =3D timerlat_bpf_wait(params->common.quiet ? -1 : params->common.sleep_time); =20 - retval =3D timerlat_top_bpf_pull_data(top); + retval =3D timerlat_top_bpf_pull_data(tool); if (retval) { err_msg("Error pulling BPF data\n"); return retval; } =20 if (!params->common.quiet) - timerlat_print_stats(params, top); + timerlat_print_stats(tool); =20 if (wait_retval =3D=3D 1) { /* Stopping requested by tracer */ - actions_perform(¶ms->threshold_actions); + actions_perform(¶ms->common.threshold_actions); =20 - if (!params->threshold_actions.continue_flag) + if (!params->common.threshold_actions.continue_flag) /* continue flag not set, break */ break; =20 /* 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(); } =20 /* 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; } =20 -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 =3D NULL; - struct timerlat_u_params params_u; - enum result return_value =3D ERROR; - struct osnoise_tool *top =3D NULL; - struct osnoise_tool *aa =3D NULL; - struct trace_instance *trace; - int dma_latency_fd =3D -1; - pthread_t timerlat_u; - char *max_lat; + struct timerlat_params *params =3D to_timerlat_params(tool->params); int retval; - int nr_cpus, i; - - params =3D timerlat_top_parse_args(argc, argv); - if (!params) - exit(1); - - top =3D timerlat_init_top(params); - if (!top) { - err_msg("Could not init osnoise top\n"); - goto out_exit; - } - - trace =3D &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 =3D 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) =3D= =3D 0) { - debug_msg("RTLA_NO_BPF set, disabling BPF\n"); - params->mode =3D TRACING_MODE_TRACEFS; - } else if (!tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sampl= e")) { - debug_msg("osnoise:timerlat_sample missing, disabling BPF\n"); - params->mode =3D TRACING_MODE_TRACEFS; - } else { - retval =3D timerlat_bpf_init(params); - if (retval) { - debug_msg("Could not enable BPF\n"); - params->mode =3D TRACING_MODE_TRACEFS; - } - } - - retval =3D timerlat_top_apply_config(top, params); - if (retval) { - err_msg("Could not apply config\n"); - goto out_free; - } =20 - retval =3D enable_timerlat(trace); - if (retval) { - err_msg("Failed to enable timerlat tracer\n"); - goto out_free; - } - - if (params->common.set_sched) { - retval =3D 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 =3D 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 >=3D 0) { - dma_latency_fd =3D 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 >=3D -1) { - if (!have_libcpupower_support()) { - err_msg("rtla built without libcpupower, --deepest-idle-state is not su= pported\n"); - goto out_free; - } - - nr_cpus =3D sysconf(_SC_NPROCESSORS_CONF); - - for (i =3D 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 =3D 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 =3D record->trace.inst; - params->end_actions.trace_output_inst =3D record->trace.inst; - - if (params->common.events) { - retval =3D trace_events_enable(&record->trace, params->common.events); - if (retval) - goto out_top; - } - - if (params->common.buffer_size > 0) { - retval =3D trace_set_buffer_size(&record->trace, params->common.buffer_= size); - if (retval) - goto out_top; - } - } - - if (!params->no_aa) { - aa =3D osnoise_init_tool("timerlat_aa"); - if (!aa) - goto out_top; - - retval =3D 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 !=3D top) { - retval =3D 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 =3D 1; - /* all threads left */ - params_u.stopped_running =3D 0; - - params_u.set =3D ¶ms->common.monitored_cpus; - if (params->common.set_sched) - params_u.sched_param =3D ¶ms->common.sched_param; - else - params_u.sched_param =3D NULL; - - params_u.cgroup_name =3D params->common.cgroup_name; - - retval =3D pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, &par= ams_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 =3D=3D TRACING_MODE_TRACEFS) { - trace_instance_start(trace); + retval =3D top_main_loop(tool); } else { - retval =3D timerlat_bpf_attach(); - if (retval) { - err_msg("Error attaching BPF program\n"); - goto out_top; - } - } - - top->start_time =3D time(NULL); - timerlat_top_set_signals(params); - - if (params->mode =3D=3D TRACING_MODE_TRACEFS) - retval =3D timerlat_top_main_loop(top, record, aa, params, ¶ms_u); - else - retval =3D timerlat_top_bpf_main_loop(top, record, aa, params, ¶ms_u= ); - - if (retval) - goto out_top; - - if (params->mode !=3D TRACING_MODE_TRACEFS) + retval =3D timerlat_top_bpf_main_loop(tool); timerlat_bpf_detach(); - - if (params->user_workload && !params_u.stopped_running) { - params_u.should_run =3D 0; - sleep(1); } =20 - timerlat_print_stats(params, top); - - actions_perform(¶ms->end_actions); - - return_value =3D 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 =3D FAILED; - } else if (params->aa_only) { - /* - * If the trace did not stop with --aa-only, at least print the - * max known latency. - */ - max_lat =3D 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 >=3D 0) - close(dma_latency_fd); - if (params->deepest_idle_state >=3D -1) { - for (i =3D 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 =3D NULL; -out_free: - timerlat_free_top(top->data); - if (aa && aa !=3D 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 !=3D 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 =3D { + .tracer =3D "timerlat", + .comm_prefix =3D "timerlat/", + .parse_args =3D timerlat_top_parse_args, + .init_tool =3D timerlat_init_top, + .apply_config =3D timerlat_top_apply_config, + .enable =3D timerlat_enable, + .main =3D timerlat_top_main_loop, + .print_stats =3D timerlat_print_stats, + .analyze =3D timerlat_analyze, + .free =3D 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 *trace= r_name); void disable_tracer(struct tracefs_instance *inst); =20 -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); =20 --=20 2.50.1 From nobody Wed Oct 1 21:27:15 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D0E0C222560 for ; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; cv=none; b=sCqckFgyPi4zCWOjtLjofAnzYYQrSn7OR5FHkOE99a+z6JivoKBwvuO+iZQH5ukc4oZCmsmPHvSvre0qA7yjiUjqf1vtVH4TwcPHDdQLAAkM1SM1z9HcdLnX1zd8tsEcs6qmJBjLa52MiUQAXf+KuaRYIXVbYYsy3GEx7ktQ6cg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; c=relaxed/simple; bh=zLfsWruy6Xs0wNtkHN+BYo1fj9b0x8wG3OoFp5mP224=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=atkktNQbCoWfvruw91vCBv23VTnI55nwY+GFUDr4R/tTAd8K04lD543j5XJXL8nhE39RRdH9PnAQVG3bi20KHzVGwjp/qoQYbjk5SzGwvtPK+r1O0koI2ZkhTEhvzF4hclTpUGNcjL7XD4Sw1csAFKXjqYYTbQqh1z9f/e5Q4Ik= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GnznvQo5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GnznvQo5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 85925C19421; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1759268718; bh=zLfsWruy6Xs0wNtkHN+BYo1fj9b0x8wG3OoFp5mP224=; h=Date:From:To:Cc:Subject:References:From; b=GnznvQo5oKfmY8mhI5lPPvNtmWDMjWBkeM8Sju6LIHBp+YegJ4VA8S6ggutb1bL3O QwGpQknehpxpK510RoaFXXeSSh9PmDnaygeM3/sjUTgbt6j1RoKME82B7R3lO/4CHC wavOGKSyToUJ8M3N88Kg7xf+ds78PGAkbApYN2EJV4E0f99z6WIEu6fsfw45qAZ4dB u0VEw/h+TSlOq7lJPIr2MbjCc/dB0ulSIZApecK3BxkJoiE617d+lyHbGk48ozbpvX QKtESx0RVmTEWbXQpInV0TUV3LLFXWw7H6PGfAk8GL2fW1XqJIKKuVbEBlQwF2qved PLfxbDGdIiwjQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1v3iBT-0000000DUw6-0NSJ; Tue, 30 Sep 2025 17:46:55 -0400 Message-ID: <20250930214654.944795507@kernel.org> User-Agent: quilt/0.68 Date: Tue, 30 Sep 2025 17:46:35 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Costa Shulyupin , Crystal Wood Subject: [for-next][PATCH 5/7] tools/rtla: Fix -A option name in test comment References: <20250930214630.332381812@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Crystal Wood This was changed to --on-threshold when the patches were applied. Cc: John Kacur Cc: Costa Shulyupin Link: https://lore.kernel.org/20250907022325.243930-6-crwood@redhat.com Reviewed-by: Tomas Glozar Signed-off-by: Crystal Wood Signed-off-by: Steven Rostedt (Google) --- 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=3Dcustom_filename.txt" 2 "^= Saving trace to custom_filename.txt$" check "exec command" \ "timerlat hist -T 2 --on-threshold shell,command=3D'echo TestOutput'" 2 "= ^TestOutput$" --=20 2.50.1 From nobody Wed Oct 1 21:27:15 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D9E7C257852 for ; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; cv=none; b=bwYF+SzG8nTJb+QggPrwypw7WMRBWBuaiKUMV4qjGx1wjMwX/Wo8fmIhTOHyZ7j3/a6w3M7dJz+wg1sKMDmLzYTG8UMeqhHBMCe2fQhl9tNx+dx4fGvcc7KPLnE9h5TAV6NgzggflTm7f2083W/CC4AtZTboZKkwpl45iRb0jLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268718; c=relaxed/simple; bh=3StoqyMGT6v5eQNsTkgk+H1mGh93ioOe8+erb2QLPCY=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=H9+Gu+6ZlH0uzfa3/t6ke4BGMzyPo9r6JdgRiSfaxoSunRy8MaqRbUdi8e7VX/bpF0YGtq++URV7fndlEZCHiwYiyBTkJmOOmh4h4eF6ue52ejYVeyH8cCr1p00+PY3Lz82m84MhwuKPd2XOsWA1Jh+9lKwvQW504HRRnQCOkMs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Nm9hHsHs; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Nm9hHsHs" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B7342C16AAE; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1759268718; bh=3StoqyMGT6v5eQNsTkgk+H1mGh93ioOe8+erb2QLPCY=; h=Date:From:To:Cc:Subject:References:From; b=Nm9hHsHs8iyuBv6PZTbPFXlhgnJ5hbB7bWmC55ManGtmk4eCg2k3bPwQHl3lM/fux uZLHqnbywgNgQa80S2hEy9AL4/UlQM5iOJwxPFJszS+2pjwNbFc9Oe5EpZ7st10yQW POM8/VvKjRtVigfd7U3haJl6/rrS213++ZBJ6Eaqrty9irVKDdkBOK3HX5+881GCdW KsOAKcEu7F9aq9d8tcK8oaFjx0TikF7z41mvV0NC/6gJ0eFBihMQJZ8YsRM2qTyCvB 5mT0DIsTFREAaJL+eohcPSqA2Gk6/d0CvgfSdyN71CyJJvcnp7Qmky9IXZO1TMz1kE siH3JjwPw4cIw== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1v3iBT-0000000DUwa-15b6; Tue, 30 Sep 2025 17:46:55 -0400 Message-ID: <20250930214655.111658900@kernel.org> User-Agent: quilt/0.68 Date: Tue, 30 Sep 2025 17:46:36 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Costa Shulyupin , Crystal Wood Subject: [for-next][PATCH 6/7] tools/rtla: Add test engine support for unexpected output References: <20250930214630.332381812@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: 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. Cc: John Kacur Cc: Costa Shulyupin Link: https://lore.kernel.org/20250907022325.243930-7-crwood@redhat.com Reviewed-by: Tomas Glozar Signed-off-by: Crystal Wood Signed-off-by: Steven Rostedt (Google) --- 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=3D$1 expected_exitcode=3D${3:-0} expected_output=3D$4 + unexpected_output=3D$5 # Simple check: run rtla with given arguments and test exit code. # If TEST_COUNT is set, run the test. Otherwise, just count. ctr=3D$(($ctr + 1)) @@ -53,24 +54,33 @@ check() { # Run rtla; in case of failure, include its output as comment # in the test results. result=3D$(eval stdbuf -oL $TIMEOUT "$RTLA" $2 2>&1); exitcode=3D$? + failbuf=3D'' + fail=3D0 + # Test if the results matches if requested - if [ -n "$expected_output" ] + if [ -n "$expected_output" ] && ! grep -qE "$expected_output" <<< "$resu= lt" then - grep -E "$expected_output" <<< "$result" > /dev/null; grep_result=3D$? - else - grep_result=3D0 + fail=3D1 + failbuf+=3D$(printf "# Output match failed: \"%s\"" "$expected_output") + failbuf+=3D$'\n' fi =20 - if [ $exitcode -eq $expected_exitcode ] && [ $grep_result -eq 0 ] + if [ -n "$unexpected_output" ] && grep -qE "$unexpected_output" <<< "$re= sult" + then + fail=3D1 + failbuf+=3D$(printf "# Output non-match failed: \"%s\"" "$unexpected_ou= tput") + failbuf+=3D$'\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 } --=20 2.50.1 From nobody Wed Oct 1 21:27:15 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C31828C01E for ; Tue, 30 Sep 2025 21:45:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268719; cv=none; b=E4v7bcN4dFV34n7qVboyakFFTFM7kRrbfJ0tY1q5oTuR1rS73ipq8p7Dba+32tUSCaWlLeFYchNjpjYihxXjg7qyMdoithcYZNDH+x6JcclakYZBCeMC4X4kOgm8ewhM5/xc8AO+JYF90rwUGpysF3rXkDPLv9tVuQYbLb5BoqY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759268719; c=relaxed/simple; bh=vhfCCAGBjZ+sKsHITf6F2tgtkkrDk1vWKygP1Nk3KbQ=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=DED2LPPQUll7/nWQahlw1iHznwMOYxOm71sw/v/0FzTY8uaRrQgInR53Jsws9XVHQCBPa9dW7fUm/s6QUSLd7hGVPSlO8Cu8vkxBhLjvHqWhBIgaIYYQIxnAz+o3BSGmfV8OLbwazW/j+J/CfES0zN4ODcHgyO5662g7USTW6Jg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=otOyGW03; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="otOyGW03" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CD752C113CF; Tue, 30 Sep 2025 21:45:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1759268719; bh=vhfCCAGBjZ+sKsHITf6F2tgtkkrDk1vWKygP1Nk3KbQ=; h=Date:From:To:Cc:Subject:References:From; b=otOyGW03zNy7rBrOD+Csc1mh174ELjEyTkY/kdgzH8wRXuo7o0XcwN+iI0E6tFDL0 QQf0G/Pa1ic2mLNFoH02rM4JHsLC9q4i8efNmzYUT4i7gUFNkyDE8jSh7hGk1tMAj5 eNCxmdjKdhbm54PaKw4n5Ow0gylHqmQODysiLf79gtSkGfq35CsAZnoqPOybCURTMn S6omkRBxTiMn3KPHaUBpdwFtGpmWYc99y/JxMEdfv2N3ac1fwMfFjFDHH3XAXB+eCM 1acx1ezhh0XMCKpHKPfz0Oeq7HQ1dWJ8l7AXhGhhOC3FG9jF3ePEo6SdYaTdPL/sJh VmDlhecaWM32g== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1v3iBT-0000000DUx5-1nRW; Tue, 30 Sep 2025 17:46:55 -0400 Message-ID: <20250930214655.279642395@kernel.org> User-Agent: quilt/0.68 Date: Tue, 30 Sep 2025 17:46:37 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Costa Shulyupin , Crystal Wood Subject: [for-next][PATCH 7/7] tools/rtla: Add remaining support for osnoise actions References: <20250930214630.332381812@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Crystal Wood The basic functionality came with the consolidation; now hook up the command line options, and add documentation and tests. Cc: John Kacur Cc: Costa Shulyupin Link: https://lore.kernel.org/20250907022325.243930-8-crwood@redhat.com Reviewed-by: Tomas Glozar Signed-off-by: Crystal Wood Signed-off-by: Steven Rostedt (Google) --- 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/to= ols/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. =20 +**--on-threshold** *action* + + Defines an action to be executed when tracing is stopped on a late= ncy 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 actio= ns in the list + will not be executed. + + Supported actions are: + + - *trace[,file=3D]* + + 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=3D,pid=3D* + + Sends signal to process. "parent" might be specified in place of= pid to target + the parent process of rtla. + + - *shell,command=3D* + + 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=3D"grep ipi_send |tracer|\_trace.txt" + --on-threshold signal,num=3D2,pid=3Dparent + + 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 sen= d 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 execu= ted 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 suppo= rted 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** =20 Print help menu. diff --git a/Documentation/tools/rtla/common_osnoise_options.rst b/Document= ation/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-tot= al** +.. |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* =20 Set the automatic trace mode. This mode sets some commonly used op= tions diff --git a/Documentation/tools/rtla/common_timerlat_options.rst b/Documen= tation/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 timerl= at** with BPF + support and RT priority. Note that due to implementational limitat= ions, actions + might be delayed up to one second after tracing is stopped if BPF = mode is not + available or disabled. + **-a**, **--auto** *us* =20 Set the automatic trace mode. This mode sets some commonly used op= tions @@ -55,67 +65,3 @@ Set timerlat to run without workload, waiting for the user to disp= atch a per-cpu task that waits for a new period on the tracing/osnoise/per_cpu/cp= u$ID/timerlat_fd. See linux/tools/rtla/sample/timerlat_load.py for an example of use= r-load code. - -**--on-threshold** *action* - - Defines an action to be executed when tracing is stopped on a late= ncy 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 actio= ns in the list - will not be executed. - - Supported actions are: - - - *trace[,file=3D]* - - 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=3D,pid=3D* - - Sends signal to process. "parent" might be specified in place of= pid to target - the parent process of rtla. - - - *shell,command=3D* - - 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=3D"grep ipi_send timerlat_trace.txt" - --on-threshold signal,num=3D2,pid=3Dparent - - This will save a trace with the default filename "timerlat_trace.t= xt", print its - lines that contain the text "ipi_send" on standard output, and sen= d signal 2 - (SIGINT) to the parent process. - - Performance Considerations: - - For time-sensitive actions, it is recommended to run **rtla timerl= at** with BPF - support and RT priority. Note that due to implementational limitat= ions, 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** t= racing. - - Multiple --on-end actions can be specified, and they will be execu= ted 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 suppo= rted 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/tool= s/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 =20 +.. |tool| replace:: hwnoise + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D rtla-hwnoise =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D rtla-osnoise-hist =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D rtla-osnoise-top =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D diff --git a/Documentation/tools/rtla/rtla-timerlat-hist.rst b/Documentatio= n/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 + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D rtla-timerlat-hist =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 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 + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D rtla-timerlat-top =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D diff --git a/tools/tracing/rtla/src/actions.c b/tools/tracing/rtla/src/acti= ons.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 *trace= fn) { enum action_type type =3D ACTION_NONE; - char *token; + const char *token; char trigger_c[strlen(trigger)]; =20 /* For ACTION_SIGNAL */ int signal =3D 0, pid =3D 0; =20 /* For ACTION_TRACE_OUTPUT */ - char *trace_output; + const char *trace_output; =20 strcpy(trigger_c, trigger); token =3D strtok(trigger_c, ","); @@ -160,7 +160,7 @@ actions_parse(struct actions *self, const char *trigger) case ACTION_TRACE_OUTPUT: /* Takes no argument */ if (token =3D=3D NULL) - trace_output =3D "timerlat_trace.txt"; + trace_output =3D tracefn; else { if (strlen(token) > 5 && strncmp(token, "file=3D", 5) =3D=3D 0) { trace_output =3D token + 5; diff --git a/tools/tracing/rtla/src/actions.h b/tools/tracing/rtla/src/acti= ons.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 *t= racefn); 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 d= ata", " --trace-buffer-size kB: set the per-cpu trace buffer size in kB", + " --on-threshold : define action to be executed at stop-tot= al threshold, multiple are allowed", + " --on-end : define action to be executed at measurement en= d, multiple are allowed", NULL, }; =20 @@ -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} }; =20 @@ -692,6 +696,22 @@ static struct common_params case '7': params->common.buffer_size =3D get_llong_from_str(optarg); break; + case '8': + retval =3D 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 =3D 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 *pa= rams, 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 : define action to be executed at stop-tot= al threshold, multiple are allowed", + " --on-end: define action to be executed at measurement end, multip= le are allowed", NULL, }; =20 @@ -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} }; =20 @@ -511,6 +515,22 @@ struct common_params *osnoise_top_parse_args(int argc,= char **argv) case '3': params->common.buffer_size =3D get_llong_from_str(optarg); break; + case '4': + retval =3D 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 =3D 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/sr= c/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 =3D get_llong_from_str(optarg); break; case '\5': - retval =3D actions_parse(¶ms->common.threshold_actions, optarg); + retval =3D 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 =3D actions_parse(¶ms->common.end_actions, optarg); + retval =3D 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 =3D get_llong_from_str(optarg); break; case '9': - retval =3D actions_parse(¶ms->common.threshold_actions, optarg); + retval =3D 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 =3D actions_parse(¶ms->common.end_actions, optarg); + retval =3D 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,co= mmand=3D\"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=3D600000000 =20 +# Actions tests +check "trace output through -t with custom filename" \ + "osnoise hist -S 2 -t custom_filename.txt" 2 "^ Saving trace to custom_f= ilename.txt$" +check "trace output through --on-threshold trace" \ + "osnoise hist -S 2 --on-threshold trace" 2 "^ Saving trace to osnoise_tr= ace.txt$" +check "trace output through --on-threshold trace with custom filename" \ + "osnoise hist -S 2 --on-threshold trace,file=3Dcustom_filename.txt" 2 "^ = Saving trace to custom_filename.txt$" +check "exec command" \ + "osnoise hist -S 2 --on-threshold shell,command=3D'echo TestOutput'" 2 "^= TestOutput$" +check "multiple actions" \ + "osnoise hist -S 2 --on-threshold shell,command=3D'echo -n 1' --on-thresh= old shell,command=3D'echo 2'" 2 "^12$" +check "hist stop at failed action" \ + "osnoise hist -S 2 --on-threshold shell,command=3D'echo -n 1; false' --on= -threshold shell,command=3D'echo -n 2'" 2 "^1# RTLA osnoise histogram$" +check "top stop at failed action" \ + "timerlat top -T 2 --on-threshold shell,command=3D'echo -n abc; false' --= on-threshold shell,command=3D'echo -n defgh'" 2 "^abc" "defgh" +check "hist with continue" \ + "osnoise hist -S 2 -d 1s --on-threshold shell,command=3D'echo TestOutput'= --on-threshold continue" 0 "^TestOutput$" +check "top with continue" \ + "osnoise top -q -S 2 -d 1s --on-threshold shell,command=3D'echo TestOutpu= t' --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.t= xt$" +check "top with trace output at end" \ + "osnoise top -d 1s --on-end trace" 0 "^ Saving trace to osnoise_trace.tx= t$" + test_end --=20 2.50.1