Skip to content

Commit 8b6cbca

Browse files
lenticularis39rostedt
authored andcommitted
rtla/timerlat: Introduce enum timerlat_tracing_mode
After the introduction of BPF-based sample collection, rtla-timerlat effectively runs in one of three modes: - Pure BPF mode, with tracefs only being used to set up the timerlat tracer. Sample processing and stop on threshold are handled by BPF. - tracefs mode. BPF is unsupported or kernel is lacking the necessary trace event (osnoise:timerlat_sample). Stop on theshold is handled by timerlat tracer stopping tracing in all instances. - BPF/tracefs mixed mode - BPF is used for sample collection for top or histogram, tracefs is used for trace output and/or auto-analysis. Stop on threshold is handled both through BPF program, which stops sample collection for top/histogram and wakes up rtla, and by timerlat tracer, which stops tracing for trace output/auto-analysis instances. Add enum timerlat_tracing_mode, with three values: - TRACING_MODE_BPF - TRACING_MODE_TRACEFS - TRACING_MODE_MIXED Those represent the modes described above. A field of this type is added to struct timerlat_params, named "mode", replacing the no_bpf variable. params->mode is set in timerlat_{top,hist}_parse_args to TRACING_MODE_BPF or TRACING_MODE_MIXED based on whether trace output and/or auto-analysis is requested. timerlat_{top,hist}_main then checks if BPF is not unavailable or disabled, in that case, it sets params->mode to TRACING_MODE_TRACEFS. A condition is added to timerlat_apply_config that skips setting timerlat tracer thresholds if params->mode is TRACING_MODE_BPF (those are unnecessary, since they only turn off tracing, which is already turned off in that case, since BPF is used to collect samples). Cc: John Kacur <[email protected]> Cc: Luis Goncalves <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: Chang Yin <[email protected]> Cc: Costa Shulyupin <[email protected]> Cc: Crystal Wood <[email protected]> Cc: Gabriele Monaco <[email protected]> Link: https://lore.kernel.org/[email protected] Signed-off-by: Tomas Glozar <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent d7b8f8e commit 8b6cbca

File tree

4 files changed

+97
-53
lines changed

4 files changed

+97
-53
lines changed

tools/tracing/rtla/src/timerlat.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,22 @@ timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
4040
CPU_SET(i, &params->monitored_cpus);
4141
}
4242

43-
retval = osnoise_set_stop_us(tool->context, params->stop_us);
44-
if (retval) {
45-
err_msg("Failed to set stop us\n");
46-
goto out_err;
47-
}
43+
if (params->mode != TRACING_MODE_BPF) {
44+
/*
45+
* In tracefs and mixed mode, timerlat tracer handles stopping
46+
* on threshold
47+
*/
48+
retval = osnoise_set_stop_us(tool->context, params->stop_us);
49+
if (retval) {
50+
err_msg("Failed to set stop us\n");
51+
goto out_err;
52+
}
4853

49-
retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us);
50-
if (retval) {
51-
err_msg("Failed to set stop total us\n");
52-
goto out_err;
54+
retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us);
55+
if (retval) {
56+
err_msg("Failed to set stop total us\n");
57+
goto out_err;
58+
}
5359
}
5460

5561

tools/tracing/rtla/src/timerlat.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include "osnoise.h"
33

4+
/*
5+
* Define timerlat tracing mode.
6+
*
7+
* There are three tracing modes:
8+
* - tracefs-only, used when BPF is unavailable.
9+
* - BPF-only, used when BPF is available and neither trace saving nor
10+
* auto-analysis are enabled.
11+
* - mixed mode, used when BPF is available and either trace saving or
12+
* auto-analysis is enabled (which rely on sample collection through
13+
* tracefs).
14+
*/
15+
enum timerlat_tracing_mode {
16+
TRACING_MODE_BPF,
17+
TRACING_MODE_TRACEFS,
18+
TRACING_MODE_MIXED,
19+
};
20+
421
struct timerlat_params {
522
/* Common params */
623
char *cpus;
@@ -30,6 +47,7 @@ struct timerlat_params {
3047
cpu_set_t hk_cpu_set;
3148
struct sched_attr sched_param;
3249
struct trace_events *events;
50+
enum timerlat_tracing_mode mode;
3351
union {
3452
struct {
3553
/* top only */

tools/tracing/rtla/src/timerlat_hist.c

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,9 @@ static struct timerlat_params
802802
params->bucket_size = 1;
803803
params->entries = 256;
804804

805+
/* default to BPF mode */
806+
params->mode = TRACING_MODE_BPF;
807+
805808
while (1) {
806809
static struct option long_options[] = {
807810
{"auto", required_argument, 0, 'a'},
@@ -1054,6 +1057,13 @@ static struct timerlat_params
10541057
if (params->kernel_workload && params->user_workload)
10551058
timerlat_hist_usage("--kernel-threads and --user-threads are mutually exclusive!");
10561059

1060+
/*
1061+
* If auto-analysis or trace output is enabled, switch from BPF mode to
1062+
* mixed mode
1063+
*/
1064+
if (params->mode == TRACING_MODE_BPF && params->trace_output && !params->no_aa)
1065+
params->mode = TRACING_MODE_MIXED;
1066+
10571067
return params;
10581068
}
10591069

@@ -1149,7 +1159,6 @@ int timerlat_hist_main(int argc, char *argv[])
11491159
pthread_t timerlat_u;
11501160
int retval;
11511161
int nr_cpus, i;
1152-
bool no_bpf = false;
11531162

11541163
params = timerlat_hist_parse_args(argc, argv);
11551164
if (!params)
@@ -1161,12 +1170,6 @@ int timerlat_hist_main(int argc, char *argv[])
11611170
goto out_exit;
11621171
}
11631172

1164-
retval = timerlat_hist_apply_config(tool, params);
1165-
if (retval) {
1166-
err_msg("Could not apply config\n");
1167-
goto out_free;
1168-
}
1169-
11701173
trace = &tool->trace;
11711174
/*
11721175
* Save trace instance into global variable so that SIGINT can stop
@@ -1175,24 +1178,30 @@ int timerlat_hist_main(int argc, char *argv[])
11751178
*/
11761179
hist_inst = trace;
11771180

1181+
/*
1182+
* Try to enable BPF, unless disabled explicitly.
1183+
* If BPF enablement fails, fall back to tracefs mode.
1184+
*/
11781185
if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
11791186
debug_msg("RTLA_NO_BPF set, disabling BPF\n");
1180-
no_bpf = true;
1181-
}
1182-
1183-
if (!no_bpf && !tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
1187+
params->mode = TRACING_MODE_TRACEFS;
1188+
} else if (!tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
11841189
debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
1185-
no_bpf = true;
1186-
}
1187-
1188-
if (!no_bpf) {
1190+
params->mode = TRACING_MODE_TRACEFS;
1191+
} else {
11891192
retval = timerlat_bpf_init(params);
11901193
if (retval) {
11911194
debug_msg("Could not enable BPF\n");
1192-
no_bpf = true;
1195+
params->mode = TRACING_MODE_TRACEFS;
11931196
}
11941197
}
11951198

1199+
retval = timerlat_hist_apply_config(tool, params);
1200+
if (retval) {
1201+
err_msg("Could not apply config\n");
1202+
goto out_free;
1203+
}
1204+
11961205
retval = enable_timerlat(trace);
11971206
if (retval) {
11981207
err_msg("Failed to enable timerlat tracer\n");
@@ -1320,7 +1329,7 @@ int timerlat_hist_main(int argc, char *argv[])
13201329
trace_instance_start(&record->trace);
13211330
if (!params->no_aa)
13221331
trace_instance_start(&aa->trace);
1323-
if (no_bpf) {
1332+
if (params->mode == TRACING_MODE_TRACEFS) {
13241333
trace_instance_start(trace);
13251334
} else {
13261335
retval = timerlat_bpf_attach();
@@ -1333,7 +1342,7 @@ int timerlat_hist_main(int argc, char *argv[])
13331342
tool->start_time = time(NULL);
13341343
timerlat_hist_set_signals(params);
13351344

1336-
if (no_bpf) {
1345+
if (params->mode == TRACING_MODE_TRACEFS) {
13371346
while (!stop_tracing) {
13381347
sleep(params->sleep_time);
13391348

@@ -1362,7 +1371,7 @@ int timerlat_hist_main(int argc, char *argv[])
13621371
} else
13631372
timerlat_bpf_wait(-1);
13641373

1365-
if (!no_bpf) {
1374+
if (params->mode != TRACING_MODE_TRACEFS) {
13661375
timerlat_bpf_detach();
13671376
retval = timerlat_hist_bpf_pull_data(tool);
13681377
if (retval) {
@@ -1409,10 +1418,10 @@ int timerlat_hist_main(int argc, char *argv[])
14091418
osnoise_destroy_tool(aa);
14101419
osnoise_destroy_tool(record);
14111420
osnoise_destroy_tool(tool);
1421+
if (params->mode != TRACING_MODE_TRACEFS)
1422+
timerlat_bpf_destroy();
14121423
free(params);
14131424
free_cpu_idle_disable_states();
1414-
if (!no_bpf)
1415-
timerlat_bpf_destroy();
14161425
out_exit:
14171426
exit(return_value);
14181427
}

tools/tracing/rtla/src/timerlat_top.c

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,9 @@ static struct timerlat_params
559559
/* display data in microseconds */
560560
params->output_divisor = 1000;
561561

562+
/* default to BPF mode */
563+
params->mode = TRACING_MODE_BPF;
564+
562565
while (1) {
563566
static struct option long_options[] = {
564567
{"auto", required_argument, 0, 'a'},
@@ -790,6 +793,13 @@ static struct timerlat_params
790793
if (params->kernel_workload && params->user_workload)
791794
timerlat_top_usage("--kernel-threads and --user-threads are mutually exclusive!");
792795

796+
/*
797+
* If auto-analysis or trace output is enabled, switch from BPF mode to
798+
* mixed mode
799+
*/
800+
if (params->mode == TRACING_MODE_BPF && params->trace_output && !params->no_aa)
801+
params->mode = TRACING_MODE_MIXED;
802+
793803
return params;
794804
}
795805

@@ -994,7 +1004,6 @@ int timerlat_top_main(int argc, char *argv[])
9941004
char *max_lat;
9951005
int retval;
9961006
int nr_cpus, i;
997-
bool no_bpf = false;
9981007

9991008
params = timerlat_top_parse_args(argc, argv);
10001009
if (!params)
@@ -1006,38 +1015,38 @@ int timerlat_top_main(int argc, char *argv[])
10061015
goto out_exit;
10071016
}
10081017

1009-
retval = timerlat_top_apply_config(top, params);
1010-
if (retval) {
1011-
err_msg("Could not apply config\n");
1012-
goto out_free;
1013-
}
1014-
10151018
trace = &top->trace;
10161019
/*
1017-
* Save trace instance into global variable so that SIGINT can stop
1018-
* the timerlat tracer.
1019-
* Otherwise, rtla could loop indefinitely when overloaded.
1020-
*/
1020+
* Save trace instance into global variable so that SIGINT can stop
1021+
* the timerlat tracer.
1022+
* Otherwise, rtla could loop indefinitely when overloaded.
1023+
*/
10211024
top_inst = trace;
10221025

1026+
/*
1027+
* Try to enable BPF, unless disabled explicitly.
1028+
* If BPF enablement fails, fall back to tracefs mode.
1029+
*/
10231030
if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
10241031
debug_msg("RTLA_NO_BPF set, disabling BPF\n");
1025-
no_bpf = true;
1026-
}
1027-
1028-
if (!no_bpf && !tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
1032+
params->mode = TRACING_MODE_TRACEFS;
1033+
} else if (!tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
10291034
debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
1030-
no_bpf = true;
1031-
}
1032-
1033-
if (!no_bpf) {
1035+
params->mode = TRACING_MODE_TRACEFS;
1036+
} else {
10341037
retval = timerlat_bpf_init(params);
10351038
if (retval) {
10361039
debug_msg("Could not enable BPF\n");
1037-
no_bpf = true;
1040+
params->mode = TRACING_MODE_TRACEFS;
10381041
}
10391042
}
10401043

1044+
retval = timerlat_top_apply_config(top, params);
1045+
if (retval) {
1046+
err_msg("Could not apply config\n");
1047+
goto out_free;
1048+
}
1049+
10411050
retval = enable_timerlat(trace);
10421051
if (retval) {
10431052
err_msg("Failed to enable timerlat tracer\n");
@@ -1166,7 +1175,7 @@ int timerlat_top_main(int argc, char *argv[])
11661175
trace_instance_start(&record->trace);
11671176
if (!params->no_aa)
11681177
trace_instance_start(&aa->trace);
1169-
if (no_bpf) {
1178+
if (params->mode == TRACING_MODE_TRACEFS) {
11701179
trace_instance_start(trace);
11711180
} else {
11721181
retval = timerlat_bpf_attach();
@@ -1179,15 +1188,15 @@ int timerlat_top_main(int argc, char *argv[])
11791188
top->start_time = time(NULL);
11801189
timerlat_top_set_signals(params);
11811190

1182-
if (no_bpf)
1191+
if (params->mode == TRACING_MODE_TRACEFS)
11831192
retval = timerlat_top_main_loop(top, record, params, &params_u);
11841193
else
11851194
retval = timerlat_top_bpf_main_loop(top, record, params, &params_u);
11861195

11871196
if (retval)
11881197
goto out_top;
11891198

1190-
if (!no_bpf)
1199+
if (params->mode != TRACING_MODE_TRACEFS)
11911200
timerlat_bpf_detach();
11921201

11931202
if (params->user_workload && !params_u.stopped_running) {
@@ -1239,6 +1248,8 @@ int timerlat_top_main(int argc, char *argv[])
12391248
osnoise_destroy_tool(aa);
12401249
osnoise_destroy_tool(record);
12411250
osnoise_destroy_tool(top);
1251+
if (params->mode != TRACING_MODE_TRACEFS)
1252+
timerlat_bpf_destroy();
12421253
free(params);
12431254
free_cpu_idle_disable_states();
12441255
out_exit:

0 commit comments

Comments
 (0)