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

rtla/timerlat: Add action on end feature

Implement actions on end next to actions on threshold. A new option,
--on-end is added, parallel to --on-threshold. Instead of being
executed whenever a latency threshold is reached, it is executed at the
end of the measurement.

For example:

$ rtla timerlat hist -d 5s --on-end trace

will save the trace output at the end.

All actions supported by --on-threshold are also supported by --on-end,
except for continue, which does nothing with --on-end.

Cc: John Kacur <jkacur@redhat.com>
Cc: Luis Goncalves <lgoncalv@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Chang Yin <cyin@redhat.com>
Cc: Costa Shulyupin <costa.shul@redhat.com>
Cc: Crystal Wood <crwood@redhat.com>
Cc: Gabriele Monaco <gmonaco@redhat.com>
Link: https://lore.kernel.org/20250626123405.1496931-6-tglozar@redhat.com
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

Tomas Glozar and committed by
Steven Rostedt (Google)
3aadb65d 8d933d5c

+65 -29
+4 -1
tools/tracing/rtla/src/timerlat.h
··· 48 48 struct sched_attr sched_param; 49 49 struct trace_events *events; 50 50 enum timerlat_tracing_mode mode; 51 - struct actions actions; 51 + 52 + struct actions threshold_actions; 53 + struct actions end_actions; 54 + 52 55 union { 53 56 struct { 54 57 /* top only */
+30 -14
tools/tracing/rtla/src/timerlat_hist.c
··· 758 758 " --trace-buffer-size kB: set the per-cpu trace buffer size in kB", 759 759 " --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency", 760 760 " --on-threshold <action>: define action to be executed at latency threshold, multiple are allowed", 761 + " --on-end <action>: define action to be executed at measurement end, multiple are allowed", 761 762 NULL, 762 763 }; 763 764 ··· 794 793 if (!params) 795 794 exit(1); 796 795 797 - actions_init(&params->actions); 796 + actions_init(&params->threshold_actions); 797 + actions_init(&params->end_actions); 798 798 799 799 /* disabled by default */ 800 800 params->dma_latency = -1; ··· 848 846 {"trace-buffer-size", required_argument, 0, '\3'}, 849 847 {"deepest-idle-state", required_argument, 0, '\4'}, 850 848 {"on-threshold", required_argument, 0, '\5'}, 849 + {"on-end", required_argument, 0, '\6'}, 851 850 {0, 0, 0, 0} 852 851 }; 853 852 ··· 1041 1038 params->deepest_idle_state = get_llong_from_str(optarg); 1042 1039 break; 1043 1040 case '\5': 1044 - retval = actions_parse(&params->actions, optarg); 1041 + retval = actions_parse(&params->threshold_actions, optarg); 1042 + if (retval) { 1043 + err_msg("Invalid action %s\n", optarg); 1044 + exit(EXIT_FAILURE); 1045 + } 1046 + break; 1047 + case '\6': 1048 + retval = actions_parse(&params->end_actions, optarg); 1045 1049 if (retval) { 1046 1050 err_msg("Invalid action %s\n", optarg); 1047 1051 exit(EXIT_FAILURE); ··· 1060 1050 } 1061 1051 1062 1052 if (trace_output) 1063 - actions_add_trace_output(&params->actions, trace_output); 1053 + actions_add_trace_output(&params->threshold_actions, trace_output); 1064 1054 1065 1055 if (geteuid()) { 1066 1056 err_msg("rtla needs root permission\n"); ··· 1087 1077 * mixed mode 1088 1078 */ 1089 1079 if (params->mode == TRACING_MODE_BPF && 1090 - (params->actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa)) 1080 + (params->threshold_actions.present[ACTION_TRACE_OUTPUT] || 1081 + params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa)) 1091 1082 params->mode = TRACING_MODE_MIXED; 1092 1083 1093 1084 return params; ··· 1281 1270 } 1282 1271 } 1283 1272 1284 - if (params->actions.present[ACTION_TRACE_OUTPUT]) { 1273 + if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] || 1274 + params->end_actions.present[ACTION_TRACE_OUTPUT]) { 1285 1275 record = osnoise_init_trace_tool("timerlat"); 1286 1276 if (!record) { 1287 1277 err_msg("Failed to enable the trace instance\n"); 1288 1278 goto out_free; 1289 1279 } 1290 - params->actions.trace_output_inst = record->trace.inst; 1280 + params->threshold_actions.trace_output_inst = record->trace.inst; 1281 + params->end_actions.trace_output_inst = record->trace.inst; 1291 1282 1292 1283 if (params->events) { 1293 1284 retval = trace_events_enable(&record->trace, params->events); ··· 1355 1342 * tracing while enabling other instances. The trace instance is the 1356 1343 * one with most valuable information. 1357 1344 */ 1358 - if (params->actions.present[ACTION_TRACE_OUTPUT]) 1345 + if (record) 1359 1346 trace_instance_start(&record->trace); 1360 1347 if (!params->no_aa) 1361 1348 trace_instance_start(&aa->trace); ··· 1388 1375 } 1389 1376 1390 1377 if (osnoise_trace_is_off(tool, record)) { 1391 - actions_perform(&params->actions); 1378 + actions_perform(&params->threshold_actions); 1392 1379 1393 - if (!params->actions.continue_flag) 1380 + if (!params->threshold_actions.continue_flag) 1394 1381 /* continue flag not set, break */ 1395 1382 break; 1396 1383 1397 1384 /* continue action reached, re-enable tracing */ 1398 - if (params->actions.present[ACTION_TRACE_OUTPUT]) 1385 + if (record) 1399 1386 trace_instance_start(&record->trace); 1400 1387 if (!params->no_aa) 1401 1388 trace_instance_start(&aa->trace); ··· 1416 1403 1417 1404 if (!stop_tracing) { 1418 1405 /* Threshold overflow, perform actions on threshold */ 1419 - actions_perform(&params->actions); 1406 + actions_perform(&params->threshold_actions); 1420 1407 1421 - if (!params->actions.continue_flag) 1408 + if (!params->threshold_actions.continue_flag) 1422 1409 /* continue flag not set, break */ 1423 1410 break; 1424 1411 1425 1412 /* continue action reached, re-enable tracing */ 1426 - if (params->actions.present[ACTION_TRACE_OUTPUT]) 1413 + if (record) 1427 1414 trace_instance_start(&record->trace); 1428 1415 if (!params->no_aa) 1429 1416 trace_instance_start(&aa->trace); ··· 1447 1434 } 1448 1435 1449 1436 timerlat_print_stats(params, tool); 1437 + 1438 + actions_perform(&params->end_actions); 1450 1439 1451 1440 return_value = PASSED; 1452 1441 ··· 1479 1464 osnoise_destroy_tool(aa); 1480 1465 osnoise_destroy_tool(record); 1481 1466 osnoise_destroy_tool(tool); 1482 - actions_destroy(&params->actions); 1467 + actions_destroy(&params->threshold_actions); 1468 + actions_destroy(&params->end_actions); 1483 1469 if (params->mode != TRACING_MODE_TRACEFS) 1484 1470 timerlat_bpf_destroy(); 1485 1471 free(params);
+31 -14
tools/tracing/rtla/src/timerlat_top.c
··· 517 517 " --trace-buffer-size kB: set the per-cpu trace buffer size in kB", 518 518 " --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency", 519 519 " --on-threshold <action>: define action to be executed at latency threshold, multiple are allowed", 520 + " --on-end: define action to be executed at measurement end, multiple are allowed", 520 521 NULL, 521 522 }; 522 523 ··· 553 552 if (!params) 554 553 exit(1); 555 554 556 - actions_init(&params->actions); 555 + actions_init(&params->threshold_actions); 556 + actions_init(&params->end_actions); 557 557 558 558 /* disabled by default */ 559 559 params->dma_latency = -1; ··· 599 597 {"trace-buffer-size", required_argument, 0, '7'}, 600 598 {"deepest-idle-state", required_argument, 0, '8'}, 601 599 {"on-threshold", required_argument, 0, '9'}, 600 + {"on-end", required_argument, 0, '\1'}, 602 601 {0, 0, 0, 0} 603 602 }; 604 603 ··· 626 623 627 624 /* set trace */ 628 625 trace_output = "timerlat_trace.txt"; 626 + 629 627 break; 630 628 case '5': 631 629 /* it is here because it is similar to -a */ ··· 780 776 params->deepest_idle_state = get_llong_from_str(optarg); 781 777 break; 782 778 case '9': 783 - retval = actions_parse(&params->actions, optarg); 779 + retval = actions_parse(&params->threshold_actions, optarg); 780 + if (retval) { 781 + err_msg("Invalid action %s\n", optarg); 782 + exit(EXIT_FAILURE); 783 + } 784 + break; 785 + case '\1': 786 + retval = actions_parse(&params->end_actions, optarg); 784 787 if (retval) { 785 788 err_msg("Invalid action %s\n", optarg); 786 789 exit(EXIT_FAILURE); ··· 799 788 } 800 789 801 790 if (trace_output) 802 - actions_add_trace_output(&params->actions, trace_output); 791 + actions_add_trace_output(&params->threshold_actions, trace_output); 803 792 804 793 if (geteuid()) { 805 794 err_msg("rtla needs root permission\n"); ··· 823 812 * mixed mode 824 813 */ 825 814 if (params->mode == TRACING_MODE_BPF && 826 - (params->actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa)) 815 + (params->threshold_actions.present[ACTION_TRACE_OUTPUT] || 816 + params->end_actions.present[ACTION_TRACE_OUTPUT] || !params->no_aa)) 827 817 params->mode = TRACING_MODE_MIXED; 828 818 829 819 return params; ··· 946 934 timerlat_print_stats(params, top); 947 935 948 936 if (osnoise_trace_is_off(top, record)) { 949 - actions_perform(&params->actions); 937 + actions_perform(&params->threshold_actions); 950 938 951 - if (!params->actions.continue_flag) 939 + if (!params->threshold_actions.continue_flag) 952 940 /* continue flag not set, break */ 953 941 break; 954 942 955 943 /* continue action reached, re-enable tracing */ 956 - if (params->actions.present[ACTION_TRACE_OUTPUT]) 944 + if (record) 957 945 trace_instance_start(&record->trace); 958 946 if (!params->no_aa) 959 947 trace_instance_start(&aa->trace); ··· 1005 993 1006 994 if (wait_retval == 1) { 1007 995 /* Stopping requested by tracer */ 1008 - actions_perform(&params->actions); 996 + actions_perform(&params->threshold_actions); 1009 997 1010 - if (!params->actions.continue_flag) 998 + if (!params->threshold_actions.continue_flag) 1011 999 /* continue flag not set, break */ 1012 1000 break; 1013 1001 1014 1002 /* continue action reached, re-enable tracing */ 1015 - if (params->actions.present[ACTION_TRACE_OUTPUT]) 1003 + if (record) 1016 1004 trace_instance_start(&record->trace); 1017 1005 if (!params->no_aa) 1018 1006 trace_instance_start(&aa->trace); ··· 1140 1128 } 1141 1129 } 1142 1130 1143 - if (params->actions.present[ACTION_TRACE_OUTPUT]) { 1131 + if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] || 1132 + params->end_actions.present[ACTION_TRACE_OUTPUT]) { 1144 1133 record = osnoise_init_trace_tool("timerlat"); 1145 1134 if (!record) { 1146 1135 err_msg("Failed to enable the trace instance\n"); 1147 1136 goto out_free; 1148 1137 } 1149 - params->actions.trace_output_inst = record->trace.inst; 1138 + params->threshold_actions.trace_output_inst = record->trace.inst; 1139 + params->end_actions.trace_output_inst = record->trace.inst; 1150 1140 1151 1141 if (params->events) { 1152 1142 retval = trace_events_enable(&record->trace, params->events); ··· 1215 1201 * tracing while enabling other instances. The trace instance is the 1216 1202 * one with most valuable information. 1217 1203 */ 1218 - if (params->actions.present[ACTION_TRACE_OUTPUT]) 1204 + if (record) 1219 1205 trace_instance_start(&record->trace); 1220 1206 if (!params->no_aa) 1221 1207 trace_instance_start(&aa->trace); ··· 1249 1235 } 1250 1236 1251 1237 timerlat_print_stats(params, top); 1238 + 1239 + actions_perform(&params->end_actions); 1252 1240 1253 1241 return_value = PASSED; 1254 1242 ··· 1292 1276 osnoise_destroy_tool(aa); 1293 1277 osnoise_destroy_tool(record); 1294 1278 osnoise_destroy_tool(top); 1295 - actions_destroy(&params->actions); 1279 + actions_destroy(&params->threshold_actions); 1280 + actions_destroy(&params->end_actions); 1296 1281 if (params->mode != TRACING_MODE_TRACEFS) 1297 1282 timerlat_bpf_destroy(); 1298 1283 free(params);