History

Merge tag 'trace-rtla-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull RTLA tracing tool updates from Steven Rostedt: "Real Time Analysis Tool updatesfor 5.18: - Support for adjusting tracing_threashold - Add -a (auto) option to make it easier for users to debug in the field - Add -e option to add more events to the trace - Add --trigger option to add triggers to events - Add --filter option to filter events - Add support to save histograms to the file - Add --dma-latency to set /dev/cpu_dma_latency - Other fixes and cleanups" * tag 'trace-rtla-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: rtla: Tools main loop cleanup rtla/timerlat: Add --dma-latency option rtla/osnoise: Fix osnoise hist stop tracing message rtla: Check for trace off also in the trace instance rtla/trace: Save event histogram output to a file rtla: Add --filter support rtla/trace: Add trace event filter helpers rtla: Add --trigger support rtla/trace: Add trace event trigger helpers rtla: Add -e/--event support rtla/trace: Add trace events helpers rtla/timerlat: Add the automatic trace option rtla/osnoise: Add the automatic trace option rtla/osnoise: Add an option to set the threshold rtla/osnoise: Add support to adjust the tracing_thresh

Linus Torvalds committed 4 years ago

Commit 20f463f2 parents 3ef4ea3 75016ca13 files · +903 −28Browse files

Unified · Split

13 files
  1. Documentation/tools/rtla/common_options.rst +19 −0
  2. Documentation/tools/rtla/common_osnoise_options.rst +10 −0
  3. Documentation/tools/rtla/common_timerlat_options.rst +12 −0
  4. tools/tracing/rtla/src/osnoise.c +83 −0
  5. tools/tracing/rtla/src/osnoise.h +8 −0
  6. tools/tracing/rtla/src/osnoise_hist.c +87 −8
  7. tools/tracing/rtla/src/osnoise_top.c +85 −6
  8. tools/tracing/rtla/src/timerlat_hist.c +100 −8
  9. tools/tracing/rtla/src/timerlat_top.c +97 −6
  10. tools/tracing/rtla/src/trace.c +345 −0
  11. tools/tracing/rtla/src/trace.h +23 −0
  12. tools/tracing/rtla/src/utils.c +33 −0
  13. tools/tracing/rtla/src/utils.h +1 −0
Documentation/tools/rtla/common_options.rst+19−0
@@ -14,6 +14,25 @@ · 13 unmodified lines
1414
1515 Save the stopped trace to [*file|osnoise_trace.txt*].
1616
17+**-e**, **--event** *sys:event*
18+
19+ Enable an event in the trace (**-t**) session. The argument can be a specific event, e.g., **-e** *sched:sched_switch*, or all events of a system group, e.g., **-e** *sched*. Multiple **-e** are allowed. It is only active when **-t** or **-a** are set.
20+
21+**--filter** *<filter>*
22+
23+ Filter the previous **-e** *sys:event* event with *<filter>*. For further information about event filtering see https://www.kernel.org/doc/html/latest/trace/events.html#event-filtering.
24+
25+**--trigger** *<trigger>*
26+ Enable a trace event trigger to the previous **-e** *sys:event*.
27+ If the *hist:* trigger is activated, the output histogram will be automatically saved to a file named *system_event_hist.txt*.
28+ For example, the command:
29+
30+ rtla <command> <mode> -t -e osnoise:irq_noise --trigger="hist:key=desc,duration/1000:sort=desc,duration/1000:vals=hitcount"
31+
32+ Will automatically save the content of the histogram associated to *osnoise:irq_noise* event in *osnoise_irq_noise_hist.txt*.
33+
34+ For further information about event trigger see https://www.kernel.org/doc/html/latest/trace/events.html#event-triggers.
35+
1736 **-P**, **--priority** *o:prio|r:prio|f:prio|d:runtime:period*
1837
1938 Set scheduling parameters to the osnoise tracer threads, the format to set the priority are:
Documentation/tools/rtla/common_osnoise_options.rst+10−0
@@ -1,3 +1,8 @@
1+**-a**, **--auto** *us*
2+
3+ Set the automatic trace mode. This mode sets some commonly used options
4+ while debugging the system. It is equivalent to use **-s** *us* **-T 1 -t**.
5+
16 **-p**, **--period** *us*
27
38 Set the *osnoise* tracer period in microseconds.
@@ -15,3 +20,8 @@ · 11 unmodified lines
1520
1621 Stop the trace if the total sample is higher than the argument in microseconds.
1722 If **-T** is set, it will also save the trace to the output.
23+
24+**-T**, **--threshold** *us*
25+
26+ Specify the minimum delta between two time reads to be considered noise.
27+ The default threshold is *5 us*.
Documentation/tools/rtla/common_timerlat_options.rst+12−0
@@ -1,3 +1,10 @@
1+**-a**, **--auto** *us*
2+
3+ Set the automatic trace mode. This mode sets some commonly used options
4+ while debugging the system. It is equivalent to use **-T** *us* **-s** *us*
5+ **-t**. By default, *timerlat* tracer uses FIFO:95 for *timerlat* threads,
6+ thus equilavent to **-P** *f:95*.
7+
18 **-p**, **--period** *us*
29
310 Set the *timerlat* tracer period in microseconds.
@@ -14,3 +21,8 @@ · 10 unmodified lines
1421
1522 Save the stack trace at the *IRQ* if a *Thread* latency is higher than the
1623 argument in us.
24+
25+**--dma-latency** *us*
26+ Set the /dev/cpu_dma_latency to *us*, aiming to bound exit from idle latencies.
27+ *cyclictest* sets this value to *0* by default, use **--dma-latency** *0* to have
28+ similar results.
tools/tracing/rtla/src/osnoise.c+83−0
@@ -655,6 +655,85 @@ void osnoise_put_print_stack(struct osnoise_context *context) · 654 unmodified lines
655655 context->orig_print_stack = OSNOISE_OPTION_INIT_VAL;
656656 }
657657
658+/*
659+ * osnoise_get_tracing_thresh - read and save the original "tracing_thresh"
660+ */
661+static long long
662+osnoise_get_tracing_thresh(struct osnoise_context *context)
663+{
664+ long long tracing_thresh;
665+
666+ if (context->tracing_thresh != OSNOISE_OPTION_INIT_VAL)
667+ return context->tracing_thresh;
668+
669+ if (context->orig_tracing_thresh != OSNOISE_OPTION_INIT_VAL)
670+ return context->orig_tracing_thresh;
671+
672+ tracing_thresh = osnoise_read_ll_config("tracing_thresh");
673+ if (tracing_thresh < 0)
674+ goto out_err;
675+
676+ context->orig_tracing_thresh = tracing_thresh;
677+ return tracing_thresh;
678+
679+out_err:
680+ return OSNOISE_OPTION_INIT_VAL;
681+}
682+
683+/*
684+ * osnoise_set_tracing_thresh - set "tracing_thresh"
685+ */
686+int osnoise_set_tracing_thresh(struct osnoise_context *context, long long tracing_thresh)
687+{
688+ long long curr_tracing_thresh = osnoise_get_tracing_thresh(context);
689+ int retval;
690+
691+ if (curr_tracing_thresh == OSNOISE_OPTION_INIT_VAL)
692+ return -1;
693+
694+ retval = osnoise_write_ll_config("tracing_thresh", tracing_thresh);
695+ if (retval < 0)
696+ return -1;
697+
698+ context->tracing_thresh = tracing_thresh;
699+
700+ return 0;
701+}
702+
703+/*
704+ * osnoise_restore_tracing_thresh - restore the original "tracing_thresh"
705+ */
706+void osnoise_restore_tracing_thresh(struct osnoise_context *context)
707+{
708+ int retval;
709+
710+ if (context->orig_tracing_thresh == OSNOISE_OPTION_INIT_VAL)
711+ return;
712+
713+ if (context->orig_tracing_thresh == context->tracing_thresh)
714+ goto out_done;
715+
716+ retval = osnoise_write_ll_config("tracing_thresh", context->orig_tracing_thresh);
717+ if (retval < 0)
718+ err_msg("Could not restore original tracing_thresh\n");
719+
720+out_done:
721+ context->tracing_thresh = OSNOISE_OPTION_INIT_VAL;
722+}
723+
724+/*
725+ * osnoise_put_tracing_thresh - restore original values and cleanup data
726+ */
727+void osnoise_put_tracing_thresh(struct osnoise_context *context)
728+{
729+ osnoise_restore_tracing_thresh(context);
730+
731+ if (context->orig_tracing_thresh == OSNOISE_OPTION_INIT_VAL)
732+ return;
733+
734+ context->orig_tracing_thresh = OSNOISE_OPTION_INIT_VAL;
735+}
736+
658737 /*
659738 * enable_osnoise - enable osnoise tracer in the trace_instance
660739 */
@@ -716,6 +795,9 @@ struct osnoise_context *osnoise_context_alloc(void) · 55 unmodified lines
716795 context->orig_print_stack = OSNOISE_OPTION_INIT_VAL;
717796 context->print_stack = OSNOISE_OPTION_INIT_VAL;
718797
798+ context->orig_tracing_thresh = OSNOISE_OPTION_INIT_VAL;
799+ context->tracing_thresh = OSNOISE_OPTION_INIT_VAL;
800+
719801 osnoise_get_context(context);
720802
721803 return context;
@@ -741,6 +823,7 @@ void osnoise_put_context(struct osnoise_context *context) · 19 unmodified lines
741823 osnoise_put_stop_total_us(context);
742824 osnoise_put_timerlat_period_us(context);
743825 osnoise_put_print_stack(context);
826+ osnoise_put_tracing_thresh(context);
744827
745828 free(context);
746829 }
tools/tracing/rtla/src/osnoise.h+8−0
@@ -23,6 +23,10 @@ struct osnoise_context { · 22 unmodified lines
2323 long long orig_timerlat_period_us;
2424 long long timerlat_period_us;
2525
26+ /* 0 as init value */
27+ long long orig_tracing_thresh;
28+ long long tracing_thresh;
29+
2630 /* -1 as init value because 0 is disabled */
2731 long long orig_stop_us;
2832 long long stop_us;
@@ -67,6 +71,10 @@ int osnoise_set_timerlat_period_us(struct osnoise_context *context, · 38 unmodified lines
6771 long long timerlat_period_us);
6872 void osnoise_restore_timerlat_period_us(struct osnoise_context *context);
6973
74+int osnoise_set_tracing_thresh(struct osnoise_context *context,
75+ long long tracing_thresh);
76+void osnoise_restore_tracing_thresh(struct osnoise_context *context);
77+
7078 void osnoise_restore_print_stack(struct osnoise_context *context);
7179 int osnoise_set_print_stack(struct osnoise_context *context,
7280 long long print_stack);
tools/tracing/rtla/src/osnoise_hist.c+87−8
@@ -21,6 +21,7 @@ struct osnoise_hist_params { · 20 unmodified lines
2121 char *trace_output;
2222 unsigned long long runtime;
2323 unsigned long long period;
24+ long long threshold;
2425 long long stop_us;
2526 long long stop_total_us;
2627 int sleep_time;
@@ -28,6 +29,7 @@ struct osnoise_hist_params { · 1 unmodified line
2829 int set_sched;
2930 int output_divisor;
3031 struct sched_attr sched_param;
32+ struct trace_events *events;
3133
3234 char no_header;
3335 char no_summary;
@@ -425,19 +427,25 @@ static void osnoise_hist_usage(char *usage) · 391 unmodified lines
425427
426428 static const char * const msg[] = {
427429 "",
428− " usage: rtla osnoise hist [-h] [-D] [-d s] [-p us] [-r us] [-s us] [-S us] [-t[=file]] \\",
429− " [-c cpu-list] [-P priority] [-b N] [-E N] [--no-header] [--no-summary] \\",
430− " [--no-index] [--with-zeros]",
430+ " usage: rtla osnoise hist [-h] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\",
431+ " [-T us] [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\",
432+ " [-c cpu-list] [-P priority] [-b N] [-E N] [--no-header] [--no-summary] [--no-index] \\",
433+ " [--with-zeros]",
431434 "",
432435 " -h/--help: print this menu",
436+ " -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit",
433437 " -p/--period us: osnoise period in us",
434438 " -r/--runtime us: osnoise runtime in us",
435439 " -s/--stop us: stop trace if a single sample is higher than the argument in us",
436440 " -S/--stop-total us: stop trace if the total sample is higher than the argument in us",
441+ " -T/--threshold us: the minimum delta to be considered a noise",
437442 " -c/--cpus cpu-list: list of cpus to run osnoise threads",
438443 " -d/--duration time[s|m|h|d]: duration of the session",
439444 " -D/--debug: print debug info",
440445 " -t/--trace[=file]: save the stopped trace to [file|osnoise_trace.txt]",
446+ " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed",
447+ " --filter <filter>: enable a trace event filter to the previous -e event",
448+ " --trigger <trigger>: enable a trace event trigger to the previous -e event",
441449 " -b/--bucket-size N: set the histogram bucket size (default 1)",
442450 " -E/--entries N: set the number of entries of the histogram (default 256)",
443451 " --no-header: do not print header",
@@ -471,6 +479,7 @@ static struct osnoise_hist_params · 27 unmodified lines
471479 *osnoise_hist_parse_args(int argc, char *argv[])
472480 {
473481 struct osnoise_hist_params *params;
482+ struct trace_events *tevent;
474483 int retval;
475484 int c;
476485
@@ -485,6 +494,7 @@ static struct osnoise_hist_params · 8 unmodified lines
485494
486495 while (1) {
487496 static struct option long_options[] = {
497+ {"auto", required_argument, 0, 'a'},
488498 {"bucket-size", required_argument, 0, 'b'},
489499 {"entries", required_argument, 0, 'E'},
490500 {"cpus", required_argument, 0, 'c'},
@@ -497,17 +507,21 @@ static struct osnoise_hist_params · 6 unmodified lines
497507 {"stop", required_argument, 0, 's'},
498508 {"stop-total", required_argument, 0, 'S'},
499509 {"trace", optional_argument, 0, 't'},
510+ {"event", required_argument, 0, 'e'},
511+ {"threshold", required_argument, 0, 'T'},
500512 {"no-header", no_argument, 0, '0'},
501513 {"no-summary", no_argument, 0, '1'},
502514 {"no-index", no_argument, 0, '2'},
503515 {"with-zeros", no_argument, 0, '3'},
516+ {"trigger", required_argument, 0, '4'},
517+ {"filter", required_argument, 0, '5'},
504518 {0, 0, 0, 0}
505519 };
506520
507521 /* getopt_long stores the option index here. */
508522 int option_index = 0;
509523
510− c = getopt_long(argc, argv, "c:b:d:E:Dhp:P:r:s:S:t::0123",
524+ c = getopt_long(argc, argv, "a:c:b:d:e:E:Dhp:P:r:s:S:t::T:01234:5:",
511525 long_options, &option_index);
512526
513527 /* detect the end of the options. */
@@ -515,6 +529,17 @@ static struct osnoise_hist_params · 1 unmodified line
515529 break;
516530
517531 switch (c) {
532+ case 'a':
533+ /* set sample stop to auto_thresh */
534+ params->stop_us = get_llong_from_str(optarg);
535+
536+ /* set sample threshold to 1 */
537+ params->threshold = 1;
538+
539+ /* set trace */
540+ params->trace_output = "osnoise_trace.txt";
541+
542+ break;
518543 case 'b':
519544 params->bucket_size = get_llong_from_str(optarg);
520545 if ((params->bucket_size == 0) || (params->bucket_size >= 1000000))
@@ -534,6 +559,18 @@ static struct osnoise_hist_params · 13 unmodified lines
534559 if (!params->duration)
535560 osnoise_hist_usage("Invalid -D duration\n");
536561 break;
562+ case 'e':
563+ tevent = trace_event_alloc(optarg);
564+ if (!tevent) {
565+ err_msg("Error alloc trace event");
566+ exit(EXIT_FAILURE);
567+ }
568+
569+ if (params->events)
570+ tevent->next = params->events;
571+
572+ params->events = tevent;
573+ break;
537574 case 'E':
538575 params->entries = get_llong_from_str(optarg);
539576 if ((params->entries < 10) || (params->entries > 9999999))
@@ -565,6 +602,9 @@ static struct osnoise_hist_params · 25 unmodified lines
565602 case 'S':
566603 params->stop_total_us = get_llong_from_str(optarg);
567604 break;
605+ case 'T':
606+ params->threshold = get_llong_from_str(optarg);
607+ break;
568608 case 't':
569609 if (optarg)
570610 /* skip = */
@@ -584,6 +624,28 @@ static struct osnoise_hist_params · 13 unmodified lines
584624 case '3': /* with zeros */
585625 params->with_zeros = 1;
586626 break;
627+ case '4': /* trigger */
628+ if (params->events) {
629+ retval = trace_event_add_trigger(params->events, optarg);
630+ if (retval) {
631+ err_msg("Error adding trigger %s\n", optarg);
632+ exit(EXIT_FAILURE);
633+ }
634+ } else {
635+ osnoise_hist_usage("--trigger requires a previous -e\n");
636+ }
637+ break;
638+ case '5': /* filter */
639+ if (params->events) {
640+ retval = trace_event_add_filter(params->events, optarg);
641+ if (retval) {
642+ err_msg("Error adding filter %s\n", optarg);
643+ exit(EXIT_FAILURE);
644+ }
645+ } else {
646+ osnoise_hist_usage("--filter requires a previous -e\n");
647+ }
648+ break;
587649 default:
588650 osnoise_hist_usage("Invalid option");
589651 }
@@ -645,6 +707,14 @@ osnoise_hist_apply_config(struct osnoise_tool *tool, struct osnoise_hist_params · 55 unmodified lines
645707 }
646708 }
647709
710+ if (params->threshold) {
711+ retval = osnoise_set_tracing_thresh(tool->context, params->threshold);
712+ if (retval) {
713+ err_msg("Failed to set tracing_thresh\n");
714+ goto out_err;
715+ }
716+ }
717+
648718 return 0;
649719
650720 out_err:
@@ -751,6 +821,13 @@ int osnoise_hist_main(int argc, char *argv[]) · 100 unmodified lines
751821 err_msg("Failed to enable the trace instance\n");
752822 goto out_hist;
753823 }
824+
825+ if (params->events) {
826+ retval = trace_events_enable(&record->trace, params->events);
827+ if (retval)
828+ goto out_hist;
829+ }
830+
754831 trace_instance_start(&record->trace);
755832 }
756833
@@ -771,9 +848,9 @@ int osnoise_hist_main(int argc, char *argv[]) · 14 unmodified lines
771848 goto out_hist;
772849 }
773850
774− if (!tracefs_trace_is_on(trace->inst))
851+ if (trace_is_off(&tool->trace, &record->trace))
775852 break;
776− };
853+ }
777854
778855 osnoise_read_trace_hist(tool);
779856
@@ -781,8 +858,8 @@ int osnoise_hist_main(int argc, char *argv[]) · 1 unmodified line
781858
782859 return_value = 0;
783860
784− if (!tracefs_trace_is_on(trace->inst)) {
785− printf("rtla timelat hit stop tracing\n");
861+ if (trace_is_off(&tool->trace, &record->trace)) {
862+ printf("rtla osnoise hit stop tracing\n");
786863 if (params->trace_output) {
787864 printf(" Saving trace to %s\n", params->trace_output);
788865 save_trace_to_file(record->trace.inst, params->trace_output);
@@ -790,6 +867,8 @@ int osnoise_hist_main(int argc, char *argv[]) · 1 unmodified line
790867 }
791868
792869 out_hist:
870+ trace_events_destroy(&record->trace, params->events);
871+ params->events = NULL;
793872 osnoise_free_histogram(tool->data);
794873 out_destroy:
795874 osnoise_destroy_tool(record);
tools/tracing/rtla/src/osnoise_top.c+85−6
@@ -23,6 +23,7 @@ struct osnoise_top_params { · 22 unmodified lines
2323 char *trace_output;
2424 unsigned long long runtime;
2525 unsigned long long period;
26+ long long threshold;
2627 long long stop_us;
2728 long long stop_total_us;
2829 int sleep_time;
@@ -30,6 +31,7 @@ struct osnoise_top_params { · 1 unmodified line
3031 int quiet;
3132 int set_sched;
3233 struct sched_attr sched_param;
34+ struct trace_events *events;
3335 };
3436
3537 struct osnoise_top_cpu {
@@ -244,18 +246,24 @@ void osnoise_top_usage(char *usage) · 208 unmodified lines
244246 int i;
245247
246248 static const char * const msg[] = {
247− " usage: rtla osnoise [top] [-h] [-q] [-D] [-d s] [-p us] [-r us] [-s us] [-S us] [-t[=file]] \\",
249+ " usage: rtla osnoise [top] [-h] [-q] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\",
250+ " [-T us] [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\",
248251 " [-c cpu-list] [-P priority]",
249252 "",
250253 " -h/--help: print this menu",
254+ " -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit",
251255 " -p/--period us: osnoise period in us",
252256 " -r/--runtime us: osnoise runtime in us",
253257 " -s/--stop us: stop trace if a single sample is higher than the argument in us",
254258 " -S/--stop-total us: stop trace if the total sample is higher than the argument in us",
259+ " -T/--threshold us: the minimum delta to be considered a noise",
255260 " -c/--cpus cpu-list: list of cpus to run osnoise threads",
256261 " -d/--duration time[s|m|h|d]: duration of the session",
257262 " -D/--debug: print debug info",
258263 " -t/--trace[=file]: save the stopped trace to [file|osnoise_trace.txt]",
264+ " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed",
265+ " --filter <filter>: enable a trace event filter to the previous -e event",
266+ " --trigger <trigger>: enable a trace event trigger to the previous -e event",
259267 " -q/--quiet print only a summary at the end",
260268 " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters",
261269 " o:prio - use SCHED_OTHER with prio",
@@ -283,6 +291,7 @@ void osnoise_top_usage(char *usage) · 21 unmodified lines
283291 struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
284292 {
285293 struct osnoise_top_params *params;
294+ struct trace_events *tevent;
286295 int retval;
287296 int c;
288297
@@ -292,9 +301,11 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) · 3 unmodified lines
292301
293302 while (1) {
294303 static struct option long_options[] = {
304+ {"auto", required_argument, 0, 'a'},
295305 {"cpus", required_argument, 0, 'c'},
296306 {"debug", no_argument, 0, 'D'},
297307 {"duration", required_argument, 0, 'd'},
308+ {"event", required_argument, 0, 'e'},
298309 {"help", no_argument, 0, 'h'},
299310 {"period", required_argument, 0, 'p'},
300311 {"priority", required_argument, 0, 'P'},
@@ -302,14 +313,17 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) · 1 unmodified line
302313 {"runtime", required_argument, 0, 'r'},
303314 {"stop", required_argument, 0, 's'},
304315 {"stop-total", required_argument, 0, 'S'},
316+ {"threshold", required_argument, 0, 'T'},
305317 {"trace", optional_argument, 0, 't'},
318+ {"trigger", required_argument, 0, '0'},
319+ {"filter", required_argument, 0, '1'},
306320 {0, 0, 0, 0}
307321 };
308322
309323 /* getopt_long stores the option index here. */
310324 int option_index = 0;
311325
312− c = getopt_long(argc, argv, "c:d:Dhp:P:qr:s:S:t::",
326+ c = getopt_long(argc, argv, "a:c:d:De:hp:P:qr:s:S:t::T:0:1:",
313327 long_options, &option_index);
314328
315329 /* Detect the end of the options. */
@@ -317,6 +331,17 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) · 1 unmodified line
317331 break;
318332
319333 switch (c) {
334+ case 'a':
335+ /* set sample stop to auto_thresh */
336+ params->stop_us = get_llong_from_str(optarg);
337+
338+ /* set sample threshold to 1 */
339+ params->threshold = 1;
340+
341+ /* set trace */
342+ params->trace_output = "osnoise_trace.txt";
343+
344+ break;
320345 case 'c':
321346 retval = parse_cpu_list(optarg, &params->monitored_cpus);
322347 if (retval)
@@ -331,6 +356,18 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) · 8 unmodified lines
331356 if (!params->duration)
332357 osnoise_top_usage("Invalid -D duration\n");
333358 break;
359+ case 'e':
360+ tevent = trace_event_alloc(optarg);
361+ if (!tevent) {
362+ err_msg("Error alloc trace event");
363+ exit(EXIT_FAILURE);
364+ }
365+
366+ if (params->events)
367+ tevent->next = params->events;
368+ params->events = tevent;
369+
370+ break;
334371 case 'h':
335372 case '?':
336373 osnoise_top_usage(NULL);
@@ -367,6 +404,31 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) · 30 unmodified lines
367404 else
368405 params->trace_output = "osnoise_trace.txt";
369406 break;
407+ case 'T':
408+ params->threshold = get_llong_from_str(optarg);
409+ break;
410+ case '0': /* trigger */
411+ if (params->events) {
412+ retval = trace_event_add_trigger(params->events, optarg);
413+ if (retval) {
414+ err_msg("Error adding trigger %s\n", optarg);
415+ exit(EXIT_FAILURE);
416+ }
417+ } else {
418+ osnoise_top_usage("--trigger requires a previous -e\n");
419+ }
420+ break;
421+ case '1': /* filter */
422+ if (params->events) {
423+ retval = trace_event_add_filter(params->events, optarg);
424+ if (retval) {
425+ err_msg("Error adding filter %s\n", optarg);
426+ exit(EXIT_FAILURE);
427+ }
428+ } else {
429+ osnoise_top_usage("--filter requires a previous -e\n");
430+ }
431+ break;
370432 default:
371433 osnoise_top_usage("Invalid option");
372434 }
@@ -425,6 +487,14 @@ osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_top_params *p · 52 unmodified lines
425487 }
426488 }
427489
490+ if (params->threshold) {
491+ retval = osnoise_set_tracing_thresh(tool->context, params->threshold);
492+ if (retval) {
493+ err_msg("Failed to set tracing_thresh\n");
494+ goto out_err;
495+ }
496+ }
497+
428498 return 0;
429499
430500 out_err:
@@ -529,13 +599,20 @@ int osnoise_top_main(int argc, char **argv) · 98 unmodified lines
529599 err_msg("Failed to enable the trace instance\n");
530600 goto out_top;
531601 }
602+
603+ if (params->events) {
604+ retval = trace_events_enable(&record->trace, params->events);
605+ if (retval)
606+ goto out_top;
607+ }
608+
532609 trace_instance_start(&record->trace);
533610 }
534611
535612 tool->start_time = time(NULL);
536613 osnoise_top_set_signals(params);
537614
538− do {
615+ while (!stop_tracing) {
539616 sleep(params->sleep_time);
540617
541618 retval = tracefs_iterate_raw_events(trace->tep,
@@ -552,16 +629,16 @@ int osnoise_top_main(int argc, char **argv) · 10 unmodified lines
552629 if (!params->quiet)
553630 osnoise_print_stats(params, tool);
554631
555− if (!tracefs_trace_is_on(trace->inst))
632+ if (trace_is_off(&tool->trace, &record->trace))
556633 break;
557634
558− } while (!stop_tracing);
635+ }
559636
560637 osnoise_print_stats(params, tool);
561638
562639 return_value = 0;
563640
564− if (!tracefs_trace_is_on(trace->inst)) {
641+ if (trace_is_off(&tool->trace, &record->trace)) {
565642 printf("osnoise hit stop tracing\n");
566643 if (params->trace_output) {
567644 printf(" Saving trace to %s\n", params->trace_output);
@@ -570,6 +647,8 @@ int osnoise_top_main(int argc, char **argv) · 2 unmodified lines
570647 }
571648
572649 out_top:
650+ trace_events_destroy(&record->trace, params->events);
651+ params->events = NULL;
573652 osnoise_free_top(tool->data);
574653 osnoise_destroy_tool(record);
575654 osnoise_destroy_tool(tool);
tools/tracing/rtla/src/timerlat_hist.c+100−8
@@ -28,7 +28,9 @@ struct timerlat_hist_params { · 27 unmodified lines
2828 int output_divisor;
2929 int duration;
3030 int set_sched;
31+ int dma_latency;
3132 struct sched_attr sched_param;
33+ struct trace_events *events;
3234
3335 char no_irq;
3436 char no_thread;
@@ -428,11 +430,13 @@ static void timerlat_hist_usage(char *usage) · 393 unmodified lines
428430
429431 char *msg[] = {
430432 "",
431− " usage: [rtla] timerlat hist [-h] [-q] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] [-t[=file]] \\",
432− " [-c cpu-list] [-P priority] [-E N] [-b N] [--no-irq] [--no-thread] [--no-header] [--no-summary] \\",
433− " [--no-index] [--with-zeros]",
433+ " usage: [rtla] timerlat hist [-h] [-q] [-d s] [-D] [-n] [-a us] [-p us] [-i us] [-T us] [-s us] \\",
434+ " [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] \\",
435+ " [-P priority] [-E N] [-b N] [--no-irq] [--no-thread] [--no-header] [--no-summary] \\",
436+ " [--no-index] [--with-zeros] [--dma-latency us]",
434437 "",
435438 " -h/--help: print this menu",
439+ " -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
436440 " -p/--period us: timerlat period in us",
437441 " -i/--irq us: stop trace if the irq latency is higher than the argument in us",
438442 " -T/--thread us: stop trace if the thread latency is higher than the argument in us",
@@ -440,7 +444,10 @@ static void timerlat_hist_usage(char *usage) · 1 unmodified line
440444 " -c/--cpus cpus: run the tracer only on the given cpus",
441445 " -d/--duration time[m|h|d]: duration of the session in seconds",
442446 " -D/--debug: print debug info",
443− " -T/--trace[=file]: save the stopped trace to [file|timerlat_trace.txt]",
447+ " -t/--trace[=file]: save the stopped trace to [file|timerlat_trace.txt]",
448+ " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed",
449+ " --filter <filter>: enable a trace event filter to the previous -e event",
450+ " --trigger <trigger>: enable a trace event trigger to the previous -e event",
444451 " -n/--nano: display data in nanoseconds",
445452 " -b/--bucket-size N: set the histogram bucket size (default 1)",
446453 " -E/--entries N: set the number of entries of the histogram (default 256)",
@@ -450,6 +457,7 @@ static void timerlat_hist_usage(char *usage) · 3 unmodified lines
450457 " --no-summary: do not print summary",
451458 " --no-index: do not print index",
452459 " --with-zeros: print zero only entries",
460+ " --dma-latency us: set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency",
453461 " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters",
454462 " o:prio - use SCHED_OTHER with prio",
455463 " r:prio - use SCHED_RR with prio",
@@ -477,6 +485,8 @@ static struct timerlat_hist_params · 21 unmodified lines
477485 *timerlat_hist_parse_args(int argc, char *argv[])
478486 {
479487 struct timerlat_hist_params *params;
488+ struct trace_events *tevent;
489+ int auto_thresh;
480490 int retval;
481491 int c;
482492
@@ -484,6 +494,9 @@ static struct timerlat_hist_params · 1 unmodified line
484494 if (!params)
485495 exit(1);
486496
497+ /* disabled by default */
498+ params->dma_latency = -1;
499+
487500 /* display data in microseconds */
488501 params->output_divisor = 1000;
489502 params->bucket_size = 1;
@@ -491,6 +504,7 @@ static struct timerlat_hist_params · 1 unmodified line
491504
492505 while (1) {
493506 static struct option long_options[] = {
507+ {"auto", required_argument, 0, 'a'},
494508 {"cpus", required_argument, 0, 'c'},
495509 {"bucket-size", required_argument, 0, 'b'},
496510 {"debug", no_argument, 0, 'D'},
@@ -504,19 +518,23 @@ static struct timerlat_hist_params · 7 unmodified lines
504518 {"stack", required_argument, 0, 's'},
505519 {"thread", required_argument, 0, 'T'},
506520 {"trace", optional_argument, 0, 't'},
521+ {"event", required_argument, 0, 'e'},
507522 {"no-irq", no_argument, 0, '0'},
508523 {"no-thread", no_argument, 0, '1'},
509524 {"no-header", no_argument, 0, '2'},
510525 {"no-summary", no_argument, 0, '3'},
511526 {"no-index", no_argument, 0, '4'},
512527 {"with-zeros", no_argument, 0, '5'},
528+ {"trigger", required_argument, 0, '6'},
529+ {"filter", required_argument, 0, '7'},
530+ {"dma-latency", required_argument, 0, '8'},
513531 {0, 0, 0, 0}
514532 };
515533
516534 /* getopt_long stores the option index here. */
517535 int option_index = 0;
518536
519− c = getopt_long(argc, argv, "c:b:d:E:Dhi:np:P:s:t::T:012345",
537+ c = getopt_long(argc, argv, "a:c:b:d:e:E:Dhi:np:P:s:t::T:0123456:7:8:",
520538 long_options, &option_index);
521539
522540 /* detect the end of the options. */
@@ -524,6 +542,19 @@ static struct timerlat_hist_params · 1 unmodified line
524542 break;
525543
526544 switch (c) {
545+ case 'a':
546+ auto_thresh = get_llong_from_str(optarg);
547+
548+ /* set thread stop to auto_thresh */
549+ params->stop_total_us = auto_thresh;
550+
551+ /* get stack trace */
552+ params->print_stack = auto_thresh;
553+
554+ /* set trace */
555+ params->trace_output = "timerlat_trace.txt";
556+
557+ break;
527558 case 'c':
528559 retval = parse_cpu_list(optarg, &params->monitored_cpus);
529560 if (retval)
@@ -543,6 +574,18 @@ static struct timerlat_hist_params · 13 unmodified lines
543574 if (!params->duration)
544575 timerlat_hist_usage("Invalid -D duration\n");
545576 break;
577+ case 'e':
578+ tevent = trace_event_alloc(optarg);
579+ if (!tevent) {
580+ err_msg("Error alloc trace event");
581+ exit(EXIT_FAILURE);
582+ }
583+
584+ if (params->events)
585+ tevent->next = params->events;
586+
587+ params->events = tevent;
588+ break;
546589 case 'E':
547590 params->entries = get_llong_from_str(optarg);
548591 if ((params->entries < 10) || (params->entries > 9999999))
@@ -600,6 +643,35 @@ static struct timerlat_hist_params · 51 unmodified lines
600643 case '5': /* with zeros */
601644 params->with_zeros = 1;
602645 break;
646+ case '6': /* trigger */
647+ if (params->events) {
648+ retval = trace_event_add_trigger(params->events, optarg);
649+ if (retval) {
650+ err_msg("Error adding trigger %s\n", optarg);
651+ exit(EXIT_FAILURE);
652+ }
653+ } else {
654+ timerlat_hist_usage("--trigger requires a previous -e\n");
655+ }
656+ break;
657+ case '7': /* filter */
658+ if (params->events) {
659+ retval = trace_event_add_filter(params->events, optarg);
660+ if (retval) {
661+ err_msg("Error adding filter %s\n", optarg);
662+ exit(EXIT_FAILURE);
663+ }
664+ } else {
665+ timerlat_hist_usage("--filter requires a previous -e\n");
666+ }
667+ break;
668+ case '8':
669+ params->dma_latency = get_llong_from_str(optarg);
670+ if (params->dma_latency < 0 || params->dma_latency > 10000) {
671+ err_msg("--dma-latency needs to be >= 0 and < 10000");
672+ exit(EXIT_FAILURE);
673+ }
674+ break;
603675 default:
604676 timerlat_hist_usage("Invalid option");
605677 }
@@ -732,6 +804,7 @@ int timerlat_hist_main(int argc, char *argv[]) · 126 unmodified lines
732804 struct osnoise_tool *record = NULL;
733805 struct osnoise_tool *tool = NULL;
734806 struct trace_instance *trace;
807+ int dma_latency_fd = -1;
735808 int return_value = 1;
736809 int retval;
737810
@@ -767,6 +840,14 @@ int timerlat_hist_main(int argc, char *argv[]) · 29 unmodified lines
767840 }
768841 }
769842
843+ if (params->dma_latency >= 0) {
844+ dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
845+ if (dma_latency_fd < 0) {
846+ err_msg("Could not set /dev/cpu_dma_latency.\n");
847+ goto out_hist;
848+ }
849+ }
850+
770851 trace_instance_start(trace);
771852
772853 if (params->trace_output) {
@@ -775,6 +856,13 @@ int timerlat_hist_main(int argc, char *argv[]) · 2 unmodified lines
775856 err_msg("Failed to enable the trace instance\n");
776857 goto out_hist;
777858 }
859+
860+ if (params->events) {
861+ retval = trace_events_enable(&record->trace, params->events);
862+ if (retval)
863+ goto out_hist;
864+ }
865+
778866 trace_instance_start(&record->trace);
779867 }
780868
@@ -795,15 +883,15 @@ int timerlat_hist_main(int argc, char *argv[]) · 14 unmodified lines
795883 goto out_hist;
796884 }
797885
798− if (!tracefs_trace_is_on(trace->inst))
886+ if (trace_is_off(&tool->trace, &record->trace))
799887 break;
800− };
888+ }
801889
802890 timerlat_print_stats(params, tool);
803891
804892 return_value = 0;
805893
806− if (!tracefs_trace_is_on(trace->inst)) {
894+ if (trace_is_off(&tool->trace, &record->trace)) {
807895 printf("rtla timelat hit stop tracing\n");
808896 if (params->trace_output) {
809897 printf(" Saving trace to %s\n", params->trace_output);
@@ -812,6 +900,10 @@ int timerlat_hist_main(int argc, char *argv[]) · 2 unmodified lines
812900 }
813901
814902 out_hist:
903+ if (dma_latency_fd >= 0)
904+ close(dma_latency_fd);
905+ trace_events_destroy(&record->trace, params->events);
906+ params->events = NULL;
815907 timerlat_free_histogram(tool->data);
816908 osnoise_destroy_tool(record);
817909 osnoise_destroy_tool(tool);
tools/tracing/rtla/src/timerlat_top.c+97−6
@@ -29,7 +29,9 @@ struct timerlat_top_params { · 28 unmodified lines
2929 int duration;
3030 int quiet;
3131 int set_sched;
32+ int dma_latency;
3233 struct sched_attr sched_param;
34+ struct trace_events *events;
3335 };
3436
3537 struct timerlat_top_cpu {
@@ -266,10 +268,12 @@ static void timerlat_top_usage(char *usage) · 230 unmodified lines
266268
267269 static const char *const msg[] = {
268270 "",
269− " usage: rtla timerlat [top] [-h] [-q] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] [-t[=file]] \\",
270− " [-c cpu-list] [-P priority]",
271+ " usage: rtla timerlat [top] [-h] [-q] [-a us] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] \\",
272+ " [[-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] \\",
273+ " [-P priority] [--dma-latency us]",
271274 "",
272275 " -h/--help: print this menu",
276+ " -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
273277 " -p/--period us: timerlat period in us",
274278 " -i/--irq us: stop trace if the irq latency is higher than the argument in us",
275279 " -T/--thread us: stop trace if the thread latency is higher than the argument in us",
@@ -278,8 +282,12 @@ static void timerlat_top_usage(char *usage) · 2 unmodified lines
278282 " -d/--duration time[m|h|d]: duration of the session in seconds",
279283 " -D/--debug: print debug info",
280284 " -t/--trace[=file]: save the stopped trace to [file|timerlat_trace.txt]",
285+ " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed",
286+ " --filter <command>: enable a trace event filter to the previous -e event",
287+ " --trigger <command>: enable a trace event trigger to the previous -e event",
281288 " -n/--nano: display data in nanoseconds",
282289 " -q/--quiet print only a summary at the end",
290+ " --dma-latency us: set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency",
283291 " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters",
284292 " o:prio - use SCHED_OTHER with prio",
285293 " r:prio - use SCHED_RR with prio",
@@ -307,6 +315,8 @@ static struct timerlat_top_params · 21 unmodified lines
307315 *timerlat_top_parse_args(int argc, char **argv)
308316 {
309317 struct timerlat_top_params *params;
318+ struct trace_events *tevent;
319+ long long auto_thresh;
310320 int retval;
311321 int c;
312322
@@ -314,14 +324,19 @@ static struct timerlat_top_params · 1 unmodified line
314324 if (!params)
315325 exit(1);
316326
327+ /* disabled by default */
328+ params->dma_latency = -1;
329+
317330 /* display data in microseconds */
318331 params->output_divisor = 1000;
319332
320333 while (1) {
321334 static struct option long_options[] = {
335+ {"auto", required_argument, 0, 'a'},
322336 {"cpus", required_argument, 0, 'c'},
323337 {"debug", no_argument, 0, 'D'},
324338 {"duration", required_argument, 0, 'd'},
339+ {"event", required_argument, 0, 'e'},
325340 {"help", no_argument, 0, 'h'},
326341 {"irq", required_argument, 0, 'i'},
327342 {"nano", no_argument, 0, 'n'},
@@ -331,13 +346,16 @@ static struct timerlat_top_params · 3 unmodified lines
331346 {"stack", required_argument, 0, 's'},
332347 {"thread", required_argument, 0, 'T'},
333348 {"trace", optional_argument, 0, 't'},
349+ {"trigger", required_argument, 0, '0'},
350+ {"filter", required_argument, 0, '1'},
351+ {"dma-latency", required_argument, 0, '2'},
334352 {0, 0, 0, 0}
335353 };
336354
337355 /* getopt_long stores the option index here. */
338356 int option_index = 0;
339357
340− c = getopt_long(argc, argv, "c:d:Dhi:np:P:qs:t::T:",
358+ c = getopt_long(argc, argv, "a:c:d:De:hi:np:P:qs:t::T:0:1:2:",
341359 long_options, &option_index);
342360
343361 /* detect the end of the options. */
@@ -345,6 +363,19 @@ static struct timerlat_top_params · 1 unmodified line
345363 break;
346364
347365 switch (c) {
366+ case 'a':
367+ auto_thresh = get_llong_from_str(optarg);
368+
369+ /* set thread stop to auto_thresh */
370+ params->stop_total_us = auto_thresh;
371+
372+ /* get stack trace */
373+ params->print_stack = auto_thresh;
374+
375+ /* set trace */
376+ params->trace_output = "timerlat_trace.txt";
377+
378+ break;
348379 case 'c':
349380 retval = parse_cpu_list(optarg, &params->monitored_cpus);
350381 if (retval)
@@ -359,6 +390,17 @@ static struct timerlat_top_params · 8 unmodified lines
359390 if (!params->duration)
360391 timerlat_top_usage("Invalid -D duration\n");
361392 break;
393+ case 'e':
394+ tevent = trace_event_alloc(optarg);
395+ if (!tevent) {
396+ err_msg("Error alloc trace event");
397+ exit(EXIT_FAILURE);
398+ }
399+
400+ if (params->events)
401+ tevent->next = params->events;
402+ params->events = tevent;
403+ break;
362404 case 'h':
363405 case '?':
364406 timerlat_top_usage(NULL);
@@ -396,6 +438,35 @@ static struct timerlat_top_params · 31 unmodified lines
396438 else
397439 params->trace_output = "timerlat_trace.txt";
398440 break;
441+ case '0': /* trigger */
442+ if (params->events) {
443+ retval = trace_event_add_trigger(params->events, optarg);
444+ if (retval) {
445+ err_msg("Error adding trigger %s\n", optarg);
446+ exit(EXIT_FAILURE);
447+ }
448+ } else {
449+ timerlat_top_usage("--trigger requires a previous -e\n");
450+ }
451+ break;
452+ case '1': /* filter */
453+ if (params->events) {
454+ retval = trace_event_add_filter(params->events, optarg);
455+ if (retval) {
456+ err_msg("Error adding filter %s\n", optarg);
457+ exit(EXIT_FAILURE);
458+ }
459+ } else {
460+ timerlat_top_usage("--filter requires a previous -e\n");
461+ }
462+ break;
463+ case '2': /* dma-latency */
464+ params->dma_latency = get_llong_from_str(optarg);
465+ if (params->dma_latency < 0 || params->dma_latency > 10000) {
466+ err_msg("--dma-latency needs to be >= 0 and < 10000");
467+ exit(EXIT_FAILURE);
468+ }
469+ break;
399470 default:
400471 timerlat_top_usage("Invalid option");
401472 }
@@ -524,6 +595,7 @@ int timerlat_top_main(int argc, char *argv[]) · 122 unmodified lines
524595 struct osnoise_tool *record = NULL;
525596 struct osnoise_tool *top = NULL;
526597 struct trace_instance *trace;
598+ int dma_latency_fd = -1;
527599 int return_value = 1;
528600 int retval;
529601
@@ -559,6 +631,14 @@ int timerlat_top_main(int argc, char *argv[]) · 29 unmodified lines
559631 }
560632 }
561633
634+ if (params->dma_latency >= 0) {
635+ dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
636+ if (dma_latency_fd < 0) {
637+ err_msg("Could not set /dev/cpu_dma_latency.\n");
638+ goto out_top;
639+ }
640+ }
641+
562642 trace_instance_start(trace);
563643
564644 if (params->trace_output) {
@@ -567,6 +647,13 @@ int timerlat_top_main(int argc, char *argv[]) · 2 unmodified lines
567647 err_msg("Failed to enable the trace instance\n");
568648 goto out_top;
569649 }
650+
651+ if (params->events) {
652+ retval = trace_events_enable(&record->trace, params->events);
653+ if (retval)
654+ goto out_top;
655+ }
656+
570657 trace_instance_start(&record->trace);
571658 }
572659
@@ -590,16 +677,16 @@ int timerlat_top_main(int argc, char *argv[]) · 17 unmodified lines
590677 if (!params->quiet)
591678 timerlat_print_stats(params, top);
592679
593− if (!tracefs_trace_is_on(trace->inst))
680+ if (trace_is_off(&top->trace, &record->trace))
594681 break;
595682
596− };
683+ }
597684
598685 timerlat_print_stats(params, top);
599686
600687 return_value = 0;
601688
602− if (!tracefs_trace_is_on(trace->inst)) {
689+ if (trace_is_off(&top->trace, &record->trace)) {
603690 printf("rtla timelat hit stop tracing\n");
604691 if (params->trace_output) {
605692 printf(" Saving trace to %s\n", params->trace_output);
@@ -608,6 +695,10 @@ int timerlat_top_main(int argc, char *argv[]) · 2 unmodified lines
608695 }
609696
610697 out_top:
698+ if (dma_latency_fd >= 0)
699+ close(dma_latency_fd);
700+ trace_events_destroy(&record->trace, params->events);
701+ params->events = NULL;
611702 timerlat_free_top(top->data);
612703 osnoise_destroy_tool(record);
613704 osnoise_destroy_tool(top);
tools/tracing/rtla/src/trace.c+345−0
@@ -190,3 +190,348 @@ int trace_instance_start(struct trace_instance *trace) · 189 unmodified lines
190190 {
191191 return tracefs_trace_on(trace->inst);
192192 }
193+
194+/*
195+ * trace_events_free - free a list of trace events
196+ */
197+static void trace_events_free(struct trace_events *events)
198+{
199+ struct trace_events *tevent = events;
200+ struct trace_events *free_event;
201+
202+ while (tevent) {
203+ free_event = tevent;
204+
205+ tevent = tevent->next;
206+
207+ if (free_event->filter)
208+ free(free_event->filter);
209+ if (free_event->trigger)
210+ free(free_event->trigger);
211+ free(free_event->system);
212+ free(free_event);
213+ }
214+}
215+
216+/*
217+ * trace_event_alloc - alloc and parse a single trace event
218+ */
219+struct trace_events *trace_event_alloc(const char *event_string)
220+{
221+ struct trace_events *tevent;
222+
223+ tevent = calloc(1, sizeof(*tevent));
224+ if (!tevent)
225+ return NULL;
226+
227+ tevent->system = strdup(event_string);
228+ if (!tevent->system) {
229+ free(tevent);
230+ return NULL;
231+ }
232+
233+ tevent->event = strstr(tevent->system, ":");
234+ if (tevent->event) {
235+ *tevent->event = '\0';
236+ tevent->event = &tevent->event[1];
237+ }
238+
239+ return tevent;
240+}
241+
242+/*
243+ * trace_event_add_filter - record an event filter
244+ */
245+int trace_event_add_filter(struct trace_events *event, char *filter)
246+{
247+ if (event->filter)
248+ free(event->filter);
249+
250+ event->filter = strdup(filter);
251+ if (!event->filter)
252+ return 1;
253+
254+ return 0;
255+}
256+
257+/*
258+ * trace_event_add_trigger - record an event trigger action
259+ */
260+int trace_event_add_trigger(struct trace_events *event, char *trigger)
261+{
262+ if (event->trigger)
263+ free(event->trigger);
264+
265+ event->trigger = strdup(trigger);
266+ if (!event->trigger)
267+ return 1;
268+
269+ return 0;
270+}
271+
272+/*
273+ * trace_event_disable_filter - disable an event filter
274+ */
275+static void trace_event_disable_filter(struct trace_instance *instance,
276+ struct trace_events *tevent)
277+{
278+ char filter[1024];
279+ int retval;
280+
281+ if (!tevent->filter)
282+ return;
283+
284+ if (!tevent->filter_enabled)
285+ return;
286+
287+ debug_msg("Disabling %s:%s filter %s\n", tevent->system,
288+ tevent->event ? : "*", tevent->filter);
289+
290+ snprintf(filter, 1024, "!%s\n", tevent->filter);
291+
292+ retval = tracefs_event_file_write(instance->inst, tevent->system,
293+ tevent->event, "filter", filter);
294+ if (retval < 0)
295+ err_msg("Error disabling %s:%s filter %s\n", tevent->system,
296+ tevent->event ? : "*", tevent->filter);
297+}
298+
299+/*
300+ * trace_event_save_hist - save the content of an event hist
301+ *
302+ * If the trigger is a hist: one, save the content of the hist file.
303+ */
304+static void trace_event_save_hist(struct trace_instance *instance,
305+ struct trace_events *tevent)
306+{
307+ int retval, index, out_fd;
308+ mode_t mode = 0644;
309+ char path[1024];
310+ char *hist;
311+
312+ if (!tevent)
313+ return;
314+
315+ /* trigger enables hist */
316+ if (!tevent->trigger)
317+ return;
318+
319+ /* is this a hist: trigger? */
320+ retval = strncmp(tevent->trigger, "hist:", strlen("hist:"));
321+ if (retval)
322+ return;
323+
324+ snprintf(path, 1024, "%s_%s_hist.txt", tevent->system, tevent->event);
325+
326+ printf(" Saving event %s:%s hist to %s\n", tevent->system, tevent->event, path);
327+
328+ out_fd = creat(path, mode);
329+ if (out_fd < 0) {
330+ err_msg(" Failed to create %s output file\n", path);
331+ return;
332+ }
333+
334+ hist = tracefs_event_file_read(instance->inst, tevent->system, tevent->event, "hist", 0);
335+ if (!hist) {
336+ err_msg(" Failed to read %s:%s hist file\n", tevent->system, tevent->event);
337+ goto out_close;
338+ }
339+
340+ index = 0;
341+ do {
342+ index += write(out_fd, &hist[index], strlen(hist) - index);
343+ } while (index < strlen(hist));
344+
345+ free(hist);
346+out_close:
347+ close(out_fd);
348+}
349+
350+/*
351+ * trace_event_disable_trigger - disable an event trigger
352+ */
353+static void trace_event_disable_trigger(struct trace_instance *instance,
354+ struct trace_events *tevent)
355+{
356+ char trigger[1024];
357+ int retval;
358+
359+ if (!tevent->trigger)
360+ return;
361+
362+ if (!tevent->trigger_enabled)
363+ return;
364+
365+ debug_msg("Disabling %s:%s trigger %s\n", tevent->system,
366+ tevent->event ? : "*", tevent->trigger);
367+
368+ trace_event_save_hist(instance, tevent);
369+
370+ snprintf(trigger, 1024, "!%s\n", tevent->trigger);
371+
372+ retval = tracefs_event_file_write(instance->inst, tevent->system,
373+ tevent->event, "trigger", trigger);
374+ if (retval < 0)
375+ err_msg("Error disabling %s:%s trigger %s\n", tevent->system,
376+ tevent->event ? : "*", tevent->trigger);
377+}
378+
379+/*
380+ * trace_events_disable - disable all trace events
381+ */
382+void trace_events_disable(struct trace_instance *instance,
383+ struct trace_events *events)
384+{
385+ struct trace_events *tevent = events;
386+
387+ if (!events)
388+ return;
389+
390+ while (tevent) {
391+ debug_msg("Disabling event %s:%s\n", tevent->system, tevent->event ? : "*");
392+ if (tevent->enabled) {
393+ trace_event_disable_filter(instance, tevent);
394+ trace_event_disable_trigger(instance, tevent);
395+ tracefs_event_disable(instance->inst, tevent->system, tevent->event);
396+ }
397+
398+ tevent->enabled = 0;
399+ tevent = tevent->next;
400+ }
401+}
402+
403+/*
404+ * trace_event_enable_filter - enable an event filter associated with an event
405+ */
406+static int trace_event_enable_filter(struct trace_instance *instance,
407+ struct trace_events *tevent)
408+{
409+ char filter[1024];
410+ int retval;
411+
412+ if (!tevent->filter)
413+ return 0;
414+
415+ if (!tevent->event) {
416+ err_msg("Filter %s applies only for single events, not for all %s:* events\n",
417+ tevent->filter, tevent->system);
418+ return 1;
419+ }
420+
421+ snprintf(filter, 1024, "%s\n", tevent->filter);
422+
423+ debug_msg("Enabling %s:%s filter %s\n", tevent->system,
424+ tevent->event ? : "*", tevent->filter);
425+
426+ retval = tracefs_event_file_write(instance->inst, tevent->system,
427+ tevent->event, "filter", filter);
428+ if (retval < 0) {
429+ err_msg("Error enabling %s:%s filter %s\n", tevent->system,
430+ tevent->event ? : "*", tevent->filter);
431+ return 1;
432+ }
433+
434+ tevent->filter_enabled = 1;
435+ return 0;
436+}
437+
438+/*
439+ * trace_event_enable_trigger - enable an event trigger associated with an event
440+ */
441+static int trace_event_enable_trigger(struct trace_instance *instance,
442+ struct trace_events *tevent)
443+{
444+ char trigger[1024];
445+ int retval;
446+
447+ if (!tevent->trigger)
448+ return 0;
449+
450+ if (!tevent->event) {
451+ err_msg("Trigger %s applies only for single events, not for all %s:* events\n",
452+ tevent->trigger, tevent->system);
453+ return 1;
454+ }
455+
456+ snprintf(trigger, 1024, "%s\n", tevent->trigger);
457+
458+ debug_msg("Enabling %s:%s trigger %s\n", tevent->system,
459+ tevent->event ? : "*", tevent->trigger);
460+
461+ retval = tracefs_event_file_write(instance->inst, tevent->system,
462+ tevent->event, "trigger", trigger);
463+ if (retval < 0) {
464+ err_msg("Error enabling %s:%s trigger %s\n", tevent->system,
465+ tevent->event ? : "*", tevent->trigger);
466+ return 1;
467+ }
468+
469+ tevent->trigger_enabled = 1;
470+
471+ return 0;
472+}
473+
474+/*
475+ * trace_events_enable - enable all events
476+ */
477+int trace_events_enable(struct trace_instance *instance,
478+ struct trace_events *events)
479+{
480+ struct trace_events *tevent = events;
481+ int retval;
482+
483+ while (tevent) {
484+ debug_msg("Enabling event %s:%s\n", tevent->system, tevent->event ? : "*");
485+ retval = tracefs_event_enable(instance->inst, tevent->system, tevent->event);
486+ if (retval < 0) {
487+ err_msg("Error enabling event %s:%s\n", tevent->system,
488+ tevent->event ? : "*");
489+ return 1;
490+ }
491+
492+ retval = trace_event_enable_filter(instance, tevent);
493+ if (retval)
494+ return 1;
495+
496+ retval = trace_event_enable_trigger(instance, tevent);
497+ if (retval)
498+ return 1;
499+
500+ tevent->enabled = 1;
501+ tevent = tevent->next;
502+ }
503+
504+ return 0;
505+}
506+
507+/*
508+ * trace_events_destroy - disable and free all trace events
509+ */
510+void trace_events_destroy(struct trace_instance *instance,
511+ struct trace_events *events)
512+{
513+ if (!events)
514+ return;
515+
516+ trace_events_disable(instance, events);
517+ trace_events_free(events);
518+}
519+
520+int trace_is_off(struct trace_instance *tool, struct trace_instance *trace)
521+{
522+ /*
523+ * The tool instance is always present, it is the one used to collect
524+ * data.
525+ */
526+ if (!tracefs_trace_is_on(tool->inst))
527+ return 1;
528+
529+ /*
530+ * The trace instance is only enabled when -t is set. IOW, when the system
531+ * is tracing.
532+ */
533+ if (trace && !tracefs_trace_is_on(trace->inst))
534+ return 1;
535+
536+ return 0;
537+}
tools/tracing/rtla/src/trace.h+23−0
@@ -2,6 +2,17 @@ · 1 unmodified line
22 #include <tracefs.h>
33 #include <stddef.h>
44
5+struct trace_events {
6+ struct trace_events *next;
7+ char *system;
8+ char *event;
9+ char *filter;
10+ char *trigger;
11+ char enabled;
12+ char filter_enabled;
13+ char trigger_enabled;
14+};
15+
516 struct trace_instance {
617 struct tracefs_instance *inst;
718 struct tep_handle *tep;
@@ -25,3 +36,15 @@ void destroy_instance(struct tracefs_instance *inst); · 17 unmodified lines
2536 int save_trace_to_file(struct tracefs_instance *inst, const char *filename);
2637 int collect_registered_events(struct tep_event *tep, struct tep_record *record,
2738 int cpu, void *context);
39+
40+struct trace_events *trace_event_alloc(const char *event_string);
41+void trace_events_disable(struct trace_instance *instance,
42+ struct trace_events *events);
43+void trace_events_destroy(struct trace_instance *instance,
44+ struct trace_events *events);
45+int trace_events_enable(struct trace_instance *instance,
46+ struct trace_events *events);
47+
48+int trace_event_add_filter(struct trace_events *event, char *filter);
49+int trace_event_add_trigger(struct trace_events *event, char *trigger);
50+int trace_is_off(struct trace_instance *tool, struct trace_instance *trace);
tools/tracing/rtla/src/utils.c+33−0
@@ -10,6 +10,7 @@ · 9 unmodified lines
1010 #include <unistd.h>
1111 #include <ctype.h>
1212 #include <errno.h>
13+#include <fcntl.h>
1314 #include <sched.h>
1415 #include <stdio.h>
1516
@@ -431,3 +432,35 @@ int parse_prio(char *arg, struct sched_attr *sched_param) · 415 unmodified lines
431432 }
432433 return 0;
433434 }
435+
436+/*
437+ * set_cpu_dma_latency - set the /dev/cpu_dma_latecy
438+ *
439+ * This is used to reduce the exit from idle latency. The value
440+ * will be reset once the file descriptor of /dev/cpu_dma_latecy
441+ * is closed.
442+ *
443+ * Return: the /dev/cpu_dma_latecy file descriptor
444+ */
445+int set_cpu_dma_latency(int32_t latency)
446+{
447+ int retval;
448+ int fd;
449+
450+ fd = open("/dev/cpu_dma_latency", O_RDWR);
451+ if (fd < 0) {
452+ err_msg("Error opening /dev/cpu_dma_latency\n");
453+ return -1;
454+ }
455+
456+ retval = write(fd, &latency, 4);
457+ if (retval < 1) {
458+ err_msg("Error setting /dev/cpu_dma_latency\n");
459+ close(fd);
460+ return -1;
461+ }
462+
463+ debug_msg("Set /dev/cpu_dma_latency to %d\n", latency);
464+
465+ return fd;
466+}
tools/tracing/rtla/src/utils.h+1−0
@@ -54,3 +54,4 @@ struct sched_attr { · 53 unmodified lines
5454
5555 int parse_prio(char *arg, struct sched_attr *sched_param);
5656 int set_comm_sched_attr(const char *comm, struct sched_attr *attr);
57+int set_cpu_dma_latency(int32_t latency);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t