Skip to content

Commit fd7925c

Browse files
lenticularis39rostedt
authored andcommitted
rtla/timerlat_hist: Use BPF to collect samples
Collect samples using BPF program instead of pulling them from tracefs. If the osnoise:timerlat_sample tracepoint is unavailable or the BPF program fails to load for whatever reason, rtla falls back to the old implementation. The collection of samples using the BPF program is fully self-contained and requires no activity of the userspace part of rtla during the measurement. Thus, instead of waking up every second to collect samples, rtla simply sleeps until woken up by a signal or threshold overflow. Cc: John Kacur <[email protected]> Cc: Luis Goncalves <[email protected]> Cc: Gabriele Monaco <[email protected]> Cc: Clark Williams <[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 e34293d commit fd7925c

File tree

1 file changed

+146
-21
lines changed

1 file changed

+146
-21
lines changed

tools/tracing/rtla/src/timerlat_hist.c

Lines changed: 146 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "timerlat.h"
1818
#include "timerlat_aa.h"
1919
#include "timerlat_u.h"
20+
#include "timerlat_bpf.h"
2021

2122
struct timerlat_hist_cpu {
2223
int *irq;
@@ -193,6 +194,89 @@ timerlat_hist_handler(struct trace_seq *s, struct tep_record *record,
193194
return 0;
194195
}
195196

197+
/*
198+
* timerlat_hist_bpf_pull_data - copy data from BPF maps into userspace
199+
*/
200+
static int timerlat_hist_bpf_pull_data(struct osnoise_tool *tool)
201+
{
202+
struct timerlat_hist_data *data = tool->data;
203+
int i, j, err;
204+
long long value_irq[data->nr_cpus],
205+
value_thread[data->nr_cpus],
206+
value_user[data->nr_cpus];
207+
208+
/* Pull histogram */
209+
for (i = 0; i < data->entries; i++) {
210+
err = timerlat_bpf_get_hist_value(i, value_irq, value_thread,
211+
value_user, data->nr_cpus);
212+
if (err)
213+
return err;
214+
for (j = 0; j < data->nr_cpus; j++) {
215+
data->hist[j].irq[i] = value_irq[j];
216+
data->hist[j].thread[i] = value_thread[j];
217+
data->hist[j].user[i] = value_user[j];
218+
}
219+
}
220+
221+
/* Pull summary */
222+
err = timerlat_bpf_get_summary_value(SUMMARY_COUNT,
223+
value_irq, value_thread, value_user,
224+
data->nr_cpus);
225+
if (err)
226+
return err;
227+
for (i = 0; i < data->nr_cpus; i++) {
228+
data->hist[i].irq_count = value_irq[i];
229+
data->hist[i].thread_count = value_thread[i];
230+
data->hist[i].user_count = value_user[i];
231+
}
232+
233+
err = timerlat_bpf_get_summary_value(SUMMARY_MIN,
234+
value_irq, value_thread, value_user,
235+
data->nr_cpus);
236+
if (err)
237+
return err;
238+
for (i = 0; i < data->nr_cpus; i++) {
239+
data->hist[i].min_irq = value_irq[i];
240+
data->hist[i].min_thread = value_thread[i];
241+
data->hist[i].min_user = value_user[i];
242+
}
243+
244+
err = timerlat_bpf_get_summary_value(SUMMARY_MAX,
245+
value_irq, value_thread, value_user,
246+
data->nr_cpus);
247+
if (err)
248+
return err;
249+
for (i = 0; i < data->nr_cpus; i++) {
250+
data->hist[i].max_irq = value_irq[i];
251+
data->hist[i].max_thread = value_thread[i];
252+
data->hist[i].max_user = value_user[i];
253+
}
254+
255+
err = timerlat_bpf_get_summary_value(SUMMARY_SUM,
256+
value_irq, value_thread, value_user,
257+
data->nr_cpus);
258+
if (err)
259+
return err;
260+
for (i = 0; i < data->nr_cpus; i++) {
261+
data->hist[i].sum_irq = value_irq[i];
262+
data->hist[i].sum_thread = value_thread[i];
263+
data->hist[i].sum_user = value_user[i];
264+
}
265+
266+
err = timerlat_bpf_get_summary_value(SUMMARY_OVERFLOW,
267+
value_irq, value_thread, value_user,
268+
data->nr_cpus);
269+
if (err)
270+
return err;
271+
for (i = 0; i < data->nr_cpus; i++) {
272+
data->hist[i].irq[data->entries] = value_irq[i];
273+
data->hist[i].thread[data->entries] = value_thread[i];
274+
data->hist[i].user[data->entries] = value_user[i];
275+
}
276+
277+
return 0;
278+
}
279+
196280
/*
197281
* timerlat_hist_header - print the header of the tracer to the output
198282
*/
@@ -1152,6 +1236,7 @@ int timerlat_hist_main(int argc, char *argv[])
11521236
pthread_t timerlat_u;
11531237
int retval;
11541238
int nr_cpus, i;
1239+
bool no_bpf = false;
11551240

11561241
params = timerlat_hist_parse_args(argc, argv);
11571242
if (!params)
@@ -1177,6 +1262,24 @@ int timerlat_hist_main(int argc, char *argv[])
11771262
*/
11781263
hist_inst = trace;
11791264

1265+
if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
1266+
debug_msg("RTLA_NO_BPF set, disabling BPF\n");
1267+
no_bpf = true;
1268+
}
1269+
1270+
if (!no_bpf && !tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
1271+
debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
1272+
no_bpf = true;
1273+
}
1274+
1275+
if (!no_bpf) {
1276+
retval = timerlat_bpf_init(params);
1277+
if (retval) {
1278+
debug_msg("Could not enable BPF\n");
1279+
no_bpf = true;
1280+
}
1281+
}
1282+
11801283
retval = enable_timerlat(trace);
11811284
if (retval) {
11821285
err_msg("Failed to enable timerlat tracer\n");
@@ -1304,35 +1407,55 @@ int timerlat_hist_main(int argc, char *argv[])
13041407
trace_instance_start(&record->trace);
13051408
if (!params->no_aa)
13061409
trace_instance_start(&aa->trace);
1307-
trace_instance_start(trace);
1410+
if (no_bpf) {
1411+
trace_instance_start(trace);
1412+
} else {
1413+
retval = timerlat_bpf_attach();
1414+
if (retval) {
1415+
err_msg("Error attaching BPF program\n");
1416+
goto out_hist;
1417+
}
1418+
}
13081419

13091420
tool->start_time = time(NULL);
13101421
timerlat_hist_set_signals(params);
13111422

1312-
while (!stop_tracing) {
1313-
sleep(params->sleep_time);
1314-
1315-
retval = tracefs_iterate_raw_events(trace->tep,
1316-
trace->inst,
1317-
NULL,
1318-
0,
1319-
collect_registered_events,
1320-
trace);
1321-
if (retval < 0) {
1322-
err_msg("Error iterating on events\n");
1323-
goto out_hist;
1324-
}
1325-
1326-
if (osnoise_trace_is_off(tool, record))
1327-
break;
1423+
if (no_bpf) {
1424+
while (!stop_tracing) {
1425+
sleep(params->sleep_time);
1426+
1427+
retval = tracefs_iterate_raw_events(trace->tep,
1428+
trace->inst,
1429+
NULL,
1430+
0,
1431+
collect_registered_events,
1432+
trace);
1433+
if (retval < 0) {
1434+
err_msg("Error iterating on events\n");
1435+
goto out_hist;
1436+
}
13281437

1329-
/* is there still any user-threads ? */
1330-
if (params->user_workload) {
1331-
if (params_u.stopped_running) {
1332-
debug_msg("timerlat user-space threads stopped!\n");
1438+
if (osnoise_trace_is_off(tool, record))
13331439
break;
1440+
1441+
/* is there still any user-threads ? */
1442+
if (params->user_workload) {
1443+
if (params_u.stopped_running) {
1444+
debug_msg("timerlat user-space threads stopped!\n");
1445+
break;
1446+
}
13341447
}
13351448
}
1449+
} else
1450+
timerlat_bpf_wait(-1);
1451+
1452+
if (!no_bpf) {
1453+
timerlat_bpf_detach();
1454+
retval = timerlat_hist_bpf_pull_data(tool);
1455+
if (retval) {
1456+
err_msg("Error pulling BPF data\n");
1457+
goto out_hist;
1458+
}
13361459
}
13371460

13381461
if (params->user_workload && !params_u.stopped_running) {
@@ -1376,6 +1499,8 @@ int timerlat_hist_main(int argc, char *argv[])
13761499
osnoise_destroy_tool(tool);
13771500
free(params);
13781501
free_cpu_idle_disable_states();
1502+
if (!no_bpf)
1503+
timerlat_bpf_destroy();
13791504
out_exit:
13801505
exit(return_value);
13811506
}

0 commit comments

Comments
 (0)