Skip to content

Commit e67e0ef

Browse files
rtla/utils: Add idle state disabling via libcpupower
JIRA: https://issues.redhat.com/browse/RHEL-40744 commit 083d29d Author: Tomas Glozar <tglozar@redhat.com> Date: Thu Oct 17 16:09:11 2024 +0200 rtla/utils: Add idle state disabling via libcpupower Add functions to utils.c to disable idle states through functions of libcpupower. This will serve as the basis for disabling idle states per cpu when running timerlat. Link: https://lore.kernel.org/20241017140914.3200454-4-tglozar@redhat.com Signed-off-by: Tomas Glozar <tglozar@redhat.com> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Tomas Glozar <tglozar@redhat.com>
1 parent dcefc14 commit e67e0ef

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed

tools/tracing/rtla/src/utils.c

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
*/
55

66
#define _GNU_SOURCE
7+
#ifdef HAVE_LIBCPUPOWER_SUPPORT
8+
#include <cpuidle.h>
9+
#endif /* HAVE_LIBCPUPOWER_SUPPORT */
710
#include <dirent.h>
811
#include <stdarg.h>
912
#include <stdlib.h>
@@ -519,6 +522,153 @@ int set_cpu_dma_latency(int32_t latency)
519522
return fd;
520523
}
521524

525+
#ifdef HAVE_LIBCPUPOWER_SUPPORT
526+
static unsigned int **saved_cpu_idle_disable_state;
527+
static size_t saved_cpu_idle_disable_state_alloc_ctr;
528+
529+
/*
530+
* save_cpu_idle_state_disable - save disable for all idle states of a cpu
531+
*
532+
* Saves the current disable of all idle states of a cpu, to be subsequently
533+
* restored via restore_cpu_idle_disable_state.
534+
*
535+
* Return: idle state count on success, negative on error
536+
*/
537+
int save_cpu_idle_disable_state(unsigned int cpu)
538+
{
539+
unsigned int nr_states;
540+
unsigned int state;
541+
int disabled;
542+
int nr_cpus;
543+
544+
nr_states = cpuidle_state_count(cpu);
545+
546+
if (nr_states == 0)
547+
return 0;
548+
549+
if (saved_cpu_idle_disable_state == NULL) {
550+
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
551+
saved_cpu_idle_disable_state = calloc(nr_cpus, sizeof(unsigned int *));
552+
if (!saved_cpu_idle_disable_state)
553+
return -1;
554+
}
555+
556+
saved_cpu_idle_disable_state[cpu] = calloc(nr_states, sizeof(unsigned int));
557+
if (!saved_cpu_idle_disable_state[cpu])
558+
return -1;
559+
saved_cpu_idle_disable_state_alloc_ctr++;
560+
561+
for (state = 0; state < nr_states; state++) {
562+
disabled = cpuidle_is_state_disabled(cpu, state);
563+
if (disabled < 0)
564+
return disabled;
565+
saved_cpu_idle_disable_state[cpu][state] = disabled;
566+
}
567+
568+
return nr_states;
569+
}
570+
571+
/*
572+
* restore_cpu_idle_disable_state - restore disable for all idle states of a cpu
573+
*
574+
* Restores the current disable state of all idle states of a cpu that was
575+
* previously saved by save_cpu_idle_disable_state.
576+
*
577+
* Return: idle state count on success, negative on error
578+
*/
579+
int restore_cpu_idle_disable_state(unsigned int cpu)
580+
{
581+
unsigned int nr_states;
582+
unsigned int state;
583+
int disabled;
584+
int result;
585+
586+
nr_states = cpuidle_state_count(cpu);
587+
588+
if (nr_states == 0)
589+
return 0;
590+
591+
if (!saved_cpu_idle_disable_state)
592+
return -1;
593+
594+
for (state = 0; state < nr_states; state++) {
595+
if (!saved_cpu_idle_disable_state[cpu])
596+
return -1;
597+
disabled = saved_cpu_idle_disable_state[cpu][state];
598+
result = cpuidle_state_disable(cpu, state, disabled);
599+
if (result < 0)
600+
return result;
601+
}
602+
603+
free(saved_cpu_idle_disable_state[cpu]);
604+
saved_cpu_idle_disable_state[cpu] = NULL;
605+
saved_cpu_idle_disable_state_alloc_ctr--;
606+
if (saved_cpu_idle_disable_state_alloc_ctr == 0) {
607+
free(saved_cpu_idle_disable_state);
608+
saved_cpu_idle_disable_state = NULL;
609+
}
610+
611+
return nr_states;
612+
}
613+
614+
/*
615+
* free_cpu_idle_disable_states - free saved idle state disable for all cpus
616+
*
617+
* Frees the memory used for storing cpu idle state disable for all cpus
618+
* and states.
619+
*
620+
* Normally, the memory is freed automatically in
621+
* restore_cpu_idle_disable_state; this is mostly for cleaning up after an
622+
* error.
623+
*/
624+
void free_cpu_idle_disable_states(void)
625+
{
626+
int cpu;
627+
int nr_cpus;
628+
629+
if (!saved_cpu_idle_disable_state)
630+
return;
631+
632+
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
633+
634+
for (cpu = 0; cpu < nr_cpus; cpu++) {
635+
free(saved_cpu_idle_disable_state[cpu]);
636+
saved_cpu_idle_disable_state[cpu] = NULL;
637+
}
638+
639+
free(saved_cpu_idle_disable_state);
640+
saved_cpu_idle_disable_state = NULL;
641+
}
642+
643+
/*
644+
* set_deepest_cpu_idle_state - limit idle state of cpu
645+
*
646+
* Disables all idle states deeper than the one given in
647+
* deepest_state (assuming states with higher number are deeper).
648+
*
649+
* This is used to reduce the exit from idle latency. Unlike
650+
* set_cpu_dma_latency, it can disable idle states per cpu.
651+
*
652+
* Return: idle state count on success, negative on error
653+
*/
654+
int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int deepest_state)
655+
{
656+
unsigned int nr_states;
657+
unsigned int state;
658+
int result;
659+
660+
nr_states = cpuidle_state_count(cpu);
661+
662+
for (state = deepest_state + 1; state < nr_states; state++) {
663+
result = cpuidle_state_disable(cpu, state, 1);
664+
if (result < 0)
665+
return result;
666+
}
667+
668+
return nr_states;
669+
}
670+
#endif /* HAVE_LIBCPUPOWER_SUPPORT */
671+
522672
#define _STR(x) #x
523673
#define STR(x) _STR(x)
524674

tools/tracing/rtla/src/utils.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,19 @@ int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr);
6464
int set_comm_cgroup(const char *comm_prefix, const char *cgroup);
6565
int set_pid_cgroup(pid_t pid, const char *cgroup);
6666
int set_cpu_dma_latency(int32_t latency);
67+
#ifdef HAVE_LIBCPUPOWER_SUPPORT
68+
int save_cpu_idle_disable_state(unsigned int cpu);
69+
int restore_cpu_idle_disable_state(unsigned int cpu);
70+
void free_cpu_idle_disable_states(void);
71+
int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int state);
72+
static inline int have_libcpupower_support(void) { return 1; }
73+
#else
74+
static inline int save_cpu_idle_disable_state(unsigned int cpu) { return -1; }
75+
static inline int restore_cpu_idle_disable_state(unsigned int cpu) { return -1; }
76+
static inline void free_cpu_idle_disable_states(void) { }
77+
static inline int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int state) { return -1; }
78+
static inline int have_libcpupower_support(void) { return 0; }
79+
#endif /* HAVE_LIBCPUPOWER_SUPPORT */
6780
int auto_house_keeping(cpu_set_t *monitored_cpus);
6881

6982
#define ns_to_usf(x) (((double)x/1000))

0 commit comments

Comments
 (0)