@@ -48,6 +48,7 @@ struct timerlat_top_params {
4848 int pretty_output ;
4949 int warmup ;
5050 int buffer_size ;
51+ int deepest_idle_state ;
5152 cpu_set_t hk_cpu_set ;
5253 struct sched_attr sched_param ;
5354 struct trace_events * events ;
@@ -447,7 +448,7 @@ static void timerlat_top_usage(char *usage)
447448 "" ,
448449 " usage: rtla timerlat [top] [-h] [-q] [-a us] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] \\" ,
449450 " [[-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] " ,
451452 "" ,
452453 " -h/--help: print this menu" ,
453454 " -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)
481482 " -U/--user-load: enable timerlat for user-defined user-space workload" ,
482483 " --warm-up s: let the workload run for s seconds before collecting data" ,
483484 " --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" ,
484486 NULL ,
485487 };
486488
@@ -518,6 +520,9 @@ static struct timerlat_top_params
518520 /* disabled by default */
519521 params -> dma_latency = -1 ;
520522
523+ /* disabled by default */
524+ params -> deepest_idle_state = -2 ;
525+
521526 /* display data in microseconds */
522527 params -> output_divisor = 1000 ;
523528
@@ -550,6 +555,7 @@ static struct timerlat_top_params
550555 {"aa-only" , required_argument , 0 , '5' },
551556 {"warm-up" , required_argument , 0 , '6' },
552557 {"trace-buffer-size" , required_argument , 0 , '7' },
558+ {"deepest-idle-state" , required_argument , 0 , '8' },
553559 {0 , 0 , 0 , 0 }
554560 };
555561
@@ -726,6 +732,9 @@ static struct timerlat_top_params
726732 case '7' :
727733 params -> buffer_size = get_llong_from_str (optarg );
728734 break ;
735+ case '8' :
736+ params -> deepest_idle_state = get_llong_from_str (optarg );
737+ break ;
729738 default :
730739 timerlat_top_usage ("Invalid option" );
731740 }
@@ -922,6 +931,7 @@ int timerlat_top_main(int argc, char *argv[])
922931 int return_value = 1 ;
923932 char * max_lat ;
924933 int retval ;
934+ int nr_cpus , i ;
925935
926936 params = timerlat_top_parse_args (argc , argv );
927937 if (!params )
@@ -971,6 +981,28 @@ int timerlat_top_main(int argc, char *argv[])
971981 }
972982 }
973983
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+
9741006 if (params -> trace_output ) {
9751007 record = osnoise_init_trace_tool ("timerlat" );
9761008 if (!record ) {
@@ -1125,6 +1157,13 @@ int timerlat_top_main(int argc, char *argv[])
11251157 timerlat_aa_destroy ();
11261158 if (dma_latency_fd >= 0 )
11271159 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+ }
11281167 trace_events_destroy (& record -> trace , params -> events );
11291168 params -> events = NULL ;
11301169out_free :
@@ -1134,6 +1173,7 @@ int timerlat_top_main(int argc, char *argv[])
11341173 osnoise_destroy_tool (record );
11351174 osnoise_destroy_tool (top );
11361175 free (params );
1176+ free_cpu_idle_disable_states ();
11371177out_exit :
11381178 exit (return_value );
11391179}
0 commit comments