@@ -48,6 +48,7 @@ struct timerlat_top_params {
48
48
int pretty_output ;
49
49
int warmup ;
50
50
int buffer_size ;
51
+ int deepest_idle_state ;
51
52
cpu_set_t hk_cpu_set ;
52
53
struct sched_attr sched_param ;
53
54
struct trace_events * events ;
@@ -447,7 +448,7 @@ static void timerlat_top_usage(char *usage)
447
448
"" ,
448
449
" usage: rtla timerlat [top] [-h] [-q] [-a us] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] \\" ,
449
450
" [[-t[file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] [-H cpu-list]\\" ,
450
- " [-P priority] [--dma-latency us] [--aa-only us] [-C[=cgroup_name]] [-u|-k] [--warm-up s]" ,
451
+ " [-P priority] [--dma-latency us] [--aa-only us] [-C[=cgroup_name]] [-u|-k] [--warm-up s] [--deepest-idle-state n] " ,
451
452
"" ,
452
453
" -h/--help: print this menu" ,
453
454
" -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit" ,
@@ -481,6 +482,7 @@ static void timerlat_top_usage(char *usage)
481
482
" -U/--user-load: enable timerlat for user-defined user-space workload" ,
482
483
" --warm-up s: let the workload run for s seconds before collecting data" ,
483
484
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB" ,
485
+ " --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency" ,
484
486
NULL ,
485
487
};
486
488
@@ -518,6 +520,9 @@ static struct timerlat_top_params
518
520
/* disabled by default */
519
521
params -> dma_latency = -1 ;
520
522
523
+ /* disabled by default */
524
+ params -> deepest_idle_state = -2 ;
525
+
521
526
/* display data in microseconds */
522
527
params -> output_divisor = 1000 ;
523
528
@@ -550,6 +555,7 @@ static struct timerlat_top_params
550
555
{"aa-only" , required_argument , 0 , '5' },
551
556
{"warm-up" , required_argument , 0 , '6' },
552
557
{"trace-buffer-size" , required_argument , 0 , '7' },
558
+ {"deepest-idle-state" , required_argument , 0 , '8' },
553
559
{0 , 0 , 0 , 0 }
554
560
};
555
561
@@ -726,6 +732,9 @@ static struct timerlat_top_params
726
732
case '7' :
727
733
params -> buffer_size = get_llong_from_str (optarg );
728
734
break ;
735
+ case '8' :
736
+ params -> deepest_idle_state = get_llong_from_str (optarg );
737
+ break ;
729
738
default :
730
739
timerlat_top_usage ("Invalid option" );
731
740
}
@@ -922,6 +931,7 @@ int timerlat_top_main(int argc, char *argv[])
922
931
int return_value = 1 ;
923
932
char * max_lat ;
924
933
int retval ;
934
+ int nr_cpus , i ;
925
935
926
936
params = timerlat_top_parse_args (argc , argv );
927
937
if (!params )
@@ -971,6 +981,28 @@ int timerlat_top_main(int argc, char *argv[])
971
981
}
972
982
}
973
983
984
+ if (params -> deepest_idle_state >= -1 ) {
985
+ if (!have_libcpupower_support ()) {
986
+ err_msg ("rtla built without libcpupower, --deepest-idle-state is not supported\n" );
987
+ goto out_free ;
988
+ }
989
+
990
+ nr_cpus = sysconf (_SC_NPROCESSORS_CONF );
991
+
992
+ for (i = 0 ; i < nr_cpus ; i ++ ) {
993
+ if (params -> cpus && !CPU_ISSET (i , & params -> monitored_cpus ))
994
+ continue ;
995
+ if (save_cpu_idle_disable_state (i ) < 0 ) {
996
+ err_msg ("Could not save cpu idle state.\n" );
997
+ goto out_free ;
998
+ }
999
+ if (set_deepest_cpu_idle_state (i , params -> deepest_idle_state ) < 0 ) {
1000
+ err_msg ("Could not set deepest cpu idle state.\n" );
1001
+ goto out_free ;
1002
+ }
1003
+ }
1004
+ }
1005
+
974
1006
if (params -> trace_output ) {
975
1007
record = osnoise_init_trace_tool ("timerlat" );
976
1008
if (!record ) {
@@ -1125,6 +1157,13 @@ int timerlat_top_main(int argc, char *argv[])
1125
1157
timerlat_aa_destroy ();
1126
1158
if (dma_latency_fd >= 0 )
1127
1159
close (dma_latency_fd );
1160
+ if (params -> deepest_idle_state >= -1 ) {
1161
+ for (i = 0 ; i < nr_cpus ; i ++ ) {
1162
+ if (params -> cpus && !CPU_ISSET (i , & params -> monitored_cpus ))
1163
+ continue ;
1164
+ restore_cpu_idle_disable_state (i );
1165
+ }
1166
+ }
1128
1167
trace_events_destroy (& record -> trace , params -> events );
1129
1168
params -> events = NULL ;
1130
1169
out_free :
@@ -1134,6 +1173,7 @@ int timerlat_top_main(int argc, char *argv[])
1134
1173
osnoise_destroy_tool (record );
1135
1174
osnoise_destroy_tool (top );
1136
1175
free (params );
1176
+ free_cpu_idle_disable_states ();
1137
1177
out_exit :
1138
1178
exit (return_value );
1139
1179
}
0 commit comments