* [PATCH RESEND v3 0/6] rtla: Support idle state disabling via libcpupower in timerlat
@ 2024-10-04 9:50 tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 1/6] tools/build: Add libcpupower dependency detection tglozar
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: tglozar @ 2024-10-04 9:50 UTC (permalink / raw)
To: rostedt; +Cc: linux-trace-kernel, linux-kernel, jwyatt, jkacur, Tomas Glozar
From: Tomas Glozar <tglozar@redhat.com>
rtla-timerlat allows reducing latency on wake up from idle by setting
/dev/cpu_dma_latency during the timerlat measurement. This has an effect on
the idle states of all CPUs, including those which are not used by timerlat.
Add option --deepest-idle-state that allows limiting the idle state only on cpus
where the timerlat measurement is running.
libcpupower is used to do the disabling of idle states via the corresponding
sysfs interface.
v2:
- Split patch adding dependency on libcpupower to two patches, one for
libcpupower detection and one for rtla libcpupower dependency.
- Make building against libcpupower optional. rtla will throw an error
when built without libcpupower and --deepest-idle-state is used.
- Rename option from --disable-idle-states to --deepest-idle-state and
add an argument to choose the deepest idle state the CPU is allowed to
get into. -1 can be used to disable all idle states: this is useful on
non-ACPI platforms, where idle state 0 can be an actual idle state with
an exit latency rather than a representation of an active CPU, as with the
ACPI C0 state.
Note: It is also possible to retrieve the latency for individual idle states
of a cpu by calling cpuidle_state_latency. This could be used to implement
another rtla option that would take the maximum latency, like --dma-latency
does, and which would only take effect on CPUs used by timerlat.
My opinion is that this proposed feature should not replace either
--dma-latency nor --deepest-idle-state. For the former, there might be
systems which have /dev/cpu_dma_latency but don't have a cpuidle
implementation; for the latter, in many cases the user will want to set
the idle state rather than the latency itself.
v3:
- Remove unneeded NULL check before free in restore_cpu_idle_disable_state
and free_cpu_idle_disable_states.
- Check for calloc() returning NULL in save_cpu_idle_disable_state.
- Check for saved_cpu_idle_disable_state existing in
restore_cpu_idle_disable_state.
- Implement dummy functions for libcpupower functionality if libcpupower is
not present during build. That allows libcpupower presence to be checked
through a special function at one place instead of using several #ifdefs.
- Only call sysconf() once when iterating through all CPUs. Note that there
are a few instances in the original code which keep on calling sysconf()
multiple times; fixing that is for another patch.
Tomas Glozar (6):
tools/build: Add libcpupower dependency detection
rtla: Add optional dependency on libcpupower
rtla/utils: Add idle state disabling via libcpupower
rtla/timerlat: Add --deepest-idle-state for top
rtla/timerlat: Add --deepest-idle-state for hist
rtla: Documentation: Mention --deepest-idle-state
.../tools/rtla/common_timerlat_options.rst | 8 +
tools/build/Makefile.feature | 1 +
tools/build/feature/Makefile | 4 +
tools/tracing/rtla/Makefile | 2 +
tools/tracing/rtla/Makefile.config | 10 ++
tools/tracing/rtla/README.txt | 4 +
tools/tracing/rtla/src/timerlat_hist.c | 42 ++++-
tools/tracing/rtla/src/timerlat_top.c | 42 ++++-
tools/tracing/rtla/src/utils.c | 150 ++++++++++++++++++
tools/tracing/rtla/src/utils.h | 13 ++
10 files changed, 274 insertions(+), 2 deletions(-)
--
2.46.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RESEND v3 1/6] tools/build: Add libcpupower dependency detection
2024-10-04 9:50 [PATCH RESEND v3 0/6] rtla: Support idle state disabling via libcpupower in timerlat tglozar
@ 2024-10-04 9:50 ` tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 2/6] rtla: Add optional dependency on libcpupower tglozar
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: tglozar @ 2024-10-04 9:50 UTC (permalink / raw)
To: rostedt; +Cc: linux-trace-kernel, linux-kernel, jwyatt, jkacur, Tomas Glozar
From: Tomas Glozar <tglozar@redhat.com>
Add the ability to detect the presence of libcpupower on a system to
the Makefiles in tools/build.
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
tools/build/Makefile.feature | 1 +
tools/build/feature/Makefile | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 1e2ab148d5db..e4fb0a1fbddf 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -53,6 +53,7 @@ FEATURE_TESTS_BASIC := \
libslang-include-subdir \
libtraceevent \
libtracefs \
+ libcpupower \
libcrypto \
libunwind \
pthread-attr-setaffinity-np \
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 489cbed7e82a..c4a78333660b 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -38,6 +38,7 @@ FILES= \
test-libslang.bin \
test-libslang-include-subdir.bin \
test-libtraceevent.bin \
+ test-libcpupower.bin \
test-libtracefs.bin \
test-libcrypto.bin \
test-libunwind.bin \
@@ -212,6 +213,9 @@ $(OUTPUT)test-libslang-include-subdir.bin:
$(OUTPUT)test-libtraceevent.bin:
$(BUILD) -ltraceevent
+$(OUTPUT)test-libcpupower.bin:
+ $(BUILD) -lcpupower
+
$(OUTPUT)test-libtracefs.bin:
$(BUILD) $(shell $(PKG_CONFIG) --cflags libtracefs 2>/dev/null) -ltracefs
--
2.46.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RESEND v3 2/6] rtla: Add optional dependency on libcpupower
2024-10-04 9:50 [PATCH RESEND v3 0/6] rtla: Support idle state disabling via libcpupower in timerlat tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 1/6] tools/build: Add libcpupower dependency detection tglozar
@ 2024-10-04 9:50 ` tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 3/6] rtla/utils: Add idle state disabling via libcpupower tglozar
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: tglozar @ 2024-10-04 9:50 UTC (permalink / raw)
To: rostedt; +Cc: linux-trace-kernel, linux-kernel, jwyatt, jkacur, Tomas Glozar
From: Tomas Glozar <tglozar@redhat.com>
If libcpupower is present, set HAVE_LIBCPUPOWER_SUPPORT macro to allow
features depending on libcpupower in rtla.
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
tools/tracing/rtla/Makefile | 2 ++
tools/tracing/rtla/Makefile.config | 10 ++++++++++
2 files changed, 12 insertions(+)
diff --git a/tools/tracing/rtla/Makefile b/tools/tracing/rtla/Makefile
index b5878be36125..a6a7dee16622 100644
--- a/tools/tracing/rtla/Makefile
+++ b/tools/tracing/rtla/Makefile
@@ -32,8 +32,10 @@ DOCSRC := ../../../Documentation/tools/rtla/
FEATURE_TESTS := libtraceevent
FEATURE_TESTS += libtracefs
+FEATURE_TESTS += libcpupower
FEATURE_DISPLAY := libtraceevent
FEATURE_DISPLAY += libtracefs
+FEATURE_DISPLAY += libcpupower
ifeq ($(V),1)
Q =
diff --git a/tools/tracing/rtla/Makefile.config b/tools/tracing/rtla/Makefile.config
index 0b7ecfb30d19..5f6f537c9728 100644
--- a/tools/tracing/rtla/Makefile.config
+++ b/tools/tracing/rtla/Makefile.config
@@ -42,6 +42,16 @@ else
$(info libtracefs is missing. Please install libtracefs-dev/libtracefs-devel)
endif
+$(call feature_check,libcpupower)
+ifeq ($(feature-libcpupower), 1)
+ $(call detected,CONFIG_LIBCPUPOWER)
+ $(call lib_setup,cpupower)
+ CFLAGS += -DHAVE_LIBCPUPOWER_SUPPORT
+else
+ $(info libcpupower is missing, building without --deepest-idle-state support.)
+ $(info Please install libcpupower-dev/kernel-tools-libs-devel)
+endif
+
ifeq ($(STOP_ERROR),1)
$(error Please, check the errors above.)
endif
--
2.46.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RESEND v3 3/6] rtla/utils: Add idle state disabling via libcpupower
2024-10-04 9:50 [PATCH RESEND v3 0/6] rtla: Support idle state disabling via libcpupower in timerlat tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 1/6] tools/build: Add libcpupower dependency detection tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 2/6] rtla: Add optional dependency on libcpupower tglozar
@ 2024-10-04 9:50 ` tglozar
2024-10-10 20:06 ` Steven Rostedt
2024-10-04 9:50 ` [PATCH RESEND v3 4/6] rtla/timerlat: Add --deepest-idle-state for top tglozar
` (2 subsequent siblings)
5 siblings, 1 reply; 9+ messages in thread
From: tglozar @ 2024-10-04 9:50 UTC (permalink / raw)
To: rostedt; +Cc: linux-trace-kernel, linux-kernel, jwyatt, jkacur, Tomas Glozar
From: Tomas Glozar <tglozar@redhat.com>
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.
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
tools/tracing/rtla/src/utils.c | 150 +++++++++++++++++++++++++++++++++
tools/tracing/rtla/src/utils.h | 13 +++
2 files changed, 163 insertions(+)
diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
index 9ac71a66840c..6ae084fdedf9 100644
--- a/tools/tracing/rtla/src/utils.c
+++ b/tools/tracing/rtla/src/utils.c
@@ -4,6 +4,9 @@
*/
#define _GNU_SOURCE
+#ifdef HAVE_LIBCPUPOWER_SUPPORT
+#include <cpuidle.h>
+#endif /* HAVE_LIBCPUPOWER_SUPPORT */
#include <dirent.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -519,6 +522,153 @@ int set_cpu_dma_latency(int32_t latency)
return fd;
}
+#ifdef HAVE_LIBCPUPOWER_SUPPORT
+static unsigned int **saved_cpu_idle_disable_state;
+static size_t saved_cpu_idle_disable_state_alloc_ctr;
+
+/*
+ * save_cpu_idle_state_disable - save disable for all idle states of a cpu
+ *
+ * Saves the current disable of all idle states of a cpu, to be subsequently
+ * restored via restore_cpu_idle_disable_state.
+ *
+ * Return: idle state count on success, negative on error
+ */
+int save_cpu_idle_disable_state(unsigned int cpu)
+{
+ unsigned int nr_states;
+ unsigned int state;
+ int disabled;
+ int nr_cpus;
+
+ nr_states = cpuidle_state_count(cpu);
+
+ if (nr_states == 0)
+ return 0;
+
+ if (saved_cpu_idle_disable_state == NULL) {
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+ saved_cpu_idle_disable_state = calloc(nr_cpus, sizeof(unsigned int *));
+ if (!saved_cpu_idle_disable_state)
+ return -1;
+ }
+
+ saved_cpu_idle_disable_state[cpu] = calloc(nr_states, sizeof(unsigned int));
+ if (!saved_cpu_idle_disable_state[cpu])
+ return -1;
+ saved_cpu_idle_disable_state_alloc_ctr++;
+
+ for (state = 0; state < nr_states; state++) {
+ disabled = cpuidle_is_state_disabled(cpu, state);
+ if (disabled < 0)
+ return disabled;
+ saved_cpu_idle_disable_state[cpu][state] = disabled;
+ }
+
+ return nr_states;
+}
+
+/*
+ * restore_cpu_idle_disable_state - restore disable for all idle states of a cpu
+ *
+ * Restores the current disable state of all idle states of a cpu that was
+ * previously saved by save_cpu_idle_disable_state.
+ *
+ * Return: idle state count on success, negative on error
+ */
+int restore_cpu_idle_disable_state(unsigned int cpu)
+{
+ unsigned int nr_states;
+ unsigned int state;
+ int disabled;
+ int result;
+
+ if (!saved_cpu_idle_disable_state)
+ return -1;
+
+ nr_states = cpuidle_state_count(cpu);
+
+ if (nr_states == 0)
+ return 0;
+
+ for (state = 0; state < nr_states; state++) {
+ if (!saved_cpu_idle_disable_state[cpu])
+ return -1;
+ disabled = saved_cpu_idle_disable_state[cpu][state];
+ result = cpuidle_state_disable(cpu, state, disabled);
+ if (result < 0)
+ return result;
+ }
+
+ free(saved_cpu_idle_disable_state[cpu]);
+ saved_cpu_idle_disable_state[cpu] = NULL;
+ saved_cpu_idle_disable_state_alloc_ctr--;
+ if (saved_cpu_idle_disable_state_alloc_ctr == 0) {
+ free(saved_cpu_idle_disable_state);
+ saved_cpu_idle_disable_state = NULL;
+ }
+
+ return nr_states;
+}
+
+/*
+ * free_cpu_idle_disable_states - free saved idle state disable for all cpus
+ *
+ * Frees the memory used for storing cpu idle state disable for all cpus
+ * and states.
+ *
+ * Normally, the memory is freed automatically in
+ * restore_cpu_idle_disable_state; this is mostly for cleaning up after an
+ * error.
+ */
+void free_cpu_idle_disable_states(void)
+{
+ int cpu;
+ int nr_cpus;
+
+ if (!saved_cpu_idle_disable_state)
+ return;
+
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+ for (cpu = 0; cpu < nr_cpus; cpu++) {
+ free(saved_cpu_idle_disable_state[cpu]);
+ saved_cpu_idle_disable_state[cpu] = NULL;
+ }
+
+ free(saved_cpu_idle_disable_state);
+ saved_cpu_idle_disable_state = NULL;
+}
+
+/*
+ * set_deepest_cpu_idle_state - limit idle state of cpu
+ *
+ * Disables all idle states deeper than the one given in
+ * deepest_state (assuming states with higher number are deeper).
+ *
+ * This is used to reduce the exit from idle latency. Unlike
+ * set_cpu_dma_latency, it can disable idle states per cpu.
+ *
+ * Return: idle state count on success, negative on error
+ */
+int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int deepest_state)
+{
+ unsigned int nr_states;
+ unsigned int state;
+ int result;
+
+ nr_states = cpuidle_state_count(cpu);
+
+ for (state = deepest_state + 1; state < nr_states; state++) {
+ result = cpuidle_state_disable(cpu, state, 1);
+ if (result < 0)
+ return result;
+ }
+
+ return nr_states;
+}
+#endif /* HAVE_LIBCPUPOWER_SUPPORT */
+
#define _STR(x) #x
#define STR(x) _STR(x)
diff --git a/tools/tracing/rtla/src/utils.h b/tools/tracing/rtla/src/utils.h
index d44513e6c66a..e439db7fc848 100644
--- a/tools/tracing/rtla/src/utils.h
+++ b/tools/tracing/rtla/src/utils.h
@@ -64,6 +64,19 @@ int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr);
int set_comm_cgroup(const char *comm_prefix, const char *cgroup);
int set_pid_cgroup(pid_t pid, const char *cgroup);
int set_cpu_dma_latency(int32_t latency);
+#ifdef HAVE_LIBCPUPOWER_SUPPORT
+int save_cpu_idle_disable_state(unsigned int cpu);
+int restore_cpu_idle_disable_state(unsigned int cpu);
+void free_cpu_idle_disable_states(void);
+int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int state);
+static inline int have_libcpupower_support(void) { return 1; }
+#else
+static inline int save_cpu_idle_disable_state(unsigned int cpu) { return -1; }
+static inline int restore_cpu_idle_disable_state(unsigned int cpu) { return -1; }
+static inline void free_cpu_idle_disable_states(void) { }
+static inline int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int state) { return -1; }
+static inline int have_libcpupower_support(void) { return 0; }
+#endif /* HAVE_LIBCPUPOWER_SUPPORT */
int auto_house_keeping(cpu_set_t *monitored_cpus);
#define ns_to_usf(x) (((double)x/1000))
--
2.46.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RESEND v3 4/6] rtla/timerlat: Add --deepest-idle-state for top
2024-10-04 9:50 [PATCH RESEND v3 0/6] rtla: Support idle state disabling via libcpupower in timerlat tglozar
` (2 preceding siblings ...)
2024-10-04 9:50 ` [PATCH RESEND v3 3/6] rtla/utils: Add idle state disabling via libcpupower tglozar
@ 2024-10-04 9:50 ` tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 5/6] rtla/timerlat: Add --deepest-idle-state for hist tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 6/6] rtla: Documentation: Mention --deepest-idle-state tglozar
5 siblings, 0 replies; 9+ messages in thread
From: tglozar @ 2024-10-04 9:50 UTC (permalink / raw)
To: rostedt; +Cc: linux-trace-kernel, linux-kernel, jwyatt, jkacur, Tomas Glozar
From: Tomas Glozar <tglozar@redhat.com>
Add option to limit deepest idle state on CPUs where timerlat is running
for the duration of the workload.
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
tools/tracing/rtla/src/timerlat_top.c | 42 ++++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/tools/tracing/rtla/src/timerlat_top.c b/tools/tracing/rtla/src/timerlat_top.c
index 8c16419fe22a..56adb86898f2 100644
--- a/tools/tracing/rtla/src/timerlat_top.c
+++ b/tools/tracing/rtla/src/timerlat_top.c
@@ -48,6 +48,7 @@ struct timerlat_top_params {
int pretty_output;
int warmup;
int buffer_size;
+ int deepest_idle_state;
cpu_set_t hk_cpu_set;
struct sched_attr sched_param;
struct trace_events *events;
@@ -447,7 +448,7 @@ static void timerlat_top_usage(char *usage)
"",
" usage: rtla timerlat [top] [-h] [-q] [-a us] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] \\",
" [[-t[file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] [-H cpu-list]\\",
- " [-P priority] [--dma-latency us] [--aa-only us] [-C[=cgroup_name]] [-u|-k] [--warm-up s]",
+ " [-P priority] [--dma-latency us] [--aa-only us] [-C[=cgroup_name]] [-u|-k] [--warm-up s] [--deepest-idle-state n]",
"",
" -h/--help: print this menu",
" -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)
" -U/--user-load: enable timerlat for user-defined user-space workload",
" --warm-up s: let the workload run for s seconds before collecting data",
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
+ " --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency",
NULL,
};
@@ -518,6 +520,9 @@ static struct timerlat_top_params
/* disabled by default */
params->dma_latency = -1;
+ /* disabled by default */
+ params->deepest_idle_state = -2;
+
/* display data in microseconds */
params->output_divisor = 1000;
@@ -550,6 +555,7 @@ static struct timerlat_top_params
{"aa-only", required_argument, 0, '5'},
{"warm-up", required_argument, 0, '6'},
{"trace-buffer-size", required_argument, 0, '7'},
+ {"deepest-idle-state", required_argument, 0, '8'},
{0, 0, 0, 0}
};
@@ -726,6 +732,9 @@ static struct timerlat_top_params
case '7':
params->buffer_size = get_llong_from_str(optarg);
break;
+ case '8':
+ params->deepest_idle_state = get_llong_from_str(optarg);
+ break;
default:
timerlat_top_usage("Invalid option");
}
@@ -922,6 +931,7 @@ int timerlat_top_main(int argc, char *argv[])
int return_value = 1;
char *max_lat;
int retval;
+ int nr_cpus, i;
params = timerlat_top_parse_args(argc, argv);
if (!params)
@@ -971,6 +981,28 @@ int timerlat_top_main(int argc, char *argv[])
}
}
+ if (params->deepest_idle_state >= -1) {
+ if (!have_libcpupower_support()) {
+ err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
+ goto out_free;
+ }
+
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+ for (i = 0; i < nr_cpus; i++) {
+ if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ continue;
+ if (save_cpu_idle_disable_state(i) < 0) {
+ err_msg("Could not save cpu idle state.\n");
+ goto out_free;
+ }
+ if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
+ err_msg("Could not set deepest cpu idle state.\n");
+ goto out_free;
+ }
+ }
+ }
+
if (params->trace_output) {
record = osnoise_init_trace_tool("timerlat");
if (!record) {
@@ -1125,6 +1157,13 @@ int timerlat_top_main(int argc, char *argv[])
timerlat_aa_destroy();
if (dma_latency_fd >= 0)
close(dma_latency_fd);
+ if (params->deepest_idle_state >= -1) {
+ for (i = 0; i < nr_cpus; i++) {
+ if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ continue;
+ restore_cpu_idle_disable_state(i);
+ }
+ }
trace_events_destroy(&record->trace, params->events);
params->events = NULL;
out_free:
@@ -1134,6 +1173,7 @@ int timerlat_top_main(int argc, char *argv[])
osnoise_destroy_tool(record);
osnoise_destroy_tool(top);
free(params);
+ free_cpu_idle_disable_states();
out_exit:
exit(return_value);
}
--
2.46.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RESEND v3 5/6] rtla/timerlat: Add --deepest-idle-state for hist
2024-10-04 9:50 [PATCH RESEND v3 0/6] rtla: Support idle state disabling via libcpupower in timerlat tglozar
` (3 preceding siblings ...)
2024-10-04 9:50 ` [PATCH RESEND v3 4/6] rtla/timerlat: Add --deepest-idle-state for top tglozar
@ 2024-10-04 9:50 ` tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 6/6] rtla: Documentation: Mention --deepest-idle-state tglozar
5 siblings, 0 replies; 9+ messages in thread
From: tglozar @ 2024-10-04 9:50 UTC (permalink / raw)
To: rostedt; +Cc: linux-trace-kernel, linux-kernel, jwyatt, jkacur, Tomas Glozar
From: Tomas Glozar <tglozar@redhat.com>
Support limiting deepest idle state also for timerlat-hist.
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
tools/tracing/rtla/src/timerlat_hist.c | 42 +++++++++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index a3907c390d67..99176951c414 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -55,6 +55,7 @@ struct timerlat_hist_params {
int entries;
int warmup;
int buffer_size;
+ int deepest_idle_state;
};
struct timerlat_hist_cpu {
@@ -655,7 +656,7 @@ static void timerlat_hist_usage(char *usage)
" [-t[file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] [-H cpu-list]\\",
" [-P priority] [-E N] [-b N] [--no-irq] [--no-thread] [--no-header] [--no-summary] \\",
" [--no-index] [--with-zeros] [--dma-latency us] [-C[=cgroup_name]] [--no-aa] [--dump-task] [-u|-k]",
- " [--warm-up s]",
+ " [--warm-up s] [--deepest-idle-state n]",
"",
" -h/--help: print this menu",
" -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
@@ -695,6 +696,7 @@ static void timerlat_hist_usage(char *usage)
" -U/--user-load: enable timerlat for user-defined user-space workload",
" --warm-up s: let the workload run for s seconds before collecting data",
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
+ " --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency",
NULL,
};
@@ -732,6 +734,9 @@ static struct timerlat_hist_params
/* disabled by default */
params->dma_latency = -1;
+ /* disabled by default */
+ params->deepest_idle_state = -2;
+
/* display data in microseconds */
params->output_divisor = 1000;
params->bucket_size = 1;
@@ -772,6 +777,7 @@ static struct timerlat_hist_params
{"dump-task", no_argument, 0, '\1'},
{"warm-up", required_argument, 0, '\2'},
{"trace-buffer-size", required_argument, 0, '\3'},
+ {"deepest-idle-state", required_argument, 0, '\4'},
{0, 0, 0, 0}
};
@@ -960,6 +966,9 @@ static struct timerlat_hist_params
case '\3':
params->buffer_size = get_llong_from_str(optarg);
break;
+ case '\4':
+ params->deepest_idle_state = get_llong_from_str(optarg);
+ break;
default:
timerlat_hist_usage("Invalid option");
}
@@ -1152,6 +1161,7 @@ int timerlat_hist_main(int argc, char *argv[])
int return_value = 1;
pthread_t timerlat_u;
int retval;
+ int nr_cpus, i;
params = timerlat_hist_parse_args(argc, argv);
if (!params)
@@ -1201,6 +1211,28 @@ int timerlat_hist_main(int argc, char *argv[])
}
}
+ if (params->deepest_idle_state >= -1) {
+ if (!have_libcpupower_support()) {
+ err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
+ goto out_free;
+ }
+
+ nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+
+ for (i = 0; i < nr_cpus; i++) {
+ if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ continue;
+ if (save_cpu_idle_disable_state(i) < 0) {
+ err_msg("Could not save cpu idle state.\n");
+ goto out_free;
+ }
+ if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
+ err_msg("Could not set deepest cpu idle state.\n");
+ goto out_free;
+ }
+ }
+ }
+
if (params->trace_output) {
record = osnoise_init_trace_tool("timerlat");
if (!record) {
@@ -1332,6 +1364,13 @@ int timerlat_hist_main(int argc, char *argv[])
timerlat_aa_destroy();
if (dma_latency_fd >= 0)
close(dma_latency_fd);
+ if (params->deepest_idle_state >= -1) {
+ for (i = 0; i < nr_cpus; i++) {
+ if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
+ continue;
+ restore_cpu_idle_disable_state(i);
+ }
+ }
trace_events_destroy(&record->trace, params->events);
params->events = NULL;
out_free:
@@ -1340,6 +1379,7 @@ int timerlat_hist_main(int argc, char *argv[])
osnoise_destroy_tool(record);
osnoise_destroy_tool(tool);
free(params);
+ free_cpu_idle_disable_states();
out_exit:
exit(return_value);
}
--
2.46.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RESEND v3 6/6] rtla: Documentation: Mention --deepest-idle-state
2024-10-04 9:50 [PATCH RESEND v3 0/6] rtla: Support idle state disabling via libcpupower in timerlat tglozar
` (4 preceding siblings ...)
2024-10-04 9:50 ` [PATCH RESEND v3 5/6] rtla/timerlat: Add --deepest-idle-state for hist tglozar
@ 2024-10-04 9:50 ` tglozar
5 siblings, 0 replies; 9+ messages in thread
From: tglozar @ 2024-10-04 9:50 UTC (permalink / raw)
To: rostedt; +Cc: linux-trace-kernel, linux-kernel, jwyatt, jkacur, Tomas Glozar
From: Tomas Glozar <tglozar@redhat.com>
Add --deepest-idle-state to manpage and mention libcpupower dependency
in README.txt.
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
---
Documentation/tools/rtla/common_timerlat_options.rst | 8 ++++++++
tools/tracing/rtla/README.txt | 4 ++++
2 files changed, 12 insertions(+)
diff --git a/Documentation/tools/rtla/common_timerlat_options.rst b/Documentation/tools/rtla/common_timerlat_options.rst
index cef6651f1435..10dc802f8d65 100644
--- a/Documentation/tools/rtla/common_timerlat_options.rst
+++ b/Documentation/tools/rtla/common_timerlat_options.rst
@@ -31,6 +31,14 @@
*cyclictest* sets this value to *0* by default, use **--dma-latency** *0* to have
similar results.
+**--deepest-idle-state** *n*
+ Disable idle states higher than *n* for cpus that are running timerlat threads to
+ reduce exit from idle latencies. If *n* is -1, all idle states are disabled.
+ On exit from timerlat, the idle state setting is restored to its original state
+ before running timerlat.
+
+ Requires rtla to be built with libcpupower.
+
**-k**, **--kernel-threads**
Use timerlat kernel-space threads, in contrast of **-u**.
diff --git a/tools/tracing/rtla/README.txt b/tools/tracing/rtla/README.txt
index 4af3fd40f171..dd5621038c55 100644
--- a/tools/tracing/rtla/README.txt
+++ b/tools/tracing/rtla/README.txt
@@ -11,6 +11,7 @@ RTLA depends on the following libraries and tools:
- libtracefs
- libtraceevent
+ - libcpupower (optional, for --deepest-idle-state)
It also depends on python3-docutils to compile man pages.
@@ -26,6 +27,9 @@ For development, we suggest the following steps for compiling rtla:
$ make
$ sudo make install
$ cd ..
+ $ cd $libcpupower_src
+ $ make
+ $ sudo make install
$ cd $rtla_src
$ make
$ sudo make install
--
2.46.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH RESEND v3 3/6] rtla/utils: Add idle state disabling via libcpupower
2024-10-04 9:50 ` [PATCH RESEND v3 3/6] rtla/utils: Add idle state disabling via libcpupower tglozar
@ 2024-10-10 20:06 ` Steven Rostedt
2024-10-11 10:46 ` Tomas Glozar
0 siblings, 1 reply; 9+ messages in thread
From: Steven Rostedt @ 2024-10-10 20:06 UTC (permalink / raw)
To: tglozar; +Cc: linux-trace-kernel, linux-kernel, jwyatt, jkacur
On Fri, 4 Oct 2024 11:50:11 +0200
tglozar@redhat.com wrote:
> From: Tomas Glozar <tglozar@redhat.com>
>
> 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.
>
> Signed-off-by: Tomas Glozar <tglozar@redhat.com>
> ---
> tools/tracing/rtla/src/utils.c | 150 +++++++++++++++++++++++++++++++++
> tools/tracing/rtla/src/utils.h | 13 +++
> 2 files changed, 163 insertions(+)
>
> diff --git a/tools/tracing/rtla/src/utils.c b/tools/tracing/rtla/src/utils.c
> index 9ac71a66840c..6ae084fdedf9 100644
> --- a/tools/tracing/rtla/src/utils.c
> +++ b/tools/tracing/rtla/src/utils.c
> @@ -4,6 +4,9 @@
> */
>
> #define _GNU_SOURCE
> +#ifdef HAVE_LIBCPUPOWER_SUPPORT
> +#include <cpuidle.h>
> +#endif /* HAVE_LIBCPUPOWER_SUPPORT */
> #include <dirent.h>
> #include <stdarg.h>
> #include <stdlib.h>
> @@ -519,6 +522,153 @@ int set_cpu_dma_latency(int32_t latency)
> return fd;
> }
>
> +#ifdef HAVE_LIBCPUPOWER_SUPPORT
> +static unsigned int **saved_cpu_idle_disable_state;
> +static size_t saved_cpu_idle_disable_state_alloc_ctr;
> +
> +/*
> + * save_cpu_idle_state_disable - save disable for all idle states of a cpu
> + *
> + * Saves the current disable of all idle states of a cpu, to be subsequently
> + * restored via restore_cpu_idle_disable_state.
> + *
> + * Return: idle state count on success, negative on error
> + */
> +int save_cpu_idle_disable_state(unsigned int cpu)
> +{
> + unsigned int nr_states;
> + unsigned int state;
> + int disabled;
> + int nr_cpus;
> +
> + nr_states = cpuidle_state_count(cpu);
> +
> + if (nr_states == 0)
> + return 0;
If nr_states is zero, this returns 0 without ever allocating
saved_cpu_idle_disable_state.
> +
> + if (saved_cpu_idle_disable_state == NULL) {
> + nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
> + saved_cpu_idle_disable_state = calloc(nr_cpus, sizeof(unsigned int *));
> + if (!saved_cpu_idle_disable_state)
> + return -1;
> + }
> +
> + saved_cpu_idle_disable_state[cpu] = calloc(nr_states, sizeof(unsigned int));
> + if (!saved_cpu_idle_disable_state[cpu])
> + return -1;
> + saved_cpu_idle_disable_state_alloc_ctr++;
> +
> + for (state = 0; state < nr_states; state++) {
> + disabled = cpuidle_is_state_disabled(cpu, state);
> + if (disabled < 0)
> + return disabled;
> + saved_cpu_idle_disable_state[cpu][state] = disabled;
> + }
> +
> + return nr_states;
> +}
> +
> +/*
> + * restore_cpu_idle_disable_state - restore disable for all idle states of a cpu
> + *
> + * Restores the current disable state of all idle states of a cpu that was
> + * previously saved by save_cpu_idle_disable_state.
> + *
> + * Return: idle state count on success, negative on error
> + */
> +int restore_cpu_idle_disable_state(unsigned int cpu)
> +{
> + unsigned int nr_states;
> + unsigned int state;
> + int disabled;
> + int result;
> +
> + if (!saved_cpu_idle_disable_state)
> + return -1;
This returns -1 even if nr_states is zero. That is,
save_cpu_idle_disable_state() can return success, but this restore will
return failure.
-- Steve
> +
> + nr_states = cpuidle_state_count(cpu);
> +
> + if (nr_states == 0)
> + return 0;
> +
> + for (state = 0; state < nr_states; state++) {
> + if (!saved_cpu_idle_disable_state[cpu])
> + return -1;
> + disabled = saved_cpu_idle_disable_state[cpu][state];
> + result = cpuidle_state_disable(cpu, state, disabled);
> + if (result < 0)
> + return result;
> + }
> +
> + free(saved_cpu_idle_disable_state[cpu]);
> + saved_cpu_idle_disable_state[cpu] = NULL;
> + saved_cpu_idle_disable_state_alloc_ctr--;
> + if (saved_cpu_idle_disable_state_alloc_ctr == 0) {
> + free(saved_cpu_idle_disable_state);
> + saved_cpu_idle_disable_state = NULL;
> + }
> +
> + return nr_states;
> +}
> +
> +/*
> + * free_cpu_idle_disable_states - free saved idle state disable for all cpus
> + *
> + * Frees the memory used for storing cpu idle state disable for all cpus
> + * and states.
> + *
> + * Normally, the memory is freed automatically in
> + * restore_cpu_idle_disable_state; this is mostly for cleaning up after an
> + * error.
> + */
> +void free_cpu_idle_disable_states(void)
> +{
> + int cpu;
> + int nr_cpus;
> +
> + if (!saved_cpu_idle_disable_state)
> + return;
> +
> + nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
> +
> + for (cpu = 0; cpu < nr_cpus; cpu++) {
> + free(saved_cpu_idle_disable_state[cpu]);
> + saved_cpu_idle_disable_state[cpu] = NULL;
> + }
> +
> + free(saved_cpu_idle_disable_state);
> + saved_cpu_idle_disable_state = NULL;
> +}
> +
> +/*
> + * set_deepest_cpu_idle_state - limit idle state of cpu
> + *
> + * Disables all idle states deeper than the one given in
> + * deepest_state (assuming states with higher number are deeper).
> + *
> + * This is used to reduce the exit from idle latency. Unlike
> + * set_cpu_dma_latency, it can disable idle states per cpu.
> + *
> + * Return: idle state count on success, negative on error
> + */
> +int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int deepest_state)
> +{
> + unsigned int nr_states;
> + unsigned int state;
> + int result;
> +
> + nr_states = cpuidle_state_count(cpu);
> +
> + for (state = deepest_state + 1; state < nr_states; state++) {
> + result = cpuidle_state_disable(cpu, state, 1);
> + if (result < 0)
> + return result;
> + }
> +
> + return nr_states;
> +}
> +#endif /* HAVE_LIBCPUPOWER_SUPPORT */
> +
> #define _STR(x) #x
> #define STR(x) _STR(x)
>
> diff --git a/tools/tracing/rtla/src/utils.h b/tools/tracing/rtla/src/utils.h
> index d44513e6c66a..e439db7fc848 100644
> --- a/tools/tracing/rtla/src/utils.h
> +++ b/tools/tracing/rtla/src/utils.h
> @@ -64,6 +64,19 @@ int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr);
> int set_comm_cgroup(const char *comm_prefix, const char *cgroup);
> int set_pid_cgroup(pid_t pid, const char *cgroup);
> int set_cpu_dma_latency(int32_t latency);
> +#ifdef HAVE_LIBCPUPOWER_SUPPORT
> +int save_cpu_idle_disable_state(unsigned int cpu);
> +int restore_cpu_idle_disable_state(unsigned int cpu);
> +void free_cpu_idle_disable_states(void);
> +int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int state);
> +static inline int have_libcpupower_support(void) { return 1; }
> +#else
> +static inline int save_cpu_idle_disable_state(unsigned int cpu) { return -1; }
> +static inline int restore_cpu_idle_disable_state(unsigned int cpu) { return -1; }
> +static inline void free_cpu_idle_disable_states(void) { }
> +static inline int set_deepest_cpu_idle_state(unsigned int cpu, unsigned int state) { return -1; }
> +static inline int have_libcpupower_support(void) { return 0; }
> +#endif /* HAVE_LIBCPUPOWER_SUPPORT */
> int auto_house_keeping(cpu_set_t *monitored_cpus);
>
> #define ns_to_usf(x) (((double)x/1000))
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH RESEND v3 3/6] rtla/utils: Add idle state disabling via libcpupower
2024-10-10 20:06 ` Steven Rostedt
@ 2024-10-11 10:46 ` Tomas Glozar
0 siblings, 0 replies; 9+ messages in thread
From: Tomas Glozar @ 2024-10-11 10:46 UTC (permalink / raw)
To: Steven Rostedt; +Cc: linux-trace-kernel, linux-kernel, jwyatt, jkacur
čt 10. 10. 2024 v 22:06 odesílatel Steven Rostedt <rostedt@goodmis.org> napsal:
>
> If nr_states is zero, this returns 0 without ever allocating
> saved_cpu_idle_disable_state.
>
>> ...
>
> This returns -1 even if nr_states is zero. That is,
> save_cpu_idle_disable_state() can return success, but this restore will
> return failure.
>
> -- Steve
Oh I see: there might be no idle states to save,
saved_cpu_idle_disable_state doesn't get allocated at all, and then
restore_cpu_idle_disable_state behaves as the saves weren't saved
before. Checking for nr_state should fix that; I'll send a v3.
Tomas
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2024-10-11 10:46 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-04 9:50 [PATCH RESEND v3 0/6] rtla: Support idle state disabling via libcpupower in timerlat tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 1/6] tools/build: Add libcpupower dependency detection tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 2/6] rtla: Add optional dependency on libcpupower tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 3/6] rtla/utils: Add idle state disabling via libcpupower tglozar
2024-10-10 20:06 ` Steven Rostedt
2024-10-11 10:46 ` Tomas Glozar
2024-10-04 9:50 ` [PATCH RESEND v3 4/6] rtla/timerlat: Add --deepest-idle-state for top tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 5/6] rtla/timerlat: Add --deepest-idle-state for hist tglozar
2024-10-04 9:50 ` [PATCH RESEND v3 6/6] rtla: Documentation: Mention --deepest-idle-state tglozar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).