tracing/tools: Updates for 6.13

- Add ':' to getopt option 'trace-buffer-size' in timerlat_hist for
   consistency
 
 - Remove unused sched_getattr define
 
 - Rename sched_setattr() helper to syscall_sched_setattr() to avoid
   conflicts
 
 - Update counters to long from int to avoid overflow
 
 - Add libcpupower dependency detection
 
 - Add --deepest-idle-state to timerlat to limit deep idle sleeps
 
 - Other minor clean ups and documentation changes
 -----BEGIN PGP SIGNATURE-----
 
 iIoEABYIADIWIQRRSw7ePDh/lE+zeZMp5XQQmuv6qgUCZz5O/hQccm9zdGVkdEBn
 b29kbWlzLm9yZwAKCRAp5XQQmuv6qkLlAQDAJ0MASrdbJRDrLrfmKX6sja582MLe
 3MvevdSkOeXRdQEA0tzm46KOb5/aYNotzpntQVkTjuZiPBHSgn1JzASiaAI=
 =OZ1w
 -----END PGP SIGNATURE-----

Merge tag 'trace-tools-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull tracing tools updates from Steven Rostedt:

 - Add ':' to getopt option 'trace-buffer-size' in timerlat_hist for
   consistency

 - Remove unused sched_getattr define

 - Rename sched_setattr() helper to syscall_sched_setattr() to avoid
   conflicts

 - Update counters to long from int to avoid overflow

 - Add libcpupower dependency detection

 - Add --deepest-idle-state to timerlat to limit deep idle sleeps

 - Other minor clean ups and documentation changes

* tag 'trace-tools-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  verification/dot2: Improve dot parser robustness
  tools/rtla: Improve exception handling in timerlat_load.py
  tools/rtla: Enhance argument parsing in timerlat_load.py
  tools/rtla: Improve code readability in timerlat_load.py
  rtla/timerlat: Do not set params->user_workload with -U
  rtla: Documentation: Mention --deepest-idle-state
  rtla/timerlat: Add --deepest-idle-state for hist
  rtla/timerlat: Add --deepest-idle-state for top
  rtla/utils: Add idle state disabling via libcpupower
  rtla: Add optional dependency on libcpupower
  tools/build: Add libcpupower dependency detection
  rtla/timerlat: Make timerlat_hist_cpu->*_count unsigned long long
  rtla/timerlat: Make timerlat_top_cpu->*_count unsigned long long
  tools/rtla: fix collision with glibc sched_attr/sched_set_attr
  tools/rtla: drop __NR_sched_getattr
  rtla: Fix consistency in getopt_long for timerlat_hist
  rv: Fix a typo
  tools/rv: Correct the grammatical errors in the comments
  tools/rv: Correct the grammatical errors in the comments
  rtla: use the definition for stdout fd when calling isatty()
This commit is contained in:
Linus Torvalds 2024-11-22 13:24:22 -08:00
commit 4b01712311
17 changed files with 361 additions and 79 deletions

View File

@ -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**.

View File

@ -41,7 +41,7 @@
* per-task monitor, and so on), and the helper functions that glue the
* monitor to the system via trace. Generally, a monitor includes some form
* of trace output as a reaction for event parsing and exceptions,
* as depicted bellow:
* as depicted below:
*
* Linux +----- RV Monitor ----------------------------------+ Formal
* Realm | | Realm

View File

@ -53,6 +53,7 @@ FEATURE_TESTS_BASIC := \
libslang-include-subdir \
libtraceevent \
libtracefs \
libcpupower \
libcrypto \
libunwind \
pthread-attr-setaffinity-np \

View File

@ -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 \
@ -248,6 +249,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

View File

@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
#include <cpuidle.h>
int main(void)
{
int rv = cpuidle_state_count(0);
return rv;
}

View File

@ -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 =

View File

@ -43,6 +43,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)
CFLAGS += -DHAVE_LIBCPUPOWER_SUPPORT
EXTLIBS += -lcpupower
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

View File

@ -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

View File

@ -25,50 +25,54 @@ import sys
import os
parser = argparse.ArgumentParser(description='user-space timerlat thread in Python')
parser.add_argument("cpu", help='CPU to run timerlat thread')
parser.add_argument("-p", "--prio", help='FIFO priority')
parser.add_argument("cpu", type=int, help='CPU to run timerlat thread')
parser.add_argument("-p", "--prio", type=int, help='FIFO priority')
args = parser.parse_args()
try:
affinity_mask = { int(args.cpu) }
except:
print("Invalid cpu: " + args.cpu)
exit(1)
affinity_mask = {args.cpu}
os.sched_setaffinity(0, affinity_mask)
except Exception as e:
print(f"Error setting affinity: {e}")
sys.exit(1)
try:
os.sched_setaffinity(0, affinity_mask);
except:
print("Error setting affinity")
exit(1)
if (args.prio):
if args.prio:
try:
param = os.sched_param(int(args.prio))
param = os.sched_param(args.prio)
os.sched_setscheduler(0, os.SCHED_FIFO, param)
except:
print("Error setting priority")
exit(1)
except Exception as e:
print(f"Error setting priority: {e}")
sys.exit(1)
try:
timerlat_path = "/sys/kernel/tracing/osnoise/per_cpu/cpu" + args.cpu + "/timerlat_fd"
timerlat_path = f"/sys/kernel/tracing/osnoise/per_cpu/cpu{args.cpu}/timerlat_fd"
timerlat_fd = open(timerlat_path, 'r')
except:
except PermissionError:
print("Permission denied. Please check your access rights.")
sys.exit(1)
except OSError:
print("Error opening timerlat fd, did you run timerlat -U?")
exit(1)
sys.exit(1)
try:
data_fd = open("/dev/full", 'r');
except:
print("Error opening data fd")
data_fd = open("/dev/full", 'r')
except Exception as e:
print(f"Error opening data fd: {e}")
sys.exit(1)
while True:
try:
timerlat_fd.read(1)
data_fd.read(20*1024*1024)
except:
data_fd.read(20 * 1024 * 1024)
except KeyboardInterrupt:
print("Leaving")
break
except IOError as e:
print(f"I/O error occurred: {e}")
break
except Exception as e:
print(f"Unexpected error: {e}")
break
timerlat_fd.close()
data_fd.close()

View File

@ -627,7 +627,7 @@ osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_top_params *p
auto_house_keeping(&params->monitored_cpus);
}
if (isatty(1) && !params->quiet)
if (isatty(STDOUT_FILENO) && !params->quiet)
params->pretty_output = 1;
return 0;

View File

@ -55,6 +55,7 @@ struct timerlat_hist_params {
int entries;
int warmup;
int buffer_size;
int deepest_idle_state;
};
struct timerlat_hist_cpu {
@ -62,9 +63,9 @@ struct timerlat_hist_cpu {
int *thread;
int *user;
int irq_count;
int thread_count;
int user_count;
unsigned long long irq_count;
unsigned long long thread_count;
unsigned long long user_count;
unsigned long long min_irq;
unsigned long long sum_irq;
@ -304,15 +305,15 @@ timerlat_print_summary(struct timerlat_hist_params *params,
continue;
if (!params->no_irq)
trace_seq_printf(trace->seq, "%9d ",
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].irq_count);
if (!params->no_thread)
trace_seq_printf(trace->seq, "%9d ",
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].thread_count);
if (params->user_hist)
trace_seq_printf(trace->seq, "%9d ",
trace_seq_printf(trace->seq, "%9llu ",
data->hist[cpu].user_count);
}
trace_seq_printf(trace->seq, "\n");
@ -488,15 +489,15 @@ timerlat_print_stats_all(struct timerlat_hist_params *params,
trace_seq_printf(trace->seq, "count:");
if (!params->no_irq)
trace_seq_printf(trace->seq, "%9d ",
trace_seq_printf(trace->seq, "%9llu ",
sum.irq_count);
if (!params->no_thread)
trace_seq_printf(trace->seq, "%9d ",
trace_seq_printf(trace->seq, "%9llu ",
sum.thread_count);
if (params->user_hist)
trace_seq_printf(trace->seq, "%9d ",
trace_seq_printf(trace->seq, "%9llu ",
sum.user_count);
trace_seq_printf(trace->seq, "\n");
@ -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,13 +777,14 @@ 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}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3",
c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
long_options, &option_index);
/* detect the end of the options. */
@ -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");
}
@ -1064,7 +1073,7 @@ timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_hist_param
* If the user did not specify a type of thread, try user-threads first.
* Fall back to kernel threads otherwise.
*/
if (!params->kernel_workload && !params->user_workload) {
if (!params->kernel_workload && !params->user_hist) {
retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd");
if (retval) {
debug_msg("User-space interface detected, setting user-threads\n");
@ -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, &params->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, &params->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);
}

View File

@ -48,15 +48,16 @@ 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;
};
struct timerlat_top_cpu {
int irq_count;
int thread_count;
int user_count;
unsigned long long irq_count;
unsigned long long thread_count;
unsigned long long user_count;
unsigned long long cur_irq;
unsigned long long min_irq;
@ -280,7 +281,7 @@ static void timerlat_top_print(struct osnoise_tool *top, int cpu)
/*
* Unless trace is being lost, IRQ counter is always the max.
*/
trace_seq_printf(s, "%3d #%-9d |", cpu, cpu_data->irq_count);
trace_seq_printf(s, "%3d #%-9llu |", cpu, cpu_data->irq_count);
if (!cpu_data->irq_count) {
trace_seq_printf(s, "%s %s %s %s |", no_value, no_value, no_value, no_value);
@ -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");
}
@ -830,7 +839,7 @@ timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_top_params *
* If the user did not specify a type of thread, try user-threads first.
* Fall back to kernel threads otherwise.
*/
if (!params->kernel_workload && !params->user_workload) {
if (!params->kernel_workload && !params->user_top) {
retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd");
if (retval) {
debug_msg("User-space interface detected, setting user-threads\n");
@ -850,7 +859,7 @@ timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_top_params *
}
}
if (isatty(1) && !params->quiet)
if (isatty(STDOUT_FILENO) && !params->quiet)
params->pretty_output = 1;
return 0;
@ -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, &params->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, &params->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);
}

View File

@ -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>
@ -211,29 +214,25 @@ long parse_ns_duration(char *val)
/*
* This is a set of helper functions to use SCHED_DEADLINE.
*/
#ifdef __x86_64__
# define __NR_sched_setattr 314
# define __NR_sched_getattr 315
#elif __i386__
# define __NR_sched_setattr 351
# define __NR_sched_getattr 352
#elif __arm__
# define __NR_sched_setattr 380
# define __NR_sched_getattr 381
#elif __aarch64__ || __riscv
# define __NR_sched_setattr 274
# define __NR_sched_getattr 275
#elif __powerpc__
# define __NR_sched_setattr 355
# define __NR_sched_getattr 356
#elif __s390x__
# define __NR_sched_setattr 345
# define __NR_sched_getattr 346
#ifndef __NR_sched_setattr
# ifdef __x86_64__
# define __NR_sched_setattr 314
# elif __i386__
# define __NR_sched_setattr 351
# elif __arm__
# define __NR_sched_setattr 380
# elif __aarch64__ || __riscv
# define __NR_sched_setattr 274
# elif __powerpc__
# define __NR_sched_setattr 355
# elif __s390x__
# define __NR_sched_setattr 345
# endif
#endif
#define SCHED_DEADLINE 6
static inline int sched_setattr(pid_t pid, const struct sched_attr *attr,
static inline int syscall_sched_setattr(pid_t pid, const struct sched_attr *attr,
unsigned int flags) {
return syscall(__NR_sched_setattr, pid, attr, flags);
}
@ -243,7 +242,7 @@ int __set_sched_attr(int pid, struct sched_attr *attr)
int flags = 0;
int retval;
retval = sched_setattr(pid, attr, flags);
retval = syscall_sched_setattr(pid, attr, flags);
if (retval < 0) {
err_msg("Failed to set sched attributes to the pid %d: %s\n",
pid, strerror(errno));
@ -519,6 +518,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;
nr_states = cpuidle_state_count(cpu);
if (nr_states == 0)
return 0;
if (!saved_cpu_idle_disable_state)
return -1;
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)

View File

@ -46,6 +46,7 @@ update_sum(unsigned long long *a, unsigned long long *b)
*a += *b;
}
#ifndef SCHED_ATTR_SIZE_VER0
struct sched_attr {
uint32_t size;
uint32_t sched_policy;
@ -56,6 +57,7 @@ struct sched_attr {
uint64_t sched_deadline;
uint64_t sched_period;
};
#endif /* SCHED_ATTR_SIZE_VER0 */
int parse_prio(char *arg, struct sched_attr *sched_param);
int parse_cpu_set(char *cpu_list, cpu_set_t *set);
@ -64,6 +66,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))

View File

@ -29,11 +29,11 @@ class Automata:
def __get_model_name(self):
basename = ntpath.basename(self.__dot_path)
if basename.endswith(".dot") == False:
if not basename.endswith(".dot") and not basename.endswith(".gv"):
print("not a dot file")
raise Exception("not a dot file: %s" % self.__dot_path)
model_name = basename[0:-4]
model_name = ntpath.splitext(basename)[0]
if model_name.__len__() == 0:
raise Exception("not a dot file: %s" % self.__dot_path)
@ -68,9 +68,9 @@ class Automata:
def __get_cursor_begin_events(self):
cursor = 0
while self.__dot_lines[cursor].split()[0] != "{node":
cursor += 1
cursor += 1
while self.__dot_lines[cursor].split()[0] == "{node":
cursor += 1
cursor += 1
# skip initial state transition
cursor += 1
return cursor
@ -94,11 +94,11 @@ class Automata:
initial_state = state[7:]
else:
states.append(state)
if self.__dot_lines[cursor].__contains__("doublecircle") == True:
if "doublecircle" in self.__dot_lines[cursor]:
final_states.append(state)
has_final_states = True
if self.__dot_lines[cursor].__contains__("ellipse") == True:
if "ellipse" in self.__dot_lines[cursor]:
final_states.append(state)
has_final_states = True
@ -110,7 +110,7 @@ class Automata:
# Insert the initial state at the bein og the states
states.insert(0, initial_state)
if has_final_states == False:
if not has_final_states:
final_states.append(initial_state)
return states, initial_state, final_states
@ -120,7 +120,7 @@ class Automata:
cursor = self.__get_cursor_begin_events()
events = []
while self.__dot_lines[cursor][1] == '"':
while self.__dot_lines[cursor].lstrip()[0] == '"':
# transitions have the format:
# "all_fired" -> "both_fired" [ label = "disable_irq" ];
# ------------ event is here ------------^^^^^
@ -161,7 +161,7 @@ class Automata:
# and we are back! Let's fill the matrix
cursor = self.__get_cursor_begin_events()
while self.__dot_lines[cursor][1] == '"':
while self.__dot_lines[cursor].lstrip()[0] == '"':
if self.__dot_lines[cursor].split()[1] == "->":
line = self.__dot_lines[cursor].split()
origin_state = line[0].replace('"','').replace(',','_')

View File

@ -332,7 +332,7 @@ static void ikm_print_header(struct trace_seq *s)
* ikm_event_handler - callback to handle event events
*
* Called any time a rv:"monitor"_event events is generated.
* It parses and print event.
* It parses and prints event.
*/
static int
ikm_event_handler(struct trace_seq *s, struct tep_record *record,
@ -384,7 +384,7 @@ ikm_event_handler(struct trace_seq *s, struct tep_record *record,
* ikm_error_handler - callback to handle error events
*
* Called any time a rv:"monitor"_errors events is generated.
* It parses and print event.
* It parses and prints event.
*/
static int
ikm_error_handler(struct trace_seq *s, struct tep_record *record,

View File

@ -81,7 +81,7 @@ void trace_instance_destroy(struct trace_instance *trace)
}
/**
* trace_instance_init - create an trace instance
* trace_instance_init - create a trace instance
*
* It is more than the tracefs instance, as it contains other
* things required for the tracing, such as the local events and