Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+903 -28
+19
Documentation/tools/rtla/common_options.rst
··· 14 14 15 15 Save the stopped trace to [*file|osnoise_trace.txt*]. 16 16 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 + 17 36 **-P**, **--priority** *o:prio|r:prio|f:prio|d:runtime:period* 18 37 19 38 Set scheduling parameters to the osnoise tracer threads, the format to set the priority are:
+10
Documentation/tools/rtla/common_osnoise_options.rst
··· 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 + 1 6 **-p**, **--period** *us* 2 7 3 8 Set the *osnoise* tracer period in microseconds. ··· 20 15 21 16 Stop the trace if the total sample is higher than the argument in microseconds. 22 17 If **-T** is set, it will also save the trace to the output. 18 + 19 + **-T**, **--threshold** *us* 20 + 21 + Specify the minimum delta between two time reads to be considered noise. 22 + The default threshold is *5 us*.
+12
Documentation/tools/rtla/common_timerlat_options.rst
··· 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 + 1 8 **-p**, **--period** *us* 2 9 3 10 Set the *timerlat* tracer period in microseconds. ··· 21 14 22 15 Save the stack trace at the *IRQ* if a *Thread* latency is higher than the 23 16 argument in us. 17 + 18 + **--dma-latency** *us* 19 + Set the /dev/cpu_dma_latency to *us*, aiming to bound exit from idle latencies. 20 + *cyclictest* sets this value to *0* by default, use **--dma-latency** *0* to have 21 + similar results.
+83
tools/tracing/rtla/src/osnoise.c
··· 656 656 } 657 657 658 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 + 737 + /* 659 738 * enable_osnoise - enable osnoise tracer in the trace_instance 660 739 */ 661 740 int enable_osnoise(struct trace_instance *trace) ··· 795 716 context->orig_print_stack = OSNOISE_OPTION_INIT_VAL; 796 717 context->print_stack = OSNOISE_OPTION_INIT_VAL; 797 718 719 + context->orig_tracing_thresh = OSNOISE_OPTION_INIT_VAL; 720 + context->tracing_thresh = OSNOISE_OPTION_INIT_VAL; 721 + 798 722 osnoise_get_context(context); 799 723 800 724 return context; ··· 823 741 osnoise_put_stop_total_us(context); 824 742 osnoise_put_timerlat_period_us(context); 825 743 osnoise_put_print_stack(context); 744 + osnoise_put_tracing_thresh(context); 826 745 827 746 free(context); 828 747 }
+8
tools/tracing/rtla/src/osnoise.h
··· 23 23 long long orig_timerlat_period_us; 24 24 long long timerlat_period_us; 25 25 26 + /* 0 as init value */ 27 + long long orig_tracing_thresh; 28 + long long tracing_thresh; 29 + 26 30 /* -1 as init value because 0 is disabled */ 27 31 long long orig_stop_us; 28 32 long long stop_us; ··· 70 66 int osnoise_set_timerlat_period_us(struct osnoise_context *context, 71 67 long long timerlat_period_us); 72 68 void osnoise_restore_timerlat_period_us(struct osnoise_context *context); 69 + 70 + int osnoise_set_tracing_thresh(struct osnoise_context *context, 71 + long long tracing_thresh); 72 + void osnoise_restore_tracing_thresh(struct osnoise_context *context); 73 73 74 74 void osnoise_restore_print_stack(struct osnoise_context *context); 75 75 int osnoise_set_print_stack(struct osnoise_context *context,
+87 -8
tools/tracing/rtla/src/osnoise_hist.c
··· 21 21 char *trace_output; 22 22 unsigned long long runtime; 23 23 unsigned long long period; 24 + long long threshold; 24 25 long long stop_us; 25 26 long long stop_total_us; 26 27 int sleep_time; ··· 29 28 int set_sched; 30 29 int output_divisor; 31 30 struct sched_attr sched_param; 31 + struct trace_events *events; 32 32 33 33 char no_header; 34 34 char no_summary; ··· 427 425 428 426 static const char * const msg[] = { 429 427 "", 430 - " usage: rtla osnoise hist [-h] [-D] [-d s] [-p us] [-r us] [-s us] [-S us] [-t[=file]] \\", 431 - " [-c cpu-list] [-P priority] [-b N] [-E N] [--no-header] [--no-summary] \\", 432 - " [--no-index] [--with-zeros]", 428 + " usage: rtla osnoise hist [-h] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\", 429 + " [-T us] [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\", 430 + " [-c cpu-list] [-P priority] [-b N] [-E N] [--no-header] [--no-summary] [--no-index] \\", 431 + " [--with-zeros]", 433 432 "", 434 433 " -h/--help: print this menu", 434 + " -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit", 435 435 " -p/--period us: osnoise period in us", 436 436 " -r/--runtime us: osnoise runtime in us", 437 437 " -s/--stop us: stop trace if a single sample is higher than the argument in us", 438 438 " -S/--stop-total us: stop trace if the total sample is higher than the argument in us", 439 + " -T/--threshold us: the minimum delta to be considered a noise", 439 440 " -c/--cpus cpu-list: list of cpus to run osnoise threads", 440 441 " -d/--duration time[s|m|h|d]: duration of the session", 441 442 " -D/--debug: print debug info", 442 443 " -t/--trace[=file]: save the stopped trace to [file|osnoise_trace.txt]", 444 + " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed", 445 + " --filter <filter>: enable a trace event filter to the previous -e event", 446 + " --trigger <trigger>: enable a trace event trigger to the previous -e event", 443 447 " -b/--bucket-size N: set the histogram bucket size (default 1)", 444 448 " -E/--entries N: set the number of entries of the histogram (default 256)", 445 449 " --no-header: do not print header", ··· 479 471 *osnoise_hist_parse_args(int argc, char *argv[]) 480 472 { 481 473 struct osnoise_hist_params *params; 474 + struct trace_events *tevent; 482 475 int retval; 483 476 int c; 484 477 ··· 494 485 495 486 while (1) { 496 487 static struct option long_options[] = { 488 + {"auto", required_argument, 0, 'a'}, 497 489 {"bucket-size", required_argument, 0, 'b'}, 498 490 {"entries", required_argument, 0, 'E'}, 499 491 {"cpus", required_argument, 0, 'c'}, ··· 507 497 {"stop", required_argument, 0, 's'}, 508 498 {"stop-total", required_argument, 0, 'S'}, 509 499 {"trace", optional_argument, 0, 't'}, 500 + {"event", required_argument, 0, 'e'}, 501 + {"threshold", required_argument, 0, 'T'}, 510 502 {"no-header", no_argument, 0, '0'}, 511 503 {"no-summary", no_argument, 0, '1'}, 512 504 {"no-index", no_argument, 0, '2'}, 513 505 {"with-zeros", no_argument, 0, '3'}, 506 + {"trigger", required_argument, 0, '4'}, 507 + {"filter", required_argument, 0, '5'}, 514 508 {0, 0, 0, 0} 515 509 }; 516 510 517 511 /* getopt_long stores the option index here. */ 518 512 int option_index = 0; 519 513 520 - c = getopt_long(argc, argv, "c:b:d:E:Dhp:P:r:s:S:t::0123", 514 + c = getopt_long(argc, argv, "a:c:b:d:e:E:Dhp:P:r:s:S:t::T:01234:5:", 521 515 long_options, &option_index); 522 516 523 517 /* detect the end of the options. */ ··· 529 515 break; 530 516 531 517 switch (c) { 518 + case 'a': 519 + /* set sample stop to auto_thresh */ 520 + params->stop_us = get_llong_from_str(optarg); 521 + 522 + /* set sample threshold to 1 */ 523 + params->threshold = 1; 524 + 525 + /* set trace */ 526 + params->trace_output = "osnoise_trace.txt"; 527 + 528 + break; 532 529 case 'b': 533 530 params->bucket_size = get_llong_from_str(optarg); 534 531 if ((params->bucket_size == 0) || (params->bucket_size >= 1000000)) ··· 558 533 params->duration = parse_seconds_duration(optarg); 559 534 if (!params->duration) 560 535 osnoise_hist_usage("Invalid -D duration\n"); 536 + break; 537 + case 'e': 538 + tevent = trace_event_alloc(optarg); 539 + if (!tevent) { 540 + err_msg("Error alloc trace event"); 541 + exit(EXIT_FAILURE); 542 + } 543 + 544 + if (params->events) 545 + tevent->next = params->events; 546 + 547 + params->events = tevent; 561 548 break; 562 549 case 'E': 563 550 params->entries = get_llong_from_str(optarg); ··· 602 565 case 'S': 603 566 params->stop_total_us = get_llong_from_str(optarg); 604 567 break; 568 + case 'T': 569 + params->threshold = get_llong_from_str(optarg); 570 + break; 605 571 case 't': 606 572 if (optarg) 607 573 /* skip = */ ··· 623 583 break; 624 584 case '3': /* with zeros */ 625 585 params->with_zeros = 1; 586 + break; 587 + case '4': /* trigger */ 588 + if (params->events) { 589 + retval = trace_event_add_trigger(params->events, optarg); 590 + if (retval) { 591 + err_msg("Error adding trigger %s\n", optarg); 592 + exit(EXIT_FAILURE); 593 + } 594 + } else { 595 + osnoise_hist_usage("--trigger requires a previous -e\n"); 596 + } 597 + break; 598 + case '5': /* filter */ 599 + if (params->events) { 600 + retval = trace_event_add_filter(params->events, optarg); 601 + if (retval) { 602 + err_msg("Error adding filter %s\n", optarg); 603 + exit(EXIT_FAILURE); 604 + } 605 + } else { 606 + osnoise_hist_usage("--filter requires a previous -e\n"); 607 + } 626 608 break; 627 609 default: 628 610 osnoise_hist_usage("Invalid option"); ··· 703 641 retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); 704 642 if (retval) { 705 643 err_msg("Failed to set stop total us\n"); 644 + goto out_err; 645 + } 646 + } 647 + 648 + if (params->threshold) { 649 + retval = osnoise_set_tracing_thresh(tool->context, params->threshold); 650 + if (retval) { 651 + err_msg("Failed to set tracing_thresh\n"); 706 652 goto out_err; 707 653 } 708 654 } ··· 821 751 err_msg("Failed to enable the trace instance\n"); 822 752 goto out_hist; 823 753 } 754 + 755 + if (params->events) { 756 + retval = trace_events_enable(&record->trace, params->events); 757 + if (retval) 758 + goto out_hist; 759 + } 760 + 824 761 trace_instance_start(&record->trace); 825 762 } 826 763 ··· 848 771 goto out_hist; 849 772 } 850 773 851 - if (!tracefs_trace_is_on(trace->inst)) 774 + if (trace_is_off(&tool->trace, &record->trace)) 852 775 break; 853 - }; 776 + } 854 777 855 778 osnoise_read_trace_hist(tool); 856 779 ··· 858 781 859 782 return_value = 0; 860 783 861 - if (!tracefs_trace_is_on(trace->inst)) { 862 - printf("rtla timelat hit stop tracing\n"); 784 + if (trace_is_off(&tool->trace, &record->trace)) { 785 + printf("rtla osnoise hit stop tracing\n"); 863 786 if (params->trace_output) { 864 787 printf(" Saving trace to %s\n", params->trace_output); 865 788 save_trace_to_file(record->trace.inst, params->trace_output); ··· 867 790 } 868 791 869 792 out_hist: 793 + trace_events_destroy(&record->trace, params->events); 794 + params->events = NULL; 870 795 osnoise_free_histogram(tool->data); 871 796 out_destroy: 872 797 osnoise_destroy_tool(record);
+85 -6
tools/tracing/rtla/src/osnoise_top.c
··· 23 23 char *trace_output; 24 24 unsigned long long runtime; 25 25 unsigned long long period; 26 + long long threshold; 26 27 long long stop_us; 27 28 long long stop_total_us; 28 29 int sleep_time; ··· 31 30 int quiet; 32 31 int set_sched; 33 32 struct sched_attr sched_param; 33 + struct trace_events *events; 34 34 }; 35 35 36 36 struct osnoise_top_cpu { ··· 246 244 int i; 247 245 248 246 static const char * const msg[] = { 249 - " usage: rtla osnoise [top] [-h] [-q] [-D] [-d s] [-p us] [-r us] [-s us] [-S us] [-t[=file]] \\", 247 + " usage: rtla osnoise [top] [-h] [-q] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\", 248 + " [-T us] [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\", 250 249 " [-c cpu-list] [-P priority]", 251 250 "", 252 251 " -h/--help: print this menu", 252 + " -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit", 253 253 " -p/--period us: osnoise period in us", 254 254 " -r/--runtime us: osnoise runtime in us", 255 255 " -s/--stop us: stop trace if a single sample is higher than the argument in us", 256 256 " -S/--stop-total us: stop trace if the total sample is higher than the argument in us", 257 + " -T/--threshold us: the minimum delta to be considered a noise", 257 258 " -c/--cpus cpu-list: list of cpus to run osnoise threads", 258 259 " -d/--duration time[s|m|h|d]: duration of the session", 259 260 " -D/--debug: print debug info", 260 261 " -t/--trace[=file]: save the stopped trace to [file|osnoise_trace.txt]", 262 + " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed", 263 + " --filter <filter>: enable a trace event filter to the previous -e event", 264 + " --trigger <trigger>: enable a trace event trigger to the previous -e event", 261 265 " -q/--quiet print only a summary at the end", 262 266 " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters", 263 267 " o:prio - use SCHED_OTHER with prio", ··· 291 283 struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) 292 284 { 293 285 struct osnoise_top_params *params; 286 + struct trace_events *tevent; 294 287 int retval; 295 288 int c; 296 289 ··· 301 292 302 293 while (1) { 303 294 static struct option long_options[] = { 295 + {"auto", required_argument, 0, 'a'}, 304 296 {"cpus", required_argument, 0, 'c'}, 305 297 {"debug", no_argument, 0, 'D'}, 306 298 {"duration", required_argument, 0, 'd'}, 299 + {"event", required_argument, 0, 'e'}, 307 300 {"help", no_argument, 0, 'h'}, 308 301 {"period", required_argument, 0, 'p'}, 309 302 {"priority", required_argument, 0, 'P'}, ··· 313 302 {"runtime", required_argument, 0, 'r'}, 314 303 {"stop", required_argument, 0, 's'}, 315 304 {"stop-total", required_argument, 0, 'S'}, 305 + {"threshold", required_argument, 0, 'T'}, 316 306 {"trace", optional_argument, 0, 't'}, 307 + {"trigger", required_argument, 0, '0'}, 308 + {"filter", required_argument, 0, '1'}, 317 309 {0, 0, 0, 0} 318 310 }; 319 311 320 312 /* getopt_long stores the option index here. */ 321 313 int option_index = 0; 322 314 323 - c = getopt_long(argc, argv, "c:d:Dhp:P:qr:s:S:t::", 315 + c = getopt_long(argc, argv, "a:c:d:De:hp:P:qr:s:S:t::T:0:1:", 324 316 long_options, &option_index); 325 317 326 318 /* Detect the end of the options. */ ··· 331 317 break; 332 318 333 319 switch (c) { 320 + case 'a': 321 + /* set sample stop to auto_thresh */ 322 + params->stop_us = get_llong_from_str(optarg); 323 + 324 + /* set sample threshold to 1 */ 325 + params->threshold = 1; 326 + 327 + /* set trace */ 328 + params->trace_output = "osnoise_trace.txt"; 329 + 330 + break; 334 331 case 'c': 335 332 retval = parse_cpu_list(optarg, &params->monitored_cpus); 336 333 if (retval) ··· 355 330 params->duration = parse_seconds_duration(optarg); 356 331 if (!params->duration) 357 332 osnoise_top_usage("Invalid -D duration\n"); 333 + break; 334 + case 'e': 335 + tevent = trace_event_alloc(optarg); 336 + if (!tevent) { 337 + err_msg("Error alloc trace event"); 338 + exit(EXIT_FAILURE); 339 + } 340 + 341 + if (params->events) 342 + tevent->next = params->events; 343 + params->events = tevent; 344 + 358 345 break; 359 346 case 'h': 360 347 case '?': ··· 403 366 params->trace_output = &optarg[1]; 404 367 else 405 368 params->trace_output = "osnoise_trace.txt"; 369 + break; 370 + case 'T': 371 + params->threshold = get_llong_from_str(optarg); 372 + break; 373 + case '0': /* trigger */ 374 + if (params->events) { 375 + retval = trace_event_add_trigger(params->events, optarg); 376 + if (retval) { 377 + err_msg("Error adding trigger %s\n", optarg); 378 + exit(EXIT_FAILURE); 379 + } 380 + } else { 381 + osnoise_top_usage("--trigger requires a previous -e\n"); 382 + } 383 + break; 384 + case '1': /* filter */ 385 + if (params->events) { 386 + retval = trace_event_add_filter(params->events, optarg); 387 + if (retval) { 388 + err_msg("Error adding filter %s\n", optarg); 389 + exit(EXIT_FAILURE); 390 + } 391 + } else { 392 + osnoise_top_usage("--filter requires a previous -e\n"); 393 + } 406 394 break; 407 395 default: 408 396 osnoise_top_usage("Invalid option"); ··· 483 421 retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); 484 422 if (retval) { 485 423 err_msg("Failed to set stop total us\n"); 424 + goto out_err; 425 + } 426 + } 427 + 428 + if (params->threshold) { 429 + retval = osnoise_set_tracing_thresh(tool->context, params->threshold); 430 + if (retval) { 431 + err_msg("Failed to set tracing_thresh\n"); 486 432 goto out_err; 487 433 } 488 434 } ··· 599 529 err_msg("Failed to enable the trace instance\n"); 600 530 goto out_top; 601 531 } 532 + 533 + if (params->events) { 534 + retval = trace_events_enable(&record->trace, params->events); 535 + if (retval) 536 + goto out_top; 537 + } 538 + 602 539 trace_instance_start(&record->trace); 603 540 } 604 541 605 542 tool->start_time = time(NULL); 606 543 osnoise_top_set_signals(params); 607 544 608 - do { 545 + while (!stop_tracing) { 609 546 sleep(params->sleep_time); 610 547 611 548 retval = tracefs_iterate_raw_events(trace->tep, ··· 629 552 if (!params->quiet) 630 553 osnoise_print_stats(params, tool); 631 554 632 - if (!tracefs_trace_is_on(trace->inst)) 555 + if (trace_is_off(&tool->trace, &record->trace)) 633 556 break; 634 557 635 - } while (!stop_tracing); 558 + } 636 559 637 560 osnoise_print_stats(params, tool); 638 561 639 562 return_value = 0; 640 563 641 - if (!tracefs_trace_is_on(trace->inst)) { 564 + if (trace_is_off(&tool->trace, &record->trace)) { 642 565 printf("osnoise hit stop tracing\n"); 643 566 if (params->trace_output) { 644 567 printf(" Saving trace to %s\n", params->trace_output); ··· 647 570 } 648 571 649 572 out_top: 573 + trace_events_destroy(&record->trace, params->events); 574 + params->events = NULL; 650 575 osnoise_free_top(tool->data); 651 576 osnoise_destroy_tool(record); 652 577 osnoise_destroy_tool(tool);
+100 -8
tools/tracing/rtla/src/timerlat_hist.c
··· 28 28 int output_divisor; 29 29 int duration; 30 30 int set_sched; 31 + int dma_latency; 31 32 struct sched_attr sched_param; 33 + struct trace_events *events; 32 34 33 35 char no_irq; 34 36 char no_thread; ··· 430 428 431 429 char *msg[] = { 432 430 "", 433 - " usage: [rtla] timerlat hist [-h] [-q] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] [-t[=file]] \\", 434 - " [-c cpu-list] [-P priority] [-E N] [-b N] [--no-irq] [--no-thread] [--no-header] [--no-summary] \\", 435 - " [--no-index] [--with-zeros]", 431 + " usage: [rtla] timerlat hist [-h] [-q] [-d s] [-D] [-n] [-a us] [-p us] [-i us] [-T us] [-s us] \\", 432 + " [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] \\", 433 + " [-P priority] [-E N] [-b N] [--no-irq] [--no-thread] [--no-header] [--no-summary] \\", 434 + " [--no-index] [--with-zeros] [--dma-latency us]", 436 435 "", 437 436 " -h/--help: print this menu", 437 + " -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit", 438 438 " -p/--period us: timerlat period in us", 439 439 " -i/--irq us: stop trace if the irq latency is higher than the argument in us", 440 440 " -T/--thread us: stop trace if the thread latency is higher than the argument in us", ··· 444 440 " -c/--cpus cpus: run the tracer only on the given cpus", 445 441 " -d/--duration time[m|h|d]: duration of the session in seconds", 446 442 " -D/--debug: print debug info", 447 - " -T/--trace[=file]: save the stopped trace to [file|timerlat_trace.txt]", 443 + " -t/--trace[=file]: save the stopped trace to [file|timerlat_trace.txt]", 444 + " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed", 445 + " --filter <filter>: enable a trace event filter to the previous -e event", 446 + " --trigger <trigger>: enable a trace event trigger to the previous -e event", 448 447 " -n/--nano: display data in nanoseconds", 449 448 " -b/--bucket-size N: set the histogram bucket size (default 1)", 450 449 " -E/--entries N: set the number of entries of the histogram (default 256)", ··· 457 450 " --no-summary: do not print summary", 458 451 " --no-index: do not print index", 459 452 " --with-zeros: print zero only entries", 453 + " --dma-latency us: set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency", 460 454 " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters", 461 455 " o:prio - use SCHED_OTHER with prio", 462 456 " r:prio - use SCHED_RR with prio", ··· 485 477 *timerlat_hist_parse_args(int argc, char *argv[]) 486 478 { 487 479 struct timerlat_hist_params *params; 480 + struct trace_events *tevent; 481 + int auto_thresh; 488 482 int retval; 489 483 int c; 490 484 491 485 params = calloc(1, sizeof(*params)); 492 486 if (!params) 493 487 exit(1); 488 + 489 + /* disabled by default */ 490 + params->dma_latency = -1; 494 491 495 492 /* display data in microseconds */ 496 493 params->output_divisor = 1000; ··· 504 491 505 492 while (1) { 506 493 static struct option long_options[] = { 494 + {"auto", required_argument, 0, 'a'}, 507 495 {"cpus", required_argument, 0, 'c'}, 508 496 {"bucket-size", required_argument, 0, 'b'}, 509 497 {"debug", no_argument, 0, 'D'}, ··· 518 504 {"stack", required_argument, 0, 's'}, 519 505 {"thread", required_argument, 0, 'T'}, 520 506 {"trace", optional_argument, 0, 't'}, 507 + {"event", required_argument, 0, 'e'}, 521 508 {"no-irq", no_argument, 0, '0'}, 522 509 {"no-thread", no_argument, 0, '1'}, 523 510 {"no-header", no_argument, 0, '2'}, 524 511 {"no-summary", no_argument, 0, '3'}, 525 512 {"no-index", no_argument, 0, '4'}, 526 513 {"with-zeros", no_argument, 0, '5'}, 514 + {"trigger", required_argument, 0, '6'}, 515 + {"filter", required_argument, 0, '7'}, 516 + {"dma-latency", required_argument, 0, '8'}, 527 517 {0, 0, 0, 0} 528 518 }; 529 519 530 520 /* getopt_long stores the option index here. */ 531 521 int option_index = 0; 532 522 533 - c = getopt_long(argc, argv, "c:b:d:E:Dhi:np:P:s:t::T:012345", 523 + c = getopt_long(argc, argv, "a:c:b:d:e:E:Dhi:np:P:s:t::T:0123456:7:8:", 534 524 long_options, &option_index); 535 525 536 526 /* detect the end of the options. */ ··· 542 524 break; 543 525 544 526 switch (c) { 527 + case 'a': 528 + auto_thresh = get_llong_from_str(optarg); 529 + 530 + /* set thread stop to auto_thresh */ 531 + params->stop_total_us = auto_thresh; 532 + 533 + /* get stack trace */ 534 + params->print_stack = auto_thresh; 535 + 536 + /* set trace */ 537 + params->trace_output = "timerlat_trace.txt"; 538 + 539 + break; 545 540 case 'c': 546 541 retval = parse_cpu_list(optarg, &params->monitored_cpus); 547 542 if (retval) ··· 573 542 params->duration = parse_seconds_duration(optarg); 574 543 if (!params->duration) 575 544 timerlat_hist_usage("Invalid -D duration\n"); 545 + break; 546 + case 'e': 547 + tevent = trace_event_alloc(optarg); 548 + if (!tevent) { 549 + err_msg("Error alloc trace event"); 550 + exit(EXIT_FAILURE); 551 + } 552 + 553 + if (params->events) 554 + tevent->next = params->events; 555 + 556 + params->events = tevent; 576 557 break; 577 558 case 'E': 578 559 params->entries = get_llong_from_str(optarg); ··· 642 599 break; 643 600 case '5': /* with zeros */ 644 601 params->with_zeros = 1; 602 + break; 603 + case '6': /* trigger */ 604 + if (params->events) { 605 + retval = trace_event_add_trigger(params->events, optarg); 606 + if (retval) { 607 + err_msg("Error adding trigger %s\n", optarg); 608 + exit(EXIT_FAILURE); 609 + } 610 + } else { 611 + timerlat_hist_usage("--trigger requires a previous -e\n"); 612 + } 613 + break; 614 + case '7': /* filter */ 615 + if (params->events) { 616 + retval = trace_event_add_filter(params->events, optarg); 617 + if (retval) { 618 + err_msg("Error adding filter %s\n", optarg); 619 + exit(EXIT_FAILURE); 620 + } 621 + } else { 622 + timerlat_hist_usage("--filter requires a previous -e\n"); 623 + } 624 + break; 625 + case '8': 626 + params->dma_latency = get_llong_from_str(optarg); 627 + if (params->dma_latency < 0 || params->dma_latency > 10000) { 628 + err_msg("--dma-latency needs to be >= 0 and < 10000"); 629 + exit(EXIT_FAILURE); 630 + } 645 631 break; 646 632 default: 647 633 timerlat_hist_usage("Invalid option"); ··· 804 732 struct osnoise_tool *record = NULL; 805 733 struct osnoise_tool *tool = NULL; 806 734 struct trace_instance *trace; 735 + int dma_latency_fd = -1; 807 736 int return_value = 1; 808 737 int retval; 809 738 ··· 840 767 } 841 768 } 842 769 770 + if (params->dma_latency >= 0) { 771 + dma_latency_fd = set_cpu_dma_latency(params->dma_latency); 772 + if (dma_latency_fd < 0) { 773 + err_msg("Could not set /dev/cpu_dma_latency.\n"); 774 + goto out_hist; 775 + } 776 + } 777 + 843 778 trace_instance_start(trace); 844 779 845 780 if (params->trace_output) { ··· 856 775 err_msg("Failed to enable the trace instance\n"); 857 776 goto out_hist; 858 777 } 778 + 779 + if (params->events) { 780 + retval = trace_events_enable(&record->trace, params->events); 781 + if (retval) 782 + goto out_hist; 783 + } 784 + 859 785 trace_instance_start(&record->trace); 860 786 } 861 787 ··· 883 795 goto out_hist; 884 796 } 885 797 886 - if (!tracefs_trace_is_on(trace->inst)) 798 + if (trace_is_off(&tool->trace, &record->trace)) 887 799 break; 888 - }; 800 + } 889 801 890 802 timerlat_print_stats(params, tool); 891 803 892 804 return_value = 0; 893 805 894 - if (!tracefs_trace_is_on(trace->inst)) { 806 + if (trace_is_off(&tool->trace, &record->trace)) { 895 807 printf("rtla timelat hit stop tracing\n"); 896 808 if (params->trace_output) { 897 809 printf(" Saving trace to %s\n", params->trace_output); ··· 900 812 } 901 813 902 814 out_hist: 815 + if (dma_latency_fd >= 0) 816 + close(dma_latency_fd); 817 + trace_events_destroy(&record->trace, params->events); 818 + params->events = NULL; 903 819 timerlat_free_histogram(tool->data); 904 820 osnoise_destroy_tool(record); 905 821 osnoise_destroy_tool(tool);
+97 -6
tools/tracing/rtla/src/timerlat_top.c
··· 29 29 int duration; 30 30 int quiet; 31 31 int set_sched; 32 + int dma_latency; 32 33 struct sched_attr sched_param; 34 + struct trace_events *events; 33 35 }; 34 36 35 37 struct timerlat_top_cpu { ··· 268 266 269 267 static const char *const msg[] = { 270 268 "", 271 - " usage: rtla timerlat [top] [-h] [-q] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] [-t[=file]] \\", 272 - " [-c cpu-list] [-P priority]", 269 + " usage: rtla timerlat [top] [-h] [-q] [-a us] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] \\", 270 + " [[-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] \\", 271 + " [-P priority] [--dma-latency us]", 273 272 "", 274 273 " -h/--help: print this menu", 274 + " -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit", 275 275 " -p/--period us: timerlat period in us", 276 276 " -i/--irq us: stop trace if the irq latency is higher than the argument in us", 277 277 " -T/--thread us: stop trace if the thread latency is higher than the argument in us", ··· 282 278 " -d/--duration time[m|h|d]: duration of the session in seconds", 283 279 " -D/--debug: print debug info", 284 280 " -t/--trace[=file]: save the stopped trace to [file|timerlat_trace.txt]", 281 + " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed", 282 + " --filter <command>: enable a trace event filter to the previous -e event", 283 + " --trigger <command>: enable a trace event trigger to the previous -e event", 285 284 " -n/--nano: display data in nanoseconds", 286 285 " -q/--quiet print only a summary at the end", 286 + " --dma-latency us: set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency", 287 287 " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters", 288 288 " o:prio - use SCHED_OTHER with prio", 289 289 " r:prio - use SCHED_RR with prio", ··· 315 307 *timerlat_top_parse_args(int argc, char **argv) 316 308 { 317 309 struct timerlat_top_params *params; 310 + struct trace_events *tevent; 311 + long long auto_thresh; 318 312 int retval; 319 313 int c; 320 314 ··· 324 314 if (!params) 325 315 exit(1); 326 316 317 + /* disabled by default */ 318 + params->dma_latency = -1; 319 + 327 320 /* display data in microseconds */ 328 321 params->output_divisor = 1000; 329 322 330 323 while (1) { 331 324 static struct option long_options[] = { 325 + {"auto", required_argument, 0, 'a'}, 332 326 {"cpus", required_argument, 0, 'c'}, 333 327 {"debug", no_argument, 0, 'D'}, 334 328 {"duration", required_argument, 0, 'd'}, 329 + {"event", required_argument, 0, 'e'}, 335 330 {"help", no_argument, 0, 'h'}, 336 331 {"irq", required_argument, 0, 'i'}, 337 332 {"nano", no_argument, 0, 'n'}, ··· 346 331 {"stack", required_argument, 0, 's'}, 347 332 {"thread", required_argument, 0, 'T'}, 348 333 {"trace", optional_argument, 0, 't'}, 334 + {"trigger", required_argument, 0, '0'}, 335 + {"filter", required_argument, 0, '1'}, 336 + {"dma-latency", required_argument, 0, '2'}, 349 337 {0, 0, 0, 0} 350 338 }; 351 339 352 340 /* getopt_long stores the option index here. */ 353 341 int option_index = 0; 354 342 355 - c = getopt_long(argc, argv, "c:d:Dhi:np:P:qs:t::T:", 343 + c = getopt_long(argc, argv, "a:c:d:De:hi:np:P:qs:t::T:0:1:2:", 356 344 long_options, &option_index); 357 345 358 346 /* detect the end of the options. */ ··· 363 345 break; 364 346 365 347 switch (c) { 348 + case 'a': 349 + auto_thresh = get_llong_from_str(optarg); 350 + 351 + /* set thread stop to auto_thresh */ 352 + params->stop_total_us = auto_thresh; 353 + 354 + /* get stack trace */ 355 + params->print_stack = auto_thresh; 356 + 357 + /* set trace */ 358 + params->trace_output = "timerlat_trace.txt"; 359 + 360 + break; 366 361 case 'c': 367 362 retval = parse_cpu_list(optarg, &params->monitored_cpus); 368 363 if (retval) ··· 389 358 params->duration = parse_seconds_duration(optarg); 390 359 if (!params->duration) 391 360 timerlat_top_usage("Invalid -D duration\n"); 361 + break; 362 + case 'e': 363 + tevent = trace_event_alloc(optarg); 364 + if (!tevent) { 365 + err_msg("Error alloc trace event"); 366 + exit(EXIT_FAILURE); 367 + } 368 + 369 + if (params->events) 370 + tevent->next = params->events; 371 + params->events = tevent; 392 372 break; 393 373 case 'h': 394 374 case '?': ··· 437 395 params->trace_output = &optarg[1]; 438 396 else 439 397 params->trace_output = "timerlat_trace.txt"; 398 + break; 399 + case '0': /* trigger */ 400 + if (params->events) { 401 + retval = trace_event_add_trigger(params->events, optarg); 402 + if (retval) { 403 + err_msg("Error adding trigger %s\n", optarg); 404 + exit(EXIT_FAILURE); 405 + } 406 + } else { 407 + timerlat_top_usage("--trigger requires a previous -e\n"); 408 + } 409 + break; 410 + case '1': /* filter */ 411 + if (params->events) { 412 + retval = trace_event_add_filter(params->events, optarg); 413 + if (retval) { 414 + err_msg("Error adding filter %s\n", optarg); 415 + exit(EXIT_FAILURE); 416 + } 417 + } else { 418 + timerlat_top_usage("--filter requires a previous -e\n"); 419 + } 420 + break; 421 + case '2': /* dma-latency */ 422 + params->dma_latency = get_llong_from_str(optarg); 423 + if (params->dma_latency < 0 || params->dma_latency > 10000) { 424 + err_msg("--dma-latency needs to be >= 0 and < 10000"); 425 + exit(EXIT_FAILURE); 426 + } 440 427 break; 441 428 default: 442 429 timerlat_top_usage("Invalid option"); ··· 595 524 struct osnoise_tool *record = NULL; 596 525 struct osnoise_tool *top = NULL; 597 526 struct trace_instance *trace; 527 + int dma_latency_fd = -1; 598 528 int return_value = 1; 599 529 int retval; 600 530 ··· 631 559 } 632 560 } 633 561 562 + if (params->dma_latency >= 0) { 563 + dma_latency_fd = set_cpu_dma_latency(params->dma_latency); 564 + if (dma_latency_fd < 0) { 565 + err_msg("Could not set /dev/cpu_dma_latency.\n"); 566 + goto out_top; 567 + } 568 + } 569 + 634 570 trace_instance_start(trace); 635 571 636 572 if (params->trace_output) { ··· 647 567 err_msg("Failed to enable the trace instance\n"); 648 568 goto out_top; 649 569 } 570 + 571 + if (params->events) { 572 + retval = trace_events_enable(&record->trace, params->events); 573 + if (retval) 574 + goto out_top; 575 + } 576 + 650 577 trace_instance_start(&record->trace); 651 578 } 652 579 ··· 677 590 if (!params->quiet) 678 591 timerlat_print_stats(params, top); 679 592 680 - if (!tracefs_trace_is_on(trace->inst)) 593 + if (trace_is_off(&top->trace, &record->trace)) 681 594 break; 682 595 683 - }; 596 + } 684 597 685 598 timerlat_print_stats(params, top); 686 599 687 600 return_value = 0; 688 601 689 - if (!tracefs_trace_is_on(trace->inst)) { 602 + if (trace_is_off(&top->trace, &record->trace)) { 690 603 printf("rtla timelat hit stop tracing\n"); 691 604 if (params->trace_output) { 692 605 printf(" Saving trace to %s\n", params->trace_output); ··· 695 608 } 696 609 697 610 out_top: 611 + if (dma_latency_fd >= 0) 612 + close(dma_latency_fd); 613 + trace_events_destroy(&record->trace, params->events); 614 + params->events = NULL; 698 615 timerlat_free_top(top->data); 699 616 osnoise_destroy_tool(record); 700 617 osnoise_destroy_tool(top);
+345
tools/tracing/rtla/src/trace.c
··· 190 190 { 191 191 return tracefs_trace_on(trace->inst); 192 192 } 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 + }
+23
tools/tracing/rtla/src/trace.h
··· 2 2 #include <tracefs.h> 3 3 #include <stddef.h> 4 4 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 + 5 16 struct trace_instance { 6 17 struct tracefs_instance *inst; 7 18 struct tep_handle *tep; ··· 36 25 int save_trace_to_file(struct tracefs_instance *inst, const char *filename); 37 26 int collect_registered_events(struct tep_event *tep, struct tep_record *record, 38 27 int cpu, void *context); 28 + 29 + struct trace_events *trace_event_alloc(const char *event_string); 30 + void trace_events_disable(struct trace_instance *instance, 31 + struct trace_events *events); 32 + void trace_events_destroy(struct trace_instance *instance, 33 + struct trace_events *events); 34 + int trace_events_enable(struct trace_instance *instance, 35 + struct trace_events *events); 36 + 37 + int trace_event_add_filter(struct trace_events *event, char *filter); 38 + int trace_event_add_trigger(struct trace_events *event, char *trigger); 39 + int trace_is_off(struct trace_instance *tool, struct trace_instance *trace);
+33
tools/tracing/rtla/src/utils.c
··· 10 10 #include <unistd.h> 11 11 #include <ctype.h> 12 12 #include <errno.h> 13 + #include <fcntl.h> 13 14 #include <sched.h> 14 15 #include <stdio.h> 15 16 ··· 431 430 return -1; 432 431 } 433 432 return 0; 433 + } 434 + 435 + /* 436 + * set_cpu_dma_latency - set the /dev/cpu_dma_latecy 437 + * 438 + * This is used to reduce the exit from idle latency. The value 439 + * will be reset once the file descriptor of /dev/cpu_dma_latecy 440 + * is closed. 441 + * 442 + * Return: the /dev/cpu_dma_latecy file descriptor 443 + */ 444 + int set_cpu_dma_latency(int32_t latency) 445 + { 446 + int retval; 447 + int fd; 448 + 449 + fd = open("/dev/cpu_dma_latency", O_RDWR); 450 + if (fd < 0) { 451 + err_msg("Error opening /dev/cpu_dma_latency\n"); 452 + return -1; 453 + } 454 + 455 + retval = write(fd, &latency, 4); 456 + if (retval < 1) { 457 + err_msg("Error setting /dev/cpu_dma_latency\n"); 458 + close(fd); 459 + return -1; 460 + } 461 + 462 + debug_msg("Set /dev/cpu_dma_latency to %d\n", latency); 463 + 464 + return fd; 434 465 }
+1
tools/tracing/rtla/src/utils.h
··· 54 54 55 55 int parse_prio(char *arg, struct sched_attr *sched_param); 56 56 int set_comm_sched_attr(const char *comm, struct sched_attr *attr); 57 + int set_cpu_dma_latency(int32_t latency);