Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Pull tracing tooling updates from Steven Rostedt:

- Allow RTLA to collect data via BPF

The current implementation of rtla uses libtracefs and libtraceevent
to pull sample events generated by the timerlat tracer from the trace
buffer. rtla then processes the sample by updating the histogram and
summary (current, maximum, minimum, and sum values) as well as checks
if tracing has been stopped due to threshold overflow.

In use cases where a large number of samples is being generated, that
is, with measurements running on many CPUs and with a low interval,
this sample processing design causes a significant CPU load on the
rtla side. Furthermore, with >100 CPUs and 100us interval, rtla was
reported as not being able to keep up with the samples and dropping
most of them, leading to it being unusable.

Change the way the timerlat trace processes samples by attaching a
BPF program to the trace event using the BPF skeleton feature of
bpftool. Unlike the current implementation, the BPF implementation
does not check whether tracing is stopped (in BPF mode, tracing is
always off to improve performance), but waits for a write to a BPF
ringbuffer instead. This allows rtla to exit immediately when a
threshold is violated, without waiting for the next iteration of the
while loop.

If the requirements for the BPF implementation are not met, either at
build time or at run time, the current implementation is used as
fallback. Which implementation is being used can be seen when running
rtla timerlat with "-D" option. rtla can be forced to run in non-BPF
mode by setting the RTLA_NO_BPF option to 1, for debugging purposes.

- Fix LD_FLAGS from being dropped in build

- Refactor code to remove duplication of save_trace_to_file

- Always set options and do not rely on default settings

Do not rely on the default kernel settings of the tracers when
starting. They could have been changed by the user which gives
inconsistent results. Always set the options that rtla expects.

- Add creation of ctags and TAGS for traversing code

* tag 'trace-tools-v6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
rtla: Add the ability to create ctags and etags
rtla/tests: Test setting default options
rtla/tests: Reset osnoise options before check
rtla: Always set all tracer options
rtla/osnoise: Set OSNOISE_WORKLOAD to true
rtla: Unify apply_config between top and hist
rtla/osnoise: Unify params struct
rtla: Fix segfault in save_trace_to_file call
tools/build: Use SYSTEM_BPFTOOL for system bpftool
rtla: Refactor save_trace_to_file
tools/rv: Keep user LDFLAGS in build
rtla/timerlat: Test BPF mode
rtla/timerlat_top: Use BPF to collect samples
rtla/timerlat_top: Move divisor to update
rtla/timerlat_hist: Use BPF to collect samples
rtla/timerlat: Add BPF skeleton to collect samples
rtla: Add optional dependency on BPF tooling
tools/build: Add bpftool-skeletons feature test
rtla/timerlat: Unify params struct

+1316 -626
+2 -1
tools/build/Makefile.feature
··· 135 135 libbpf-bpf_create_map \ 136 136 libpfm4 \ 137 137 libdebuginfod \ 138 - clang-bpf-co-re 138 + clang-bpf-co-re \ 139 + bpftool-skeletons 139 140 140 141 141 142 FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
+3
tools/build/feature/Makefile
··· 418 418 $(OUTPUT)test-libpfm4.bin: 419 419 $(BUILD) -lpfm 420 420 421 + $(OUTPUT)test-bpftool-skeletons.bin: 422 + $(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons' \ 423 + > $(@:.bin=.make.output) 2>&1 421 424 ############################### 422 425 423 426 clean:
+3
tools/scripts/Makefile.include
··· 91 91 LLVM_OBJCOPY ?= llvm-objcopy 92 92 LLVM_STRIP ?= llvm-strip 93 93 94 + # Some tools require bpftool 95 + SYSTEM_BPFTOOL ?= bpftool 96 + 94 97 ifeq ($(CC_NO_CLANG), 1) 95 98 EXTRA_WARNINGS += -Wstrict-aliasing=3 96 99
+1
tools/tracing/rtla/.gitignore
··· 4 4 fixdep 5 5 feature 6 6 FEATURE-DUMP 7 + *.skel.h
+19 -1
tools/tracing/rtla/Makefile
··· 33 33 FEATURE_TESTS := libtraceevent 34 34 FEATURE_TESTS += libtracefs 35 35 FEATURE_TESTS += libcpupower 36 + FEATURE_TESTS += libbpf 37 + FEATURE_TESTS += clang-bpf-co-re 38 + FEATURE_TESTS += bpftool-skeletons 36 39 FEATURE_DISPLAY := libtraceevent 37 40 FEATURE_DISPLAY += libtracefs 38 41 FEATURE_DISPLAY += libcpupower 42 + FEATURE_DISPLAY += libbpf 43 + FEATURE_DISPLAY += clang-bpf-co-re 44 + FEATURE_DISPLAY += bpftool-skeletons 39 45 40 46 all: $(RTLA) 41 47 ··· 67 61 68 62 export CFLAGS OUTPUT srctree 69 63 64 + ifeq ($(BUILD_BPF_SKEL),1) 65 + src/timerlat.bpf.o: src/timerlat.bpf.c 66 + $(QUIET_CLANG)$(CLANG) -g -O2 -target bpf -c $(filter %.c,$^) -o $@ 67 + 68 + src/timerlat.skel.h: src/timerlat.bpf.o 69 + $(QUIET_GENSKEL)$(SYSTEM_BPFTOOL) gen skeleton $< > $@ 70 + else 71 + src/timerlat.skel.h: 72 + $(Q)echo '/* BPF skeleton is disabled */' > src/timerlat.skel.h 73 + endif 74 + 70 75 $(RTLA): $(RTLA_IN) 71 76 $(QUIET_LINK)$(CC) $(LDFLAGS) -o $(RTLA) $(RTLA_IN) $(EXTLIBS) 72 77 ··· 88 71 rtla.%: fixdep FORCE 89 72 make -f $(srctree)/tools/build/Makefile.build dir=. $@ 90 73 91 - $(RTLA_IN): fixdep FORCE 74 + $(RTLA_IN): fixdep FORCE src/timerlat.skel.h 92 75 make $(build)=rtla 93 76 94 77 clean: doc_clean fixdep-clean ··· 96 79 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 97 80 $(Q)rm -f rtla rtla-static fixdep FEATURE-DUMP rtla-* 98 81 $(Q)rm -rf feature 82 + $(Q)rm -f src/timerlat.bpf.o src/timerlat.skel.h 99 83 check: $(RTLA) 100 84 RTLA=$(RTLA) prove -o -f tests/ 101 85 .PHONY: FORCE clean check
+42
tools/tracing/rtla/Makefile.config
··· 53 53 $(info Please install libcpupower-dev/kernel-tools-libs-devel) 54 54 endif 55 55 56 + ifndef BUILD_BPF_SKEL 57 + # BPF skeletons are used to implement improved sample collection, enable 58 + # them by default. 59 + BUILD_BPF_SKEL := 1 60 + endif 61 + 62 + ifeq ($(BUILD_BPF_SKEL),0) 63 + $(info BPF skeleton support disabled, building without BPF skeleton support.) 64 + endif 65 + 66 + $(call feature_check,libbpf) 67 + ifeq ($(feature-libbpf), 1) 68 + $(call detected,CONFIG_LIBBPF) 69 + else 70 + $(info libbpf is missing, building without BPF skeleton support.) 71 + $(info Please install libbpf-dev/libbpf-devel) 72 + BUILD_BPF_SKEL := 0 73 + endif 74 + 75 + $(call feature_check,clang-bpf-co-re) 76 + ifeq ($(feature-clang-bpf-co-re), 1) 77 + $(call detected,CONFIG_CLANG_BPF_CO_RE) 78 + else 79 + $(info clang is missing or does not support BPF CO-RE, building without BPF skeleton support.) 80 + $(info Please install clang) 81 + BUILD_BPF_SKEL := 0 82 + endif 83 + 84 + $(call feature_check,bpftool-skeletons) 85 + ifeq ($(feature-bpftool-skeletons), 1) 86 + $(call detected,CONFIG_BPFTOOL_SKELETONS) 87 + else 88 + $(info bpftool is missing or not supporting skeletons, building without BPF skeleton support.) 89 + $(info Please install bpftool) 90 + BUILD_BPF_SKEL := 0 91 + endif 92 + 93 + ifeq ($(BUILD_BPF_SKEL),1) 94 + CFLAGS += -DHAVE_BPF_SKEL 95 + EXTLIBS += -lbpf 96 + endif 97 + 56 98 ifeq ($(STOP_ERROR),1) 57 99 $(error Please, check the errors above.) 58 100 endif
+15 -2
tools/tracing/rtla/Makefile.rtla
··· 34 34 MKDIR := mkdir 35 35 STRIP := strip 36 36 BINDIR := /usr/bin 37 + CTAGS := ctags 38 + ETAGS := ctags -e 37 39 38 40 .PHONY: install 39 41 install: doc_install ··· 49 47 @test ! -f $(DESTDIR)$(BINDIR)/timerlat || $(RM) $(DESTDIR)$(BINDIR)/timerlat 50 48 @$(LN) -s rtla $(DESTDIR)$(BINDIR)/timerlat 51 49 50 + .PHONY: tags 51 + tags: 52 + $(CTAGS) -R --extras=+f --c-kinds=+p src 53 + 54 + .PHONY: TAGS 55 + TAGS: 56 + $(ETAGS) -R --extras=+f --c-kinds=+p src 57 + 58 + .PHONY: tags_clean 59 + tags_clean: 60 + $(RM) tags TAGS 61 + 52 62 .PHONY: doc doc_clean doc_install 53 63 doc: 54 64 $(MAKE) -C $(DOCSRC) ··· 71 57 doc_install: 72 58 $(MAKE) -C $(DOCSRC) install 73 59 74 - # This section is neesary for the tarball, when the tarball 75 - # support is removed, we can delete these entries. 60 + # This section is necessary to make the rtla tarball 76 61 NAME := rtla 77 62 DIRS := src 78 63 FILES := Makefile README.txt
+1
tools/tracing/rtla/src/Build
··· 8 8 rtla-y += timerlat_hist.o 9 9 rtla-y += timerlat_u.o 10 10 rtla-y += timerlat_aa.o 11 + rtla-y += timerlat_bpf.o 11 12 rtla-y += rtla.o
+85 -1
tools/tracing/rtla/src/osnoise.c
··· 3 3 * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> 4 4 */ 5 5 6 + #define _GNU_SOURCE 6 7 #include <sys/types.h> 7 8 #include <sys/stat.h> 8 9 #include <pthread.h> ··· 13 12 #include <errno.h> 14 13 #include <fcntl.h> 15 14 #include <stdio.h> 15 + #include <sched.h> 16 16 17 17 #include "osnoise.h" 18 - #include "utils.h" 18 + 19 + #define DEFAULT_SAMPLE_PERIOD 1000000 /* 1s */ 20 + #define DEFAULT_SAMPLE_RUNTIME 1000000 /* 1s */ 19 21 20 22 /* 21 23 * osnoise_get_cpus - return the original "osnoise/cpus" content ··· 1117 1113 tool->trace.missed_events, 1118 1114 (double) tool->trace.missed_events / total_events * 100.0); 1119 1115 } 1116 + } 1117 + 1118 + /* 1119 + * osnoise_apply_config - apply common configs to the initialized tool 1120 + */ 1121 + int 1122 + osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params) 1123 + { 1124 + int retval; 1125 + 1126 + if (!params->sleep_time) 1127 + params->sleep_time = 1; 1128 + 1129 + retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all"); 1130 + if (retval) { 1131 + err_msg("Failed to apply CPUs config\n"); 1132 + goto out_err; 1133 + } 1134 + 1135 + if (params->runtime || params->period) { 1136 + retval = osnoise_set_runtime_period(tool->context, 1137 + params->runtime, 1138 + params->period); 1139 + } else { 1140 + retval = osnoise_set_runtime_period(tool->context, 1141 + DEFAULT_SAMPLE_PERIOD, 1142 + DEFAULT_SAMPLE_RUNTIME); 1143 + } 1144 + 1145 + if (retval) { 1146 + err_msg("Failed to set runtime and/or period\n"); 1147 + goto out_err; 1148 + } 1149 + 1150 + retval = osnoise_set_stop_us(tool->context, params->stop_us); 1151 + if (retval) { 1152 + err_msg("Failed to set stop us\n"); 1153 + goto out_err; 1154 + } 1155 + 1156 + retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); 1157 + if (retval) { 1158 + err_msg("Failed to set stop total us\n"); 1159 + goto out_err; 1160 + } 1161 + 1162 + retval = osnoise_set_tracing_thresh(tool->context, params->threshold); 1163 + if (retval) { 1164 + err_msg("Failed to set tracing_thresh\n"); 1165 + goto out_err; 1166 + } 1167 + 1168 + if (params->hk_cpus) { 1169 + retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), 1170 + &params->hk_cpu_set); 1171 + if (retval == -1) { 1172 + err_msg("Failed to set rtla to the house keeping CPUs\n"); 1173 + goto out_err; 1174 + } 1175 + } else if (params->cpus) { 1176 + /* 1177 + * Even if the user do not set a house-keeping CPU, try to 1178 + * move rtla to a CPU set different to the one where the user 1179 + * set the workload to run. 1180 + * 1181 + * No need to check results as this is an automatic attempt. 1182 + */ 1183 + auto_house_keeping(&params->monitored_cpus); 1184 + } 1185 + 1186 + retval = osnoise_set_workload(tool->context, true); 1187 + if (retval < -1) { 1188 + err_msg("Failed to set OSNOISE_WORKLOAD option\n"); 1189 + goto out_err; 1190 + } 1191 + 1192 + return 0; 1193 + 1194 + out_err: 1195 + return -1; 1120 1196 } 1121 1197 1122 1198 static void osnoise_usage(int err)
+50
tools/tracing/rtla/src/osnoise.h
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 + #pragma once 3 + 4 + #include "utils.h" 2 5 #include "trace.h" 6 + 7 + enum osnoise_mode { 8 + MODE_OSNOISE = 0, 9 + MODE_HWNOISE 10 + }; 11 + 12 + struct osnoise_params { 13 + /* Common params */ 14 + char *cpus; 15 + cpu_set_t monitored_cpus; 16 + char *trace_output; 17 + char *cgroup_name; 18 + unsigned long long runtime; 19 + unsigned long long period; 20 + long long threshold; 21 + long long stop_us; 22 + long long stop_total_us; 23 + int sleep_time; 24 + int duration; 25 + int set_sched; 26 + int cgroup; 27 + int hk_cpus; 28 + cpu_set_t hk_cpu_set; 29 + struct sched_attr sched_param; 30 + struct trace_events *events; 31 + int warmup; 32 + int buffer_size; 33 + union { 34 + struct { 35 + /* top only */ 36 + int quiet; 37 + int pretty_output; 38 + enum osnoise_mode mode; 39 + }; 40 + struct { 41 + /* hist only */ 42 + int output_divisor; 43 + char no_header; 44 + char no_summary; 45 + char no_index; 46 + char with_zeros; 47 + int bucket_size; 48 + int entries; 49 + }; 50 + }; 51 + }; 3 52 4 53 /* 5 54 * osnoise_context - read, store, write, restore osnoise configs. ··· 155 106 struct osnoise_tool *osnoise_init_trace_tool(char *tracer); 156 107 void osnoise_report_missed_events(struct osnoise_tool *tool); 157 108 bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record); 109 + int osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params); 158 110 159 111 int osnoise_hist_main(int argc, char *argv[]); 160 112 int osnoise_top_main(int argc, char **argv);
+16 -108
tools/tracing/rtla/src/osnoise_hist.c
··· 12 12 #include <errno.h> 13 13 #include <stdio.h> 14 14 #include <time.h> 15 - #include <sched.h> 16 15 17 - #include "utils.h" 18 16 #include "osnoise.h" 19 - 20 - struct osnoise_hist_params { 21 - char *cpus; 22 - cpu_set_t monitored_cpus; 23 - char *trace_output; 24 - char *cgroup_name; 25 - unsigned long long runtime; 26 - unsigned long long period; 27 - long long threshold; 28 - long long stop_us; 29 - long long stop_total_us; 30 - int sleep_time; 31 - int duration; 32 - int set_sched; 33 - int output_divisor; 34 - int cgroup; 35 - int hk_cpus; 36 - cpu_set_t hk_cpu_set; 37 - struct sched_attr sched_param; 38 - struct trace_events *events; 39 - char no_header; 40 - char no_summary; 41 - char no_index; 42 - char with_zeros; 43 - int bucket_size; 44 - int entries; 45 - int warmup; 46 - int buffer_size; 47 - }; 48 17 49 18 struct osnoise_hist_cpu { 50 19 int *samples; ··· 95 126 static void osnoise_hist_update_multiple(struct osnoise_tool *tool, int cpu, 96 127 unsigned long long duration, int count) 97 128 { 98 - struct osnoise_hist_params *params = tool->params; 129 + struct osnoise_params *params = tool->params; 99 130 struct osnoise_hist_data *data = tool->data; 100 131 unsigned long long total_duration; 101 132 int entries = data->entries; ··· 137 168 */ 138 169 static int osnoise_init_trace_hist(struct osnoise_tool *tool) 139 170 { 140 - struct osnoise_hist_params *params = tool->params; 171 + struct osnoise_params *params = tool->params; 141 172 struct osnoise_hist_data *data = tool->data; 142 173 int bucket_size; 143 174 char buff[128]; ··· 222 253 */ 223 254 static void osnoise_hist_header(struct osnoise_tool *tool) 224 255 { 225 - struct osnoise_hist_params *params = tool->params; 256 + struct osnoise_params *params = tool->params; 226 257 struct osnoise_hist_data *data = tool->data; 227 258 struct trace_seq *s = tool->trace.seq; 228 259 char duration[26]; ··· 261 292 * osnoise_print_summary - print the summary of the hist data to the output 262 293 */ 263 294 static void 264 - osnoise_print_summary(struct osnoise_hist_params *params, 295 + osnoise_print_summary(struct osnoise_params *params, 265 296 struct trace_instance *trace, 266 297 struct osnoise_hist_data *data) 267 298 { ··· 339 370 * osnoise_print_stats - print data for all CPUs 340 371 */ 341 372 static void 342 - osnoise_print_stats(struct osnoise_hist_params *params, struct osnoise_tool *tool) 373 + osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *tool) 343 374 { 344 375 struct osnoise_hist_data *data = tool->data; 345 376 struct trace_instance *trace = &tool->trace; ··· 477 508 /* 478 509 * osnoise_hist_parse_args - allocs, parse and fill the cmd line parameters 479 510 */ 480 - static struct osnoise_hist_params 511 + static struct osnoise_params 481 512 *osnoise_hist_parse_args(int argc, char *argv[]) 482 513 { 483 - struct osnoise_hist_params *params; 514 + struct osnoise_params *params; 484 515 struct trace_events *tevent; 485 516 int retval; 486 517 int c; ··· 700 731 * osnoise_hist_apply_config - apply the hist configs to the initialized tool 701 732 */ 702 733 static int 703 - osnoise_hist_apply_config(struct osnoise_tool *tool, struct osnoise_hist_params *params) 734 + osnoise_hist_apply_config(struct osnoise_tool *tool, struct osnoise_params *params) 704 735 { 705 736 int retval; 706 737 707 - if (!params->sleep_time) 708 - params->sleep_time = 1; 709 - 710 - if (params->cpus) { 711 - retval = osnoise_set_cpus(tool->context, params->cpus); 712 - if (retval) { 713 - err_msg("Failed to apply CPUs config\n"); 714 - goto out_err; 715 - } 716 - } 717 - 718 - if (params->runtime || params->period) { 719 - retval = osnoise_set_runtime_period(tool->context, 720 - params->runtime, 721 - params->period); 722 - if (retval) { 723 - err_msg("Failed to set runtime and/or period\n"); 724 - goto out_err; 725 - } 726 - } 727 - 728 - if (params->stop_us) { 729 - retval = osnoise_set_stop_us(tool->context, params->stop_us); 730 - if (retval) { 731 - err_msg("Failed to set stop us\n"); 732 - goto out_err; 733 - } 734 - } 735 - 736 - if (params->stop_total_us) { 737 - retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); 738 - if (retval) { 739 - err_msg("Failed to set stop total us\n"); 740 - goto out_err; 741 - } 742 - } 743 - 744 - if (params->threshold) { 745 - retval = osnoise_set_tracing_thresh(tool->context, params->threshold); 746 - if (retval) { 747 - err_msg("Failed to set tracing_thresh\n"); 748 - goto out_err; 749 - } 750 - } 751 - 752 - if (params->hk_cpus) { 753 - retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), 754 - &params->hk_cpu_set); 755 - if (retval == -1) { 756 - err_msg("Failed to set rtla to the house keeping CPUs\n"); 757 - goto out_err; 758 - } 759 - } else if (params->cpus) { 760 - /* 761 - * Even if the user do not set a house-keeping CPU, try to 762 - * move rtla to a CPU set different to the one where the user 763 - * set the workload to run. 764 - * 765 - * No need to check results as this is an automatic attempt. 766 - */ 767 - auto_house_keeping(&params->monitored_cpus); 768 - } 738 + retval = osnoise_apply_config(tool, params); 739 + if (retval) 740 + goto out_err; 769 741 770 742 return 0; 771 743 ··· 718 808 * osnoise_init_hist - initialize a osnoise hist tool with parameters 719 809 */ 720 810 static struct osnoise_tool 721 - *osnoise_init_hist(struct osnoise_hist_params *params) 811 + *osnoise_init_hist(struct osnoise_params *params) 722 812 { 723 813 struct osnoise_tool *tool; 724 814 int nr_cpus; ··· 752 842 * osnoise_hist_set_signals - handles the signal to stop the tool 753 843 */ 754 844 static void 755 - osnoise_hist_set_signals(struct osnoise_hist_params *params) 845 + osnoise_hist_set_signals(struct osnoise_params *params) 756 846 { 757 847 signal(SIGINT, stop_hist); 758 848 if (params->duration) { ··· 763 853 764 854 int osnoise_hist_main(int argc, char *argv[]) 765 855 { 766 - struct osnoise_hist_params *params; 856 + struct osnoise_params *params; 767 857 struct osnoise_tool *record = NULL; 768 858 struct osnoise_tool *tool = NULL; 769 859 struct trace_instance *trace; ··· 893 983 894 984 if (osnoise_trace_is_off(tool, record)) { 895 985 printf("rtla osnoise hit stop tracing\n"); 896 - if (params->trace_output) { 897 - printf(" Saving trace to %s\n", params->trace_output); 898 - save_trace_to_file(record->trace.inst, params->trace_output); 899 - } 986 + save_trace_to_file(record ? record->trace.inst : NULL, 987 + params->trace_output); 900 988 } 901 989 902 990 out_hist:
+15 -111
tools/tracing/rtla/src/osnoise_top.c
··· 11 11 #include <unistd.h> 12 12 #include <stdio.h> 13 13 #include <time.h> 14 - #include <sched.h> 15 14 16 15 #include "osnoise.h" 17 - #include "utils.h" 18 - 19 - enum osnoise_mode { 20 - MODE_OSNOISE = 0, 21 - MODE_HWNOISE 22 - }; 23 - 24 - /* 25 - * osnoise top parameters 26 - */ 27 - struct osnoise_top_params { 28 - char *cpus; 29 - cpu_set_t monitored_cpus; 30 - char *trace_output; 31 - char *cgroup_name; 32 - unsigned long long runtime; 33 - unsigned long long period; 34 - long long threshold; 35 - long long stop_us; 36 - long long stop_total_us; 37 - int sleep_time; 38 - int duration; 39 - int quiet; 40 - int set_sched; 41 - int cgroup; 42 - int hk_cpus; 43 - int warmup; 44 - int buffer_size; 45 - int pretty_output; 46 - cpu_set_t hk_cpu_set; 47 - struct sched_attr sched_param; 48 - struct trace_events *events; 49 - enum osnoise_mode mode; 50 - }; 51 16 52 17 struct osnoise_top_cpu { 53 18 unsigned long long sum_runtime; ··· 123 158 */ 124 159 static void osnoise_top_header(struct osnoise_tool *top) 125 160 { 126 - struct osnoise_top_params *params = top->params; 161 + struct osnoise_params *params = top->params; 127 162 struct trace_seq *s = top->trace.seq; 128 163 char duration[26]; 129 164 ··· 183 218 */ 184 219 static void osnoise_top_print(struct osnoise_tool *tool, int cpu) 185 220 { 186 - struct osnoise_top_params *params = tool->params; 221 + struct osnoise_params *params = tool->params; 187 222 struct trace_seq *s = tool->trace.seq; 188 223 struct osnoise_top_cpu *cpu_data; 189 224 struct osnoise_top_data *data; ··· 223 258 * osnoise_print_stats - print data for all cpus 224 259 */ 225 260 static void 226 - osnoise_print_stats(struct osnoise_top_params *params, struct osnoise_tool *top) 261 + osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *top) 227 262 { 228 263 struct trace_instance *trace = &top->trace; 229 264 static int nr_cpus = -1; ··· 251 286 /* 252 287 * osnoise_top_usage - prints osnoise top usage message 253 288 */ 254 - static void osnoise_top_usage(struct osnoise_top_params *params, char *usage) 289 + static void osnoise_top_usage(struct osnoise_params *params, char *usage) 255 290 { 256 291 int i; 257 292 ··· 319 354 /* 320 355 * osnoise_top_parse_args - allocs, parse and fill the cmd line parameters 321 356 */ 322 - struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) 357 + struct osnoise_params *osnoise_top_parse_args(int argc, char **argv) 323 358 { 324 - struct osnoise_top_params *params; 359 + struct osnoise_params *params; 325 360 struct trace_events *tevent; 326 361 int retval; 327 362 int c; ··· 518 553 * osnoise_top_apply_config - apply the top configs to the initialized tool 519 554 */ 520 555 static int 521 - osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_top_params *params) 556 + osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_params *params) 522 557 { 523 558 int retval; 524 559 525 - if (!params->sleep_time) 526 - params->sleep_time = 1; 527 - 528 - if (params->cpus) { 529 - retval = osnoise_set_cpus(tool->context, params->cpus); 530 - if (retval) { 531 - err_msg("Failed to apply CPUs config\n"); 532 - goto out_err; 533 - } 534 - } 535 - 536 - if (params->runtime || params->period) { 537 - retval = osnoise_set_runtime_period(tool->context, 538 - params->runtime, 539 - params->period); 540 - if (retval) { 541 - err_msg("Failed to set runtime and/or period\n"); 542 - goto out_err; 543 - } 544 - } 545 - 546 - if (params->stop_us) { 547 - retval = osnoise_set_stop_us(tool->context, params->stop_us); 548 - if (retval) { 549 - err_msg("Failed to set stop us\n"); 550 - goto out_err; 551 - } 552 - } 553 - 554 - if (params->stop_total_us) { 555 - retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); 556 - if (retval) { 557 - err_msg("Failed to set stop total us\n"); 558 - goto out_err; 559 - } 560 - } 561 - 562 - if (params->threshold) { 563 - retval = osnoise_set_tracing_thresh(tool->context, params->threshold); 564 - if (retval) { 565 - err_msg("Failed to set tracing_thresh\n"); 566 - goto out_err; 567 - } 568 - } 560 + retval = osnoise_apply_config(tool, params); 561 + if (retval) 562 + goto out_err; 569 563 570 564 if (params->mode == MODE_HWNOISE) { 571 565 retval = osnoise_set_irq_disable(tool->context, 1); ··· 532 608 err_msg("Failed to set OSNOISE_IRQ_DISABLE option\n"); 533 609 goto out_err; 534 610 } 535 - } 536 - 537 - if (params->hk_cpus) { 538 - retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), 539 - &params->hk_cpu_set); 540 - if (retval == -1) { 541 - err_msg("Failed to set rtla to the house keeping CPUs\n"); 542 - goto out_err; 543 - } 544 - } else if (params->cpus) { 545 - /* 546 - * Even if the user do not set a house-keeping CPU, try to 547 - * move rtla to a CPU set different to the one where the user 548 - * set the workload to run. 549 - * 550 - * No need to check results as this is an automatic attempt. 551 - */ 552 - auto_house_keeping(&params->monitored_cpus); 553 611 } 554 612 555 613 if (isatty(STDOUT_FILENO) && !params->quiet) ··· 546 640 /* 547 641 * osnoise_init_top - initialize a osnoise top tool with parameters 548 642 */ 549 - struct osnoise_tool *osnoise_init_top(struct osnoise_top_params *params) 643 + struct osnoise_tool *osnoise_init_top(struct osnoise_params *params) 550 644 { 551 645 struct osnoise_tool *tool; 552 646 int nr_cpus; ··· 580 674 /* 581 675 * osnoise_top_set_signals - handles the signal to stop the tool 582 676 */ 583 - static void osnoise_top_set_signals(struct osnoise_top_params *params) 677 + static void osnoise_top_set_signals(struct osnoise_params *params) 584 678 { 585 679 signal(SIGINT, stop_top); 586 680 if (params->duration) { ··· 591 685 592 686 int osnoise_top_main(int argc, char **argv) 593 687 { 594 - struct osnoise_top_params *params; 688 + struct osnoise_params *params; 595 689 struct osnoise_tool *record = NULL; 596 690 struct osnoise_tool *tool = NULL; 597 691 struct trace_instance *trace; ··· 719 813 720 814 if (osnoise_trace_is_off(tool, record)) { 721 815 printf("osnoise hit stop tracing\n"); 722 - if (params->trace_output) { 723 - printf(" Saving trace to %s\n", params->trace_output); 724 - save_trace_to_file(record->trace.inst, params->trace_output); 725 - } 816 + save_trace_to_file(record ? record->trace.inst : NULL, 817 + params->trace_output); 726 818 } 727 819 728 820 out_top:
+149
tools/tracing/rtla/src/timerlat.bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/bpf.h> 3 + #include <bpf/bpf_tracing.h> 4 + #include <stdbool.h> 5 + #include "timerlat_bpf.h" 6 + 7 + #define nosubprog __always_inline 8 + #define MAX_ENTRIES_DEFAULT 4096 9 + 10 + char LICENSE[] SEC("license") = "GPL"; 11 + 12 + struct trace_event_raw_timerlat_sample { 13 + unsigned long long timer_latency; 14 + int context; 15 + } __attribute__((preserve_access_index)); 16 + 17 + struct { 18 + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 19 + __uint(max_entries, MAX_ENTRIES_DEFAULT); 20 + __type(key, unsigned int); 21 + __type(value, unsigned long long); 22 + } hist_irq SEC(".maps"), hist_thread SEC(".maps"), hist_user SEC(".maps"); 23 + 24 + struct { 25 + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 26 + __uint(max_entries, SUMMARY_FIELD_N); 27 + __type(key, unsigned int); 28 + __type(value, unsigned long long); 29 + } summary_irq SEC(".maps"), summary_thread SEC(".maps"), summary_user SEC(".maps"); 30 + 31 + struct { 32 + __uint(type, BPF_MAP_TYPE_RINGBUF); 33 + __uint(max_entries, 1); 34 + } signal_stop_tracing SEC(".maps"); 35 + 36 + /* Params to be set by rtla */ 37 + const volatile int bucket_size = 1; 38 + const volatile int output_divisor = 1000; 39 + const volatile int entries = 256; 40 + const volatile int irq_threshold; 41 + const volatile int thread_threshold; 42 + const volatile bool aa_only; 43 + 44 + int stop_tracing; 45 + 46 + nosubprog unsigned long long map_get(void *map, 47 + unsigned int key) 48 + { 49 + unsigned long long *value_ptr; 50 + 51 + value_ptr = bpf_map_lookup_elem(map, &key); 52 + 53 + return !value_ptr ? 0 : *value_ptr; 54 + } 55 + 56 + nosubprog void map_set(void *map, 57 + unsigned int key, 58 + unsigned long long value) 59 + { 60 + bpf_map_update_elem(map, &key, &value, BPF_ANY); 61 + } 62 + 63 + nosubprog void map_increment(void *map, 64 + unsigned int key) 65 + { 66 + map_set(map, key, map_get(map, key) + 1); 67 + } 68 + 69 + nosubprog void update_main_hist(void *map, 70 + int bucket) 71 + { 72 + if (entries == 0) 73 + /* No histogram */ 74 + return; 75 + 76 + if (bucket >= entries) 77 + /* Overflow */ 78 + return; 79 + 80 + map_increment(map, bucket); 81 + } 82 + 83 + nosubprog void update_summary(void *map, 84 + unsigned long long latency, 85 + int bucket) 86 + { 87 + if (aa_only) 88 + /* Auto-analysis only, nothing to be done here */ 89 + return; 90 + 91 + map_set(map, SUMMARY_CURRENT, latency); 92 + 93 + if (bucket >= entries) 94 + /* Overflow */ 95 + map_increment(map, SUMMARY_OVERFLOW); 96 + 97 + if (latency > map_get(map, SUMMARY_MAX)) 98 + map_set(map, SUMMARY_MAX, latency); 99 + 100 + if (latency < map_get(map, SUMMARY_MIN) || map_get(map, SUMMARY_COUNT) == 0) 101 + map_set(map, SUMMARY_MIN, latency); 102 + 103 + map_increment(map, SUMMARY_COUNT); 104 + map_set(map, SUMMARY_SUM, map_get(map, SUMMARY_SUM) + latency); 105 + } 106 + 107 + nosubprog void set_stop_tracing(void) 108 + { 109 + int value = 0; 110 + 111 + /* Suppress further sample processing */ 112 + stop_tracing = 1; 113 + 114 + /* Signal to userspace */ 115 + bpf_ringbuf_output(&signal_stop_tracing, &value, sizeof(value), 0); 116 + } 117 + 118 + SEC("tp/osnoise/timerlat_sample") 119 + int handle_timerlat_sample(struct trace_event_raw_timerlat_sample *tp_args) 120 + { 121 + unsigned long long latency, latency_us; 122 + int bucket; 123 + 124 + if (stop_tracing) 125 + return 0; 126 + 127 + latency = tp_args->timer_latency / output_divisor; 128 + latency_us = tp_args->timer_latency / 1000; 129 + bucket = latency / bucket_size; 130 + 131 + if (tp_args->context == 0) { 132 + update_main_hist(&hist_irq, bucket); 133 + update_summary(&summary_irq, latency, bucket); 134 + 135 + if (irq_threshold != 0 && latency_us >= irq_threshold) 136 + set_stop_tracing(); 137 + } else if (tp_args->context == 1) { 138 + update_main_hist(&hist_thread, bucket); 139 + update_summary(&summary_thread, latency, bucket); 140 + 141 + if (thread_threshold != 0 && latency_us >= thread_threshold) 142 + set_stop_tracing(); 143 + } else { 144 + update_main_hist(&hist_user, bucket); 145 + update_summary(&summary_user, latency, bucket); 146 + } 147 + 148 + return 0; 149 + }
+106
tools/tracing/rtla/src/timerlat.c
··· 2 2 /* 3 3 * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> 4 4 */ 5 + #define _GNU_SOURCE 5 6 #include <sys/types.h> 6 7 #include <sys/stat.h> 7 8 #include <pthread.h> ··· 12 11 #include <errno.h> 13 12 #include <fcntl.h> 14 13 #include <stdio.h> 14 + #include <sched.h> 15 15 16 16 #include "timerlat.h" 17 + 18 + #define DEFAULT_TIMERLAT_PERIOD 1000 /* 1ms */ 19 + 20 + /* 21 + * timerlat_apply_config - apply common configs to the initialized tool 22 + */ 23 + int 24 + timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params) 25 + { 26 + int retval, i; 27 + 28 + if (!params->sleep_time) 29 + params->sleep_time = 1; 30 + 31 + retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all"); 32 + if (retval) { 33 + err_msg("Failed to apply CPUs config\n"); 34 + goto out_err; 35 + } 36 + 37 + if (!params->cpus) { 38 + for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++) 39 + CPU_SET(i, &params->monitored_cpus); 40 + } 41 + 42 + retval = osnoise_set_stop_us(tool->context, params->stop_us); 43 + if (retval) { 44 + err_msg("Failed to set stop us\n"); 45 + goto out_err; 46 + } 47 + 48 + retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); 49 + if (retval) { 50 + err_msg("Failed to set stop total us\n"); 51 + goto out_err; 52 + } 53 + 54 + 55 + retval = osnoise_set_timerlat_period_us(tool->context, 56 + params->timerlat_period_us ? 57 + params->timerlat_period_us : 58 + DEFAULT_TIMERLAT_PERIOD); 59 + if (retval) { 60 + err_msg("Failed to set timerlat period\n"); 61 + goto out_err; 62 + } 63 + 64 + 65 + retval = osnoise_set_print_stack(tool->context, params->print_stack); 66 + if (retval) { 67 + err_msg("Failed to set print stack\n"); 68 + goto out_err; 69 + } 70 + 71 + if (params->hk_cpus) { 72 + retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), 73 + &params->hk_cpu_set); 74 + if (retval == -1) { 75 + err_msg("Failed to set rtla to the house keeping CPUs\n"); 76 + goto out_err; 77 + } 78 + } else if (params->cpus) { 79 + /* 80 + * Even if the user do not set a house-keeping CPU, try to 81 + * move rtla to a CPU set different to the one where the user 82 + * set the workload to run. 83 + * 84 + * No need to check results as this is an automatic attempt. 85 + */ 86 + auto_house_keeping(&params->monitored_cpus); 87 + } 88 + 89 + /* 90 + * If the user did not specify a type of thread, try user-threads first. 91 + * Fall back to kernel threads otherwise. 92 + */ 93 + if (!params->kernel_workload && !params->user_data) { 94 + retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd"); 95 + if (retval) { 96 + debug_msg("User-space interface detected, setting user-threads\n"); 97 + params->user_workload = 1; 98 + params->user_data = 1; 99 + } else { 100 + debug_msg("User-space interface not detected, setting kernel-threads\n"); 101 + params->kernel_workload = 1; 102 + } 103 + } 104 + 105 + /* 106 + * Set workload according to type of thread if the kernel supports it. 107 + * On kernels without support, user threads will have already failed 108 + * on missing timerlat_fd, and kernel threads do not need it. 109 + */ 110 + retval = osnoise_set_workload(tool->context, params->kernel_workload); 111 + if (retval < -1) { 112 + err_msg("Failed to set OSNOISE_WORKLOAD option\n"); 113 + goto out_err; 114 + } 115 + 116 + return 0; 117 + 118 + out_err: 119 + return -1; 120 + } 17 121 18 122 static void timerlat_usage(int err) 19 123 {
+54
tools/tracing/rtla/src/timerlat.h
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 + #include "osnoise.h" 3 + 4 + struct timerlat_params { 5 + /* Common params */ 6 + char *cpus; 7 + cpu_set_t monitored_cpus; 8 + char *trace_output; 9 + char *cgroup_name; 10 + unsigned long long runtime; 11 + long long stop_us; 12 + long long stop_total_us; 13 + long long timerlat_period_us; 14 + long long print_stack; 15 + int sleep_time; 16 + int output_divisor; 17 + int duration; 18 + int set_sched; 19 + int dma_latency; 20 + int no_aa; 21 + int dump_tasks; 22 + int cgroup; 23 + int hk_cpus; 24 + int user_workload; 25 + int kernel_workload; 26 + int user_data; 27 + int warmup; 28 + int buffer_size; 29 + int deepest_idle_state; 30 + cpu_set_t hk_cpu_set; 31 + struct sched_attr sched_param; 32 + struct trace_events *events; 33 + union { 34 + struct { 35 + /* top only */ 36 + int quiet; 37 + int aa_only; 38 + int pretty_output; 39 + }; 40 + struct { 41 + /* hist only */ 42 + char no_irq; 43 + char no_thread; 44 + char no_header; 45 + char no_summary; 46 + char no_index; 47 + char with_zeros; 48 + int bucket_size; 49 + int entries; 50 + }; 51 + }; 52 + }; 53 + 54 + int timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params); 55 + 2 56 int timerlat_hist_main(int argc, char *argv[]); 3 57 int timerlat_top_main(int argc, char *argv[]); 4 58 int timerlat_main(int argc, char *argv[]);
-2
tools/tracing/rtla/src/timerlat_aa.c
··· 5 5 6 6 #include <stdlib.h> 7 7 #include <errno.h> 8 - #include "utils.h" 9 - #include "osnoise.h" 10 8 #include "timerlat.h" 11 9 #include <unistd.h> 12 10
+166
tools/tracing/rtla/src/timerlat_bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #ifdef HAVE_BPF_SKEL 3 + #include "timerlat.h" 4 + #include "timerlat_bpf.h" 5 + #include "timerlat.skel.h" 6 + 7 + static struct timerlat_bpf *bpf; 8 + 9 + /* 10 + * timerlat_bpf_init - load and initialize BPF program to collect timerlat data 11 + */ 12 + int timerlat_bpf_init(struct timerlat_params *params) 13 + { 14 + int err; 15 + 16 + debug_msg("Loading BPF program\n"); 17 + 18 + bpf = timerlat_bpf__open(); 19 + if (!bpf) 20 + return 1; 21 + 22 + /* Pass common options */ 23 + bpf->rodata->output_divisor = params->output_divisor; 24 + bpf->rodata->entries = params->entries; 25 + bpf->rodata->irq_threshold = params->stop_us; 26 + bpf->rodata->thread_threshold = params->stop_total_us; 27 + bpf->rodata->aa_only = params->aa_only; 28 + 29 + if (params->entries != 0) { 30 + /* Pass histogram options */ 31 + bpf->rodata->bucket_size = params->bucket_size; 32 + 33 + /* Set histogram array sizes */ 34 + bpf_map__set_max_entries(bpf->maps.hist_irq, params->entries); 35 + bpf_map__set_max_entries(bpf->maps.hist_thread, params->entries); 36 + bpf_map__set_max_entries(bpf->maps.hist_user, params->entries); 37 + } else { 38 + /* No entries, disable histogram */ 39 + bpf_map__set_autocreate(bpf->maps.hist_irq, false); 40 + bpf_map__set_autocreate(bpf->maps.hist_thread, false); 41 + bpf_map__set_autocreate(bpf->maps.hist_user, false); 42 + } 43 + 44 + if (params->aa_only) { 45 + /* Auto-analysis only, disable summary */ 46 + bpf_map__set_autocreate(bpf->maps.summary_irq, false); 47 + bpf_map__set_autocreate(bpf->maps.summary_thread, false); 48 + bpf_map__set_autocreate(bpf->maps.summary_user, false); 49 + } 50 + 51 + /* Load and verify BPF program */ 52 + err = timerlat_bpf__load(bpf); 53 + if (err) { 54 + timerlat_bpf__destroy(bpf); 55 + return err; 56 + } 57 + 58 + return 0; 59 + } 60 + 61 + /* 62 + * timerlat_bpf_attach - attach BPF program to collect timerlat data 63 + */ 64 + int timerlat_bpf_attach(void) 65 + { 66 + debug_msg("Attaching BPF program\n"); 67 + 68 + return timerlat_bpf__attach(bpf); 69 + } 70 + 71 + /* 72 + * timerlat_bpf_detach - detach BPF program to collect timerlat data 73 + */ 74 + void timerlat_bpf_detach(void) 75 + { 76 + timerlat_bpf__detach(bpf); 77 + } 78 + 79 + /* 80 + * timerlat_bpf_detach - destroy BPF program to collect timerlat data 81 + */ 82 + void timerlat_bpf_destroy(void) 83 + { 84 + timerlat_bpf__destroy(bpf); 85 + } 86 + 87 + static int handle_rb_event(void *ctx, void *data, size_t data_sz) 88 + { 89 + return 0; 90 + } 91 + 92 + /* 93 + * timerlat_bpf_wait - wait until tracing is stopped or signal 94 + */ 95 + int timerlat_bpf_wait(int timeout) 96 + { 97 + struct ring_buffer *rb; 98 + int retval; 99 + 100 + rb = ring_buffer__new(bpf_map__fd(bpf->maps.signal_stop_tracing), 101 + handle_rb_event, NULL, NULL); 102 + retval = ring_buffer__poll(rb, timeout * 1000); 103 + ring_buffer__free(rb); 104 + 105 + return retval; 106 + } 107 + 108 + static int get_value(struct bpf_map *map_irq, 109 + struct bpf_map *map_thread, 110 + struct bpf_map *map_user, 111 + int key, 112 + long long *value_irq, 113 + long long *value_thread, 114 + long long *value_user, 115 + int cpus) 116 + { 117 + int err; 118 + 119 + err = bpf_map__lookup_elem(map_irq, &key, 120 + sizeof(unsigned int), value_irq, 121 + sizeof(long long) * cpus, 0); 122 + if (err) 123 + return err; 124 + err = bpf_map__lookup_elem(map_thread, &key, 125 + sizeof(unsigned int), value_thread, 126 + sizeof(long long) * cpus, 0); 127 + if (err) 128 + return err; 129 + err = bpf_map__lookup_elem(map_user, &key, 130 + sizeof(unsigned int), value_user, 131 + sizeof(long long) * cpus, 0); 132 + if (err) 133 + return err; 134 + return 0; 135 + } 136 + 137 + /* 138 + * timerlat_bpf_get_hist_value - get value from BPF hist map 139 + */ 140 + int timerlat_bpf_get_hist_value(int key, 141 + long long *value_irq, 142 + long long *value_thread, 143 + long long *value_user, 144 + int cpus) 145 + { 146 + return get_value(bpf->maps.hist_irq, 147 + bpf->maps.hist_thread, 148 + bpf->maps.hist_user, 149 + key, value_irq, value_thread, value_user, cpus); 150 + } 151 + 152 + /* 153 + * timerlat_bpf_get_summary_value - get value from BPF summary map 154 + */ 155 + int timerlat_bpf_get_summary_value(enum summary_field key, 156 + long long *value_irq, 157 + long long *value_thread, 158 + long long *value_user, 159 + int cpus) 160 + { 161 + return get_value(bpf->maps.summary_irq, 162 + bpf->maps.summary_thread, 163 + bpf->maps.summary_user, 164 + key, value_irq, value_thread, value_user, cpus); 165 + } 166 + #endif /* HAVE_BPF_SKEL */
+59
tools/tracing/rtla/src/timerlat_bpf.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #pragma once 3 + 4 + enum summary_field { 5 + SUMMARY_CURRENT, 6 + SUMMARY_MIN, 7 + SUMMARY_MAX, 8 + SUMMARY_COUNT, 9 + SUMMARY_SUM, 10 + SUMMARY_OVERFLOW, 11 + SUMMARY_FIELD_N 12 + }; 13 + 14 + #ifndef __bpf__ 15 + #ifdef HAVE_BPF_SKEL 16 + int timerlat_bpf_init(struct timerlat_params *params); 17 + int timerlat_bpf_attach(void); 18 + void timerlat_bpf_detach(void); 19 + void timerlat_bpf_destroy(void); 20 + int timerlat_bpf_wait(int timeout); 21 + int timerlat_bpf_get_hist_value(int key, 22 + long long *value_irq, 23 + long long *value_thread, 24 + long long *value_user, 25 + int cpus); 26 + int timerlat_bpf_get_summary_value(enum summary_field key, 27 + long long *value_irq, 28 + long long *value_thread, 29 + long long *value_user, 30 + int cpus); 31 + static inline int have_libbpf_support(void) { return 1; } 32 + #else 33 + static inline int timerlat_bpf_init(struct timerlat_params *params) 34 + { 35 + return -1; 36 + } 37 + static inline int timerlat_bpf_attach(void) { return -1; } 38 + static inline void timerlat_bpf_detach(void) { }; 39 + static inline void timerlat_bpf_destroy(void) { }; 40 + static inline int timerlat_bpf_wait(int timeout) { return -1; } 41 + static inline int timerlat_bpf_get_hist_value(int key, 42 + long long *value_irq, 43 + long long *value_thread, 44 + long long *value_user, 45 + int cpus) 46 + { 47 + return -1; 48 + } 49 + static inline int timerlat_bpf_get_summary_value(enum summary_field key, 50 + long long *value_irq, 51 + long long *value_thread, 52 + long long *value_user, 53 + int cpus) 54 + { 55 + return -1; 56 + } 57 + static inline int have_libbpf_support(void) { return 0; } 58 + #endif /* HAVE_BPF_SKEL */ 59 + #endif /* __bpf__ */
+176 -180
tools/tracing/rtla/src/timerlat_hist.c
··· 14 14 #include <sched.h> 15 15 #include <pthread.h> 16 16 17 - #include "utils.h" 18 - #include "osnoise.h" 19 17 #include "timerlat.h" 20 18 #include "timerlat_aa.h" 21 19 #include "timerlat_u.h" 22 - 23 - struct timerlat_hist_params { 24 - char *cpus; 25 - cpu_set_t monitored_cpus; 26 - char *trace_output; 27 - char *cgroup_name; 28 - unsigned long long runtime; 29 - long long stop_us; 30 - long long stop_total_us; 31 - long long timerlat_period_us; 32 - long long print_stack; 33 - int sleep_time; 34 - int output_divisor; 35 - int duration; 36 - int set_sched; 37 - int dma_latency; 38 - int cgroup; 39 - int hk_cpus; 40 - int no_aa; 41 - int dump_tasks; 42 - int user_workload; 43 - int kernel_workload; 44 - int user_hist; 45 - cpu_set_t hk_cpu_set; 46 - struct sched_attr sched_param; 47 - struct trace_events *events; 48 - char no_irq; 49 - char no_thread; 50 - char no_header; 51 - char no_summary; 52 - char no_index; 53 - char with_zeros; 54 - int bucket_size; 55 - int entries; 56 - int warmup; 57 - int buffer_size; 58 - int deepest_idle_state; 59 - }; 20 + #include "timerlat_bpf.h" 60 21 61 22 struct timerlat_hist_cpu { 62 23 int *irq; ··· 135 174 unsigned long long context, 136 175 unsigned long long latency) 137 176 { 138 - struct timerlat_hist_params *params = tool->params; 177 + struct timerlat_params *params = tool->params; 139 178 struct timerlat_hist_data *data = tool->data; 140 179 int entries = data->entries; 141 180 int bucket; ··· 195 234 } 196 235 197 236 /* 237 + * timerlat_hist_bpf_pull_data - copy data from BPF maps into userspace 238 + */ 239 + static int timerlat_hist_bpf_pull_data(struct osnoise_tool *tool) 240 + { 241 + struct timerlat_hist_data *data = tool->data; 242 + int i, j, err; 243 + long long value_irq[data->nr_cpus], 244 + value_thread[data->nr_cpus], 245 + value_user[data->nr_cpus]; 246 + 247 + /* Pull histogram */ 248 + for (i = 0; i < data->entries; i++) { 249 + err = timerlat_bpf_get_hist_value(i, value_irq, value_thread, 250 + value_user, data->nr_cpus); 251 + if (err) 252 + return err; 253 + for (j = 0; j < data->nr_cpus; j++) { 254 + data->hist[j].irq[i] = value_irq[j]; 255 + data->hist[j].thread[i] = value_thread[j]; 256 + data->hist[j].user[i] = value_user[j]; 257 + } 258 + } 259 + 260 + /* Pull summary */ 261 + err = timerlat_bpf_get_summary_value(SUMMARY_COUNT, 262 + value_irq, value_thread, value_user, 263 + data->nr_cpus); 264 + if (err) 265 + return err; 266 + for (i = 0; i < data->nr_cpus; i++) { 267 + data->hist[i].irq_count = value_irq[i]; 268 + data->hist[i].thread_count = value_thread[i]; 269 + data->hist[i].user_count = value_user[i]; 270 + } 271 + 272 + err = timerlat_bpf_get_summary_value(SUMMARY_MIN, 273 + value_irq, value_thread, value_user, 274 + data->nr_cpus); 275 + if (err) 276 + return err; 277 + for (i = 0; i < data->nr_cpus; i++) { 278 + data->hist[i].min_irq = value_irq[i]; 279 + data->hist[i].min_thread = value_thread[i]; 280 + data->hist[i].min_user = value_user[i]; 281 + } 282 + 283 + err = timerlat_bpf_get_summary_value(SUMMARY_MAX, 284 + value_irq, value_thread, value_user, 285 + data->nr_cpus); 286 + if (err) 287 + return err; 288 + for (i = 0; i < data->nr_cpus; i++) { 289 + data->hist[i].max_irq = value_irq[i]; 290 + data->hist[i].max_thread = value_thread[i]; 291 + data->hist[i].max_user = value_user[i]; 292 + } 293 + 294 + err = timerlat_bpf_get_summary_value(SUMMARY_SUM, 295 + value_irq, value_thread, value_user, 296 + data->nr_cpus); 297 + if (err) 298 + return err; 299 + for (i = 0; i < data->nr_cpus; i++) { 300 + data->hist[i].sum_irq = value_irq[i]; 301 + data->hist[i].sum_thread = value_thread[i]; 302 + data->hist[i].sum_user = value_user[i]; 303 + } 304 + 305 + err = timerlat_bpf_get_summary_value(SUMMARY_OVERFLOW, 306 + value_irq, value_thread, value_user, 307 + data->nr_cpus); 308 + if (err) 309 + return err; 310 + for (i = 0; i < data->nr_cpus; i++) { 311 + data->hist[i].irq[data->entries] = value_irq[i]; 312 + data->hist[i].thread[data->entries] = value_thread[i]; 313 + data->hist[i].user[data->entries] = value_user[i]; 314 + } 315 + 316 + return 0; 317 + } 318 + 319 + /* 198 320 * timerlat_hist_header - print the header of the tracer to the output 199 321 */ 200 322 static void timerlat_hist_header(struct osnoise_tool *tool) 201 323 { 202 - struct timerlat_hist_params *params = tool->params; 324 + struct timerlat_params *params = tool->params; 203 325 struct timerlat_hist_data *data = tool->data; 204 326 struct trace_seq *s = tool->trace.seq; 205 327 char duration[26]; ··· 315 271 if (!params->no_thread) 316 272 trace_seq_printf(s, " Thr-%03d", cpu); 317 273 318 - if (params->user_hist) 274 + if (params->user_data) 319 275 trace_seq_printf(s, " Usr-%03d", cpu); 320 276 } 321 277 trace_seq_printf(s, "\n"); ··· 344 300 * timerlat_print_summary - print the summary of the hist data to the output 345 301 */ 346 302 static void 347 - timerlat_print_summary(struct timerlat_hist_params *params, 303 + timerlat_print_summary(struct timerlat_params *params, 348 304 struct trace_instance *trace, 349 305 struct timerlat_hist_data *data) 350 306 { ··· 371 327 trace_seq_printf(trace->seq, "%9llu ", 372 328 data->hist[cpu].thread_count); 373 329 374 - if (params->user_hist) 330 + if (params->user_data) 375 331 trace_seq_printf(trace->seq, "%9llu ", 376 332 data->hist[cpu].user_count); 377 333 } ··· 399 355 data->hist[cpu].min_thread, 400 356 false); 401 357 402 - if (params->user_hist) 358 + if (params->user_data) 403 359 format_summary_value(trace->seq, 404 360 data->hist[cpu].user_count, 405 361 data->hist[cpu].min_user, ··· 429 385 data->hist[cpu].sum_thread, 430 386 true); 431 387 432 - if (params->user_hist) 388 + if (params->user_data) 433 389 format_summary_value(trace->seq, 434 390 data->hist[cpu].user_count, 435 391 data->hist[cpu].sum_user, ··· 459 415 data->hist[cpu].max_thread, 460 416 false); 461 417 462 - if (params->user_hist) 418 + if (params->user_data) 463 419 format_summary_value(trace->seq, 464 420 data->hist[cpu].user_count, 465 421 data->hist[cpu].max_user, ··· 471 427 } 472 428 473 429 static void 474 - timerlat_print_stats_all(struct timerlat_hist_params *params, 430 + timerlat_print_stats_all(struct timerlat_params *params, 475 431 struct trace_instance *trace, 476 432 struct timerlat_hist_data *data) 477 433 { ··· 521 477 if (!params->no_thread) 522 478 trace_seq_printf(trace->seq, " Thr"); 523 479 524 - if (params->user_hist) 480 + if (params->user_data) 525 481 trace_seq_printf(trace->seq, " Usr"); 526 482 527 483 trace_seq_printf(trace->seq, "\n"); ··· 537 493 trace_seq_printf(trace->seq, "%9llu ", 538 494 sum.thread_count); 539 495 540 - if (params->user_hist) 496 + if (params->user_data) 541 497 trace_seq_printf(trace->seq, "%9llu ", 542 498 sum.user_count); 543 499 ··· 558 514 sum.min_thread, 559 515 false); 560 516 561 - if (params->user_hist) 517 + if (params->user_data) 562 518 format_summary_value(trace->seq, 563 519 sum.user_count, 564 520 sum.min_user, ··· 581 537 sum.sum_thread, 582 538 true); 583 539 584 - if (params->user_hist) 540 + if (params->user_data) 585 541 format_summary_value(trace->seq, 586 542 sum.user_count, 587 543 sum.sum_user, ··· 604 560 sum.max_thread, 605 561 false); 606 562 607 - if (params->user_hist) 563 + if (params->user_data) 608 564 format_summary_value(trace->seq, 609 565 sum.user_count, 610 566 sum.max_user, ··· 619 575 * timerlat_print_stats - print data for each CPUs 620 576 */ 621 577 static void 622 - timerlat_print_stats(struct timerlat_hist_params *params, struct osnoise_tool *tool) 578 + timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool) 623 579 { 624 580 struct timerlat_hist_data *data = tool->data; 625 581 struct trace_instance *trace = &tool->trace; ··· 654 610 data->hist[cpu].thread[bucket]); 655 611 } 656 612 657 - if (params->user_hist) { 613 + if (params->user_data) { 658 614 total += data->hist[cpu].user[bucket]; 659 615 trace_seq_printf(trace->seq, "%9d ", 660 616 data->hist[cpu].user[bucket]); ··· 690 646 trace_seq_printf(trace->seq, "%9d ", 691 647 data->hist[cpu].thread[data->entries]); 692 648 693 - if (params->user_hist) 649 + if (params->user_data) 694 650 trace_seq_printf(trace->seq, "%9d ", 695 651 data->hist[cpu].user[data->entries]); 696 652 } ··· 778 734 /* 779 735 * timerlat_hist_parse_args - allocs, parse and fill the cmd line parameters 780 736 */ 781 - static struct timerlat_hist_params 737 + static struct timerlat_params 782 738 *timerlat_hist_parse_args(int argc, char *argv[]) 783 739 { 784 - struct timerlat_hist_params *params; 740 + struct timerlat_params *params; 785 741 struct trace_events *tevent; 786 742 int auto_thresh; 787 743 int retval; ··· 965 921 params->user_workload = 1; 966 922 /* fallback: -u implies in -U */ 967 923 case 'U': 968 - params->user_hist = 1; 924 + params->user_data = 1; 969 925 break; 970 926 case '0': /* no irq */ 971 927 params->no_irq = 1; ··· 1061 1017 * timerlat_hist_apply_config - apply the hist configs to the initialized tool 1062 1018 */ 1063 1019 static int 1064 - timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_hist_params *params) 1020 + timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_params *params) 1065 1021 { 1066 - int retval, i; 1022 + int retval; 1067 1023 1068 - if (!params->sleep_time) 1069 - params->sleep_time = 1; 1070 - 1071 - if (params->cpus) { 1072 - retval = osnoise_set_cpus(tool->context, params->cpus); 1073 - if (retval) { 1074 - err_msg("Failed to apply CPUs config\n"); 1075 - goto out_err; 1076 - } 1077 - } else { 1078 - for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++) 1079 - CPU_SET(i, &params->monitored_cpus); 1080 - } 1081 - 1082 - if (params->stop_us) { 1083 - retval = osnoise_set_stop_us(tool->context, params->stop_us); 1084 - if (retval) { 1085 - err_msg("Failed to set stop us\n"); 1086 - goto out_err; 1087 - } 1088 - } 1089 - 1090 - if (params->stop_total_us) { 1091 - retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); 1092 - if (retval) { 1093 - err_msg("Failed to set stop total us\n"); 1094 - goto out_err; 1095 - } 1096 - } 1097 - 1098 - if (params->timerlat_period_us) { 1099 - retval = osnoise_set_timerlat_period_us(tool->context, params->timerlat_period_us); 1100 - if (retval) { 1101 - err_msg("Failed to set timerlat period\n"); 1102 - goto out_err; 1103 - } 1104 - } 1105 - 1106 - if (params->print_stack) { 1107 - retval = osnoise_set_print_stack(tool->context, params->print_stack); 1108 - if (retval) { 1109 - err_msg("Failed to set print stack\n"); 1110 - goto out_err; 1111 - } 1112 - } 1113 - 1114 - if (params->hk_cpus) { 1115 - retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), 1116 - &params->hk_cpu_set); 1117 - if (retval == -1) { 1118 - err_msg("Failed to set rtla to the house keeping CPUs\n"); 1119 - goto out_err; 1120 - } 1121 - } else if (params->cpus) { 1122 - /* 1123 - * Even if the user do not set a house-keeping CPU, try to 1124 - * move rtla to a CPU set different to the one where the user 1125 - * set the workload to run. 1126 - * 1127 - * No need to check results as this is an automatic attempt. 1128 - */ 1129 - auto_house_keeping(&params->monitored_cpus); 1130 - } 1131 - 1132 - /* 1133 - * If the user did not specify a type of thread, try user-threads first. 1134 - * Fall back to kernel threads otherwise. 1135 - */ 1136 - if (!params->kernel_workload && !params->user_hist) { 1137 - retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd"); 1138 - if (retval) { 1139 - debug_msg("User-space interface detected, setting user-threads\n"); 1140 - params->user_workload = 1; 1141 - params->user_hist = 1; 1142 - } else { 1143 - debug_msg("User-space interface not detected, setting kernel-threads\n"); 1144 - params->kernel_workload = 1; 1145 - } 1146 - } 1147 - 1148 - /* 1149 - * Set workload according to type of thread if the kernel supports it. 1150 - * On kernels without support, user threads will have already failed 1151 - * on missing timerlat_fd, and kernel threads do not need it. 1152 - */ 1153 - retval = osnoise_set_workload(tool->context, params->kernel_workload); 1154 - if (retval < -1) { 1155 - err_msg("Failed to set OSNOISE_WORKLOAD option\n"); 1024 + retval = timerlat_apply_config(tool, params); 1025 + if (retval) 1156 1026 goto out_err; 1157 - } 1158 1027 1159 1028 return 0; 1160 1029 ··· 1079 1122 * timerlat_init_hist - initialize a timerlat hist tool with parameters 1080 1123 */ 1081 1124 static struct osnoise_tool 1082 - *timerlat_init_hist(struct timerlat_hist_params *params) 1125 + *timerlat_init_hist(struct timerlat_params *params) 1083 1126 { 1084 1127 struct osnoise_tool *tool; 1085 1128 int nr_cpus; ··· 1127 1170 * timerlat_hist_set_signals - handles the signal to stop the tool 1128 1171 */ 1129 1172 static void 1130 - timerlat_hist_set_signals(struct timerlat_hist_params *params) 1173 + timerlat_hist_set_signals(struct timerlat_params *params) 1131 1174 { 1132 1175 signal(SIGINT, stop_hist); 1133 1176 if (params->duration) { ··· 1138 1181 1139 1182 int timerlat_hist_main(int argc, char *argv[]) 1140 1183 { 1141 - struct timerlat_hist_params *params; 1184 + struct timerlat_params *params; 1142 1185 struct osnoise_tool *record = NULL; 1143 1186 struct timerlat_u_params params_u; 1144 1187 struct osnoise_tool *tool = NULL; ··· 1149 1192 pthread_t timerlat_u; 1150 1193 int retval; 1151 1194 int nr_cpus, i; 1195 + bool no_bpf = false; 1152 1196 1153 1197 params = timerlat_hist_parse_args(argc, argv); 1154 1198 if (!params) ··· 1174 1216 * Otherwise, rtla could loop indefinitely when overloaded. 1175 1217 */ 1176 1218 hist_inst = trace; 1219 + 1220 + if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) { 1221 + debug_msg("RTLA_NO_BPF set, disabling BPF\n"); 1222 + no_bpf = true; 1223 + } 1224 + 1225 + if (!no_bpf && !tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) { 1226 + debug_msg("osnoise:timerlat_sample missing, disabling BPF\n"); 1227 + no_bpf = true; 1228 + } 1229 + 1230 + if (!no_bpf) { 1231 + retval = timerlat_bpf_init(params); 1232 + if (retval) { 1233 + debug_msg("Could not enable BPF\n"); 1234 + no_bpf = true; 1235 + } 1236 + } 1177 1237 1178 1238 retval = enable_timerlat(trace); 1179 1239 if (retval) { ··· 1320 1344 trace_instance_start(&record->trace); 1321 1345 if (!params->no_aa) 1322 1346 trace_instance_start(&aa->trace); 1323 - trace_instance_start(trace); 1347 + if (no_bpf) { 1348 + trace_instance_start(trace); 1349 + } else { 1350 + retval = timerlat_bpf_attach(); 1351 + if (retval) { 1352 + err_msg("Error attaching BPF program\n"); 1353 + goto out_hist; 1354 + } 1355 + } 1324 1356 1325 1357 tool->start_time = time(NULL); 1326 1358 timerlat_hist_set_signals(params); 1327 1359 1328 - while (!stop_tracing) { 1329 - sleep(params->sleep_time); 1360 + if (no_bpf) { 1361 + while (!stop_tracing) { 1362 + sleep(params->sleep_time); 1330 1363 1331 - retval = tracefs_iterate_raw_events(trace->tep, 1332 - trace->inst, 1333 - NULL, 1334 - 0, 1335 - collect_registered_events, 1336 - trace); 1337 - if (retval < 0) { 1338 - err_msg("Error iterating on events\n"); 1339 - goto out_hist; 1340 - } 1341 - 1342 - if (osnoise_trace_is_off(tool, record)) 1343 - break; 1344 - 1345 - /* is there still any user-threads ? */ 1346 - if (params->user_workload) { 1347 - if (params_u.stopped_running) { 1348 - debug_msg("timerlat user-space threads stopped!\n"); 1349 - break; 1364 + retval = tracefs_iterate_raw_events(trace->tep, 1365 + trace->inst, 1366 + NULL, 1367 + 0, 1368 + collect_registered_events, 1369 + trace); 1370 + if (retval < 0) { 1371 + err_msg("Error iterating on events\n"); 1372 + goto out_hist; 1350 1373 } 1374 + 1375 + if (osnoise_trace_is_off(tool, record)) 1376 + break; 1377 + 1378 + /* is there still any user-threads ? */ 1379 + if (params->user_workload) { 1380 + if (params_u.stopped_running) { 1381 + debug_msg("timerlat user-space threads stopped!\n"); 1382 + break; 1383 + } 1384 + } 1385 + } 1386 + } else 1387 + timerlat_bpf_wait(-1); 1388 + 1389 + if (!no_bpf) { 1390 + timerlat_bpf_detach(); 1391 + retval = timerlat_hist_bpf_pull_data(tool); 1392 + if (retval) { 1393 + err_msg("Error pulling BPF data\n"); 1394 + goto out_hist; 1351 1395 } 1352 1396 } 1353 1397 ··· 1386 1390 if (!params->no_aa) 1387 1391 timerlat_auto_analysis(params->stop_us, params->stop_total_us); 1388 1392 1389 - if (params->trace_output) { 1390 - printf(" Saving trace to %s\n", params->trace_output); 1391 - save_trace_to_file(record->trace.inst, params->trace_output); 1392 - } 1393 + save_trace_to_file(record ? record->trace.inst : NULL, 1394 + params->trace_output); 1393 1395 } 1394 1396 1395 1397 out_hist: ··· 1410 1416 osnoise_destroy_tool(tool); 1411 1417 free(params); 1412 1418 free_cpu_idle_disable_states(); 1419 + if (!no_bpf) 1420 + timerlat_bpf_destroy(); 1413 1421 out_exit: 1414 1422 exit(return_value); 1415 1423 }
+263 -219
tools/tracing/rtla/src/timerlat_top.c
··· 15 15 #include <sched.h> 16 16 #include <pthread.h> 17 17 18 - #include "utils.h" 19 - #include "osnoise.h" 20 18 #include "timerlat.h" 21 19 #include "timerlat_aa.h" 22 20 #include "timerlat_u.h" 23 - 24 - struct timerlat_top_params { 25 - char *cpus; 26 - cpu_set_t monitored_cpus; 27 - char *trace_output; 28 - char *cgroup_name; 29 - unsigned long long runtime; 30 - long long stop_us; 31 - long long stop_total_us; 32 - long long timerlat_period_us; 33 - long long print_stack; 34 - int sleep_time; 35 - int output_divisor; 36 - int duration; 37 - int quiet; 38 - int set_sched; 39 - int dma_latency; 40 - int no_aa; 41 - int aa_only; 42 - int dump_tasks; 43 - int cgroup; 44 - int hk_cpus; 45 - int user_top; 46 - int user_workload; 47 - int kernel_workload; 48 - int pretty_output; 49 - int warmup; 50 - int buffer_size; 51 - int deepest_idle_state; 52 - cpu_set_t hk_cpu_set; 53 - struct sched_attr sched_param; 54 - struct trace_events *events; 55 - }; 21 + #include "timerlat_bpf.h" 56 22 57 23 struct timerlat_top_cpu { 58 24 unsigned long long irq_count; ··· 128 162 unsigned long long thread, 129 163 unsigned long long latency) 130 164 { 165 + struct timerlat_params *params = tool->params; 131 166 struct timerlat_top_data *data = tool->data; 132 167 struct timerlat_top_cpu *cpu_data = &data->cpu_data[cpu]; 168 + 169 + if (params->output_divisor) 170 + latency = latency / params->output_divisor; 133 171 134 172 if (!thread) { 135 173 cpu_data->irq_count++; ··· 164 194 struct tep_event *event, void *context) 165 195 { 166 196 struct trace_instance *trace = context; 167 - struct timerlat_top_params *params; 197 + struct timerlat_params *params; 168 198 unsigned long long latency, thread; 169 199 struct osnoise_tool *top; 170 200 int cpu = record->cpu; ··· 183 213 } 184 214 185 215 /* 216 + * timerlat_top_bpf_pull_data - copy data from BPF maps into userspace 217 + */ 218 + static int timerlat_top_bpf_pull_data(struct osnoise_tool *tool) 219 + { 220 + struct timerlat_top_data *data = tool->data; 221 + int i, err; 222 + long long value_irq[data->nr_cpus], 223 + value_thread[data->nr_cpus], 224 + value_user[data->nr_cpus]; 225 + 226 + /* Pull summary */ 227 + err = timerlat_bpf_get_summary_value(SUMMARY_CURRENT, 228 + value_irq, value_thread, value_user, 229 + data->nr_cpus); 230 + if (err) 231 + return err; 232 + for (i = 0; i < data->nr_cpus; i++) { 233 + data->cpu_data[i].cur_irq = value_irq[i]; 234 + data->cpu_data[i].cur_thread = value_thread[i]; 235 + data->cpu_data[i].cur_user = value_user[i]; 236 + } 237 + 238 + err = timerlat_bpf_get_summary_value(SUMMARY_COUNT, 239 + value_irq, value_thread, value_user, 240 + data->nr_cpus); 241 + if (err) 242 + return err; 243 + for (i = 0; i < data->nr_cpus; i++) { 244 + data->cpu_data[i].irq_count = value_irq[i]; 245 + data->cpu_data[i].thread_count = value_thread[i]; 246 + data->cpu_data[i].user_count = value_user[i]; 247 + } 248 + 249 + err = timerlat_bpf_get_summary_value(SUMMARY_MIN, 250 + value_irq, value_thread, value_user, 251 + data->nr_cpus); 252 + if (err) 253 + return err; 254 + for (i = 0; i < data->nr_cpus; i++) { 255 + data->cpu_data[i].min_irq = value_irq[i]; 256 + data->cpu_data[i].min_thread = value_thread[i]; 257 + data->cpu_data[i].min_user = value_user[i]; 258 + } 259 + 260 + err = timerlat_bpf_get_summary_value(SUMMARY_MAX, 261 + value_irq, value_thread, value_user, 262 + data->nr_cpus); 263 + if (err) 264 + return err; 265 + for (i = 0; i < data->nr_cpus; i++) { 266 + data->cpu_data[i].max_irq = value_irq[i]; 267 + data->cpu_data[i].max_thread = value_thread[i]; 268 + data->cpu_data[i].max_user = value_user[i]; 269 + } 270 + 271 + err = timerlat_bpf_get_summary_value(SUMMARY_SUM, 272 + value_irq, value_thread, value_user, 273 + data->nr_cpus); 274 + if (err) 275 + return err; 276 + for (i = 0; i < data->nr_cpus; i++) { 277 + data->cpu_data[i].sum_irq = value_irq[i]; 278 + data->cpu_data[i].sum_thread = value_thread[i]; 279 + data->cpu_data[i].sum_user = value_user[i]; 280 + } 281 + 282 + return 0; 283 + } 284 + 285 + /* 186 286 * timerlat_top_header - print the header of the tool output 187 287 */ 188 - static void timerlat_top_header(struct timerlat_top_params *params, struct osnoise_tool *top) 288 + static void timerlat_top_header(struct timerlat_params *params, struct osnoise_tool *top) 189 289 { 190 290 struct trace_seq *s = top->trace.seq; 191 291 char duration[26]; ··· 266 226 trace_seq_printf(s, "\033[2;37;40m"); 267 227 268 228 trace_seq_printf(s, " Timer Latency "); 269 - if (params->user_top) 229 + if (params->user_data) 270 230 trace_seq_printf(s, " "); 271 231 272 232 if (params->pretty_output) ··· 277 237 params->output_divisor == 1 ? "ns" : "us", 278 238 params->output_divisor == 1 ? "ns" : "us"); 279 239 280 - if (params->user_top) { 240 + if (params->user_data) { 281 241 trace_seq_printf(s, " | Ret user Timer Latency (%s)", 282 242 params->output_divisor == 1 ? "ns" : "us"); 283 243 } ··· 287 247 trace_seq_printf(s, "\033[2;30;47m"); 288 248 289 249 trace_seq_printf(s, "CPU COUNT | cur min avg max | cur min avg max"); 290 - if (params->user_top) 250 + if (params->user_data) 291 251 trace_seq_printf(s, " | cur min avg max"); 292 252 293 253 if (params->pretty_output) ··· 303 263 static void timerlat_top_print(struct osnoise_tool *top, int cpu) 304 264 { 305 265 306 - struct timerlat_top_params *params = top->params; 266 + struct timerlat_params *params = top->params; 307 267 struct timerlat_top_data *data = top->data; 308 268 struct timerlat_top_cpu *cpu_data = &data->cpu_data[cpu]; 309 - int divisor = params->output_divisor; 310 269 struct trace_seq *s = top->trace.seq; 311 - 312 - if (divisor == 0) 313 - return; 314 270 315 271 /* 316 272 * Skip if no data is available: is this cpu offline? ··· 322 286 if (!cpu_data->irq_count) { 323 287 trace_seq_printf(s, "%s %s %s %s |", no_value, no_value, no_value, no_value); 324 288 } else { 325 - trace_seq_printf(s, "%9llu ", cpu_data->cur_irq / params->output_divisor); 326 - trace_seq_printf(s, "%9llu ", cpu_data->min_irq / params->output_divisor); 327 - trace_seq_printf(s, "%9llu ", (cpu_data->sum_irq / cpu_data->irq_count) / divisor); 328 - trace_seq_printf(s, "%9llu |", cpu_data->max_irq / divisor); 289 + trace_seq_printf(s, "%9llu ", cpu_data->cur_irq); 290 + trace_seq_printf(s, "%9llu ", cpu_data->min_irq); 291 + trace_seq_printf(s, "%9llu ", cpu_data->sum_irq / cpu_data->irq_count); 292 + trace_seq_printf(s, "%9llu |", cpu_data->max_irq); 329 293 } 330 294 331 295 if (!cpu_data->thread_count) { 332 296 trace_seq_printf(s, "%s %s %s %s", no_value, no_value, no_value, no_value); 333 297 } else { 334 - trace_seq_printf(s, "%9llu ", cpu_data->cur_thread / divisor); 335 - trace_seq_printf(s, "%9llu ", cpu_data->min_thread / divisor); 298 + trace_seq_printf(s, "%9llu ", cpu_data->cur_thread); 299 + trace_seq_printf(s, "%9llu ", cpu_data->min_thread); 336 300 trace_seq_printf(s, "%9llu ", 337 - (cpu_data->sum_thread / cpu_data->thread_count) / divisor); 338 - trace_seq_printf(s, "%9llu", cpu_data->max_thread / divisor); 301 + cpu_data->sum_thread / cpu_data->thread_count); 302 + trace_seq_printf(s, "%9llu", cpu_data->max_thread); 339 303 } 340 304 341 - if (!params->user_top) { 305 + if (!params->user_data) { 342 306 trace_seq_printf(s, "\n"); 343 307 return; 344 308 } ··· 348 312 if (!cpu_data->user_count) { 349 313 trace_seq_printf(s, "%s %s %s %s\n", no_value, no_value, no_value, no_value); 350 314 } else { 351 - trace_seq_printf(s, "%9llu ", cpu_data->cur_user / divisor); 352 - trace_seq_printf(s, "%9llu ", cpu_data->min_user / divisor); 315 + trace_seq_printf(s, "%9llu ", cpu_data->cur_user); 316 + trace_seq_printf(s, "%9llu ", cpu_data->min_user); 353 317 trace_seq_printf(s, "%9llu ", 354 - (cpu_data->sum_user / cpu_data->user_count) / divisor); 355 - trace_seq_printf(s, "%9llu\n", cpu_data->max_user / divisor); 318 + cpu_data->sum_user / cpu_data->user_count); 319 + trace_seq_printf(s, "%9llu\n", cpu_data->max_user); 356 320 } 357 321 } 358 322 ··· 363 327 timerlat_top_print_sum(struct osnoise_tool *top, struct timerlat_top_cpu *summary) 364 328 { 365 329 const char *split = "----------------------------------------"; 366 - struct timerlat_top_params *params = top->params; 330 + struct timerlat_params *params = top->params; 367 331 unsigned long long count = summary->irq_count; 368 - int divisor = params->output_divisor; 369 332 struct trace_seq *s = top->trace.seq; 370 333 int e = 0; 371 - 372 - if (divisor == 0) 373 - return; 374 334 375 335 /* 376 336 * Skip if no data is available: is this cpu offline? ··· 380 348 } 381 349 382 350 trace_seq_printf(s, "%.*s|%.*s|%.*s", 15, split, 40, split, 39, split); 383 - if (params->user_top) 351 + if (params->user_data) 384 352 trace_seq_printf(s, "-|%.*s", 39, split); 385 353 trace_seq_printf(s, "\n"); 386 354 ··· 390 358 trace_seq_printf(s, " %s %s %s |", no_value, no_value, no_value); 391 359 } else { 392 360 trace_seq_printf(s, " "); 393 - trace_seq_printf(s, "%9llu ", summary->min_irq / params->output_divisor); 394 - trace_seq_printf(s, "%9llu ", (summary->sum_irq / summary->irq_count) / divisor); 395 - trace_seq_printf(s, "%9llu |", summary->max_irq / divisor); 361 + trace_seq_printf(s, "%9llu ", summary->min_irq); 362 + trace_seq_printf(s, "%9llu ", summary->sum_irq / summary->irq_count); 363 + trace_seq_printf(s, "%9llu |", summary->max_irq); 396 364 } 397 365 398 366 if (!summary->thread_count) { 399 367 trace_seq_printf(s, "%s %s %s %s", no_value, no_value, no_value, no_value); 400 368 } else { 401 369 trace_seq_printf(s, " "); 402 - trace_seq_printf(s, "%9llu ", summary->min_thread / divisor); 370 + trace_seq_printf(s, "%9llu ", summary->min_thread); 403 371 trace_seq_printf(s, "%9llu ", 404 - (summary->sum_thread / summary->thread_count) / divisor); 405 - trace_seq_printf(s, "%9llu", summary->max_thread / divisor); 372 + summary->sum_thread / summary->thread_count); 373 + trace_seq_printf(s, "%9llu", summary->max_thread); 406 374 } 407 375 408 - if (!params->user_top) { 376 + if (!params->user_data) { 409 377 trace_seq_printf(s, "\n"); 410 378 return; 411 379 } ··· 416 384 trace_seq_printf(s, " %s %s %s |", no_value, no_value, no_value); 417 385 } else { 418 386 trace_seq_printf(s, " "); 419 - trace_seq_printf(s, "%9llu ", summary->min_user / divisor); 387 + trace_seq_printf(s, "%9llu ", summary->min_user); 420 388 trace_seq_printf(s, "%9llu ", 421 - (summary->sum_user / summary->user_count) / divisor); 422 - trace_seq_printf(s, "%9llu\n", summary->max_user / divisor); 389 + summary->sum_user / summary->user_count); 390 + trace_seq_printf(s, "%9llu\n", summary->max_user); 423 391 } 424 392 } 425 393 ··· 436 404 * timerlat_print_stats - print data for all cpus 437 405 */ 438 406 static void 439 - timerlat_print_stats(struct timerlat_top_params *params, struct osnoise_tool *top) 407 + timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *top) 440 408 { 441 409 struct trace_instance *trace = &top->trace; 442 410 struct timerlat_top_cpu summary; ··· 537 505 /* 538 506 * timerlat_top_parse_args - allocs, parse and fill the cmd line parameters 539 507 */ 540 - static struct timerlat_top_params 508 + static struct timerlat_params 541 509 *timerlat_top_parse_args(int argc, char **argv) 542 510 { 543 - struct timerlat_top_params *params; 511 + struct timerlat_params *params; 544 512 struct trace_events *tevent; 545 513 long long auto_thresh; 546 514 int retval; ··· 722 690 params->user_workload = true; 723 691 /* fallback: -u implies -U */ 724 692 case 'U': 725 - params->user_top = true; 693 + params->user_data = true; 726 694 break; 727 695 case '0': /* trigger */ 728 696 if (params->events) { ··· 797 765 * timerlat_top_apply_config - apply the top configs to the initialized tool 798 766 */ 799 767 static int 800 - timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_top_params *params) 768 + timerlat_top_apply_config(struct osnoise_tool *top, struct timerlat_params *params) 801 769 { 802 770 int retval; 803 - int i; 804 771 805 - if (!params->sleep_time) 806 - params->sleep_time = 1; 807 - 808 - if (params->cpus) { 809 - retval = osnoise_set_cpus(top->context, params->cpus); 810 - if (retval) { 811 - err_msg("Failed to apply CPUs config\n"); 812 - goto out_err; 813 - } 814 - } else { 815 - for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++) 816 - CPU_SET(i, &params->monitored_cpus); 817 - } 818 - 819 - if (params->stop_us) { 820 - retval = osnoise_set_stop_us(top->context, params->stop_us); 821 - if (retval) { 822 - err_msg("Failed to set stop us\n"); 823 - goto out_err; 824 - } 825 - } 826 - 827 - if (params->stop_total_us) { 828 - retval = osnoise_set_stop_total_us(top->context, params->stop_total_us); 829 - if (retval) { 830 - err_msg("Failed to set stop total us\n"); 831 - goto out_err; 832 - } 833 - } 834 - 835 - 836 - if (params->timerlat_period_us) { 837 - retval = osnoise_set_timerlat_period_us(top->context, params->timerlat_period_us); 838 - if (retval) { 839 - err_msg("Failed to set timerlat period\n"); 840 - goto out_err; 841 - } 842 - } 843 - 844 - 845 - if (params->print_stack) { 846 - retval = osnoise_set_print_stack(top->context, params->print_stack); 847 - if (retval) { 848 - err_msg("Failed to set print stack\n"); 849 - goto out_err; 850 - } 851 - } 852 - 853 - if (params->hk_cpus) { 854 - retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), 855 - &params->hk_cpu_set); 856 - if (retval == -1) { 857 - err_msg("Failed to set rtla to the house keeping CPUs\n"); 858 - goto out_err; 859 - } 860 - } else if (params->cpus) { 861 - /* 862 - * Even if the user do not set a house-keeping CPU, try to 863 - * move rtla to a CPU set different to the one where the user 864 - * set the workload to run. 865 - * 866 - * No need to check results as this is an automatic attempt. 867 - */ 868 - auto_house_keeping(&params->monitored_cpus); 869 - } 870 - 871 - /* 872 - * If the user did not specify a type of thread, try user-threads first. 873 - * Fall back to kernel threads otherwise. 874 - */ 875 - if (!params->kernel_workload && !params->user_top) { 876 - retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd"); 877 - if (retval) { 878 - debug_msg("User-space interface detected, setting user-threads\n"); 879 - params->user_workload = 1; 880 - params->user_top = 1; 881 - } else { 882 - debug_msg("User-space interface not detected, setting kernel-threads\n"); 883 - params->kernel_workload = 1; 884 - } 885 - } 886 - 887 - /* 888 - * Set workload according to type of thread if the kernel supports it. 889 - * On kernels without support, user threads will have already failed 890 - * on missing timerlat_fd, and kernel threads do not need it. 891 - */ 892 - retval = osnoise_set_workload(top->context, params->kernel_workload); 893 - if (retval < -1) { 894 - err_msg("Failed to set OSNOISE_WORKLOAD option\n"); 772 + retval = timerlat_apply_config(top, params); 773 + if (retval) 895 774 goto out_err; 896 - } 897 775 898 776 if (isatty(STDOUT_FILENO) && !params->quiet) 899 777 params->pretty_output = 1; ··· 818 876 * timerlat_init_top - initialize a timerlat top tool with parameters 819 877 */ 820 878 static struct osnoise_tool 821 - *timerlat_init_top(struct timerlat_top_params *params) 879 + *timerlat_init_top(struct timerlat_params *params) 822 880 { 823 881 struct osnoise_tool *top; 824 882 int nr_cpus; ··· 866 924 * timerlat_top_set_signals - handles the signal to stop the tool 867 925 */ 868 926 static void 869 - timerlat_top_set_signals(struct timerlat_top_params *params) 927 + timerlat_top_set_signals(struct timerlat_params *params) 870 928 { 871 929 signal(SIGINT, stop_top); 872 930 if (params->duration) { ··· 875 933 } 876 934 } 877 935 936 + /* 937 + * timerlat_top_main_loop - main loop to process events 938 + */ 939 + static int 940 + timerlat_top_main_loop(struct osnoise_tool *top, 941 + struct osnoise_tool *record, 942 + struct timerlat_params *params, 943 + struct timerlat_u_params *params_u) 944 + { 945 + struct trace_instance *trace = &top->trace; 946 + int retval; 947 + 948 + while (!stop_tracing) { 949 + sleep(params->sleep_time); 950 + 951 + if (params->aa_only && !osnoise_trace_is_off(top, record)) 952 + continue; 953 + 954 + retval = tracefs_iterate_raw_events(trace->tep, 955 + trace->inst, 956 + NULL, 957 + 0, 958 + collect_registered_events, 959 + trace); 960 + if (retval < 0) { 961 + err_msg("Error iterating on events\n"); 962 + return retval; 963 + } 964 + 965 + if (!params->quiet) 966 + timerlat_print_stats(params, top); 967 + 968 + if (osnoise_trace_is_off(top, record)) 969 + break; 970 + 971 + /* is there still any user-threads ? */ 972 + if (params->user_workload) { 973 + if (params_u->stopped_running) { 974 + debug_msg("timerlat user space threads stopped!\n"); 975 + break; 976 + } 977 + } 978 + } 979 + 980 + return 0; 981 + } 982 + 983 + /* 984 + * timerlat_top_bpf_main_loop - main loop to process events (BPF variant) 985 + */ 986 + static int 987 + timerlat_top_bpf_main_loop(struct osnoise_tool *top, 988 + struct osnoise_tool *record, 989 + struct timerlat_params *params, 990 + struct timerlat_u_params *params_u) 991 + { 992 + int retval, wait_retval; 993 + 994 + if (params->aa_only) { 995 + /* Auto-analysis only, just wait for stop tracing */ 996 + timerlat_bpf_wait(-1); 997 + return 0; 998 + } 999 + 1000 + if (params->quiet) { 1001 + /* Quiet mode: wait for stop and then, print results */ 1002 + timerlat_bpf_wait(-1); 1003 + 1004 + retval = timerlat_top_bpf_pull_data(top); 1005 + if (retval) { 1006 + err_msg("Error pulling BPF data\n"); 1007 + return retval; 1008 + } 1009 + 1010 + return 0; 1011 + } 1012 + 1013 + /* Pull and display data in a loop */ 1014 + while (!stop_tracing) { 1015 + wait_retval = timerlat_bpf_wait(params->sleep_time); 1016 + 1017 + retval = timerlat_top_bpf_pull_data(top); 1018 + if (retval) { 1019 + err_msg("Error pulling BPF data\n"); 1020 + return retval; 1021 + } 1022 + 1023 + timerlat_print_stats(params, top); 1024 + 1025 + if (wait_retval == 1) 1026 + /* Stopping requested by tracer */ 1027 + break; 1028 + 1029 + /* is there still any user-threads ? */ 1030 + if (params->user_workload) { 1031 + if (params_u->stopped_running) { 1032 + debug_msg("timerlat user space threads stopped!\n"); 1033 + break; 1034 + } 1035 + } 1036 + } 1037 + 1038 + return 0; 1039 + } 1040 + 878 1041 int timerlat_top_main(int argc, char *argv[]) 879 1042 { 880 - struct timerlat_top_params *params; 1043 + struct timerlat_params *params; 881 1044 struct osnoise_tool *record = NULL; 882 1045 struct timerlat_u_params params_u; 883 1046 struct osnoise_tool *top = NULL; ··· 994 947 char *max_lat; 995 948 int retval; 996 949 int nr_cpus, i; 950 + bool no_bpf = false; 997 951 998 952 params = timerlat_top_parse_args(argc, argv); 999 953 if (!params) ··· 1020 972 */ 1021 973 top_inst = trace; 1022 974 975 + if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) { 976 + debug_msg("RTLA_NO_BPF set, disabling BPF\n"); 977 + no_bpf = true; 978 + } 979 + 980 + if (!no_bpf && !tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) { 981 + debug_msg("osnoise:timerlat_sample missing, disabling BPF\n"); 982 + no_bpf = true; 983 + } 984 + 985 + if (!no_bpf) { 986 + retval = timerlat_bpf_init(params); 987 + if (retval) { 988 + debug_msg("Could not enable BPF\n"); 989 + no_bpf = true; 990 + } 991 + } 1023 992 1024 993 retval = enable_timerlat(trace); 1025 994 if (retval) { ··· 1052 987 } 1053 988 } 1054 989 1055 - if (params->cgroup && !params->user_top) { 990 + if (params->cgroup && !params->user_data) { 1056 991 retval = set_comm_cgroup("timerlat/", params->cgroup_name); 1057 992 if (!retval) { 1058 993 err_msg("Failed to move threads to cgroup\n"); ··· 1111 1046 } 1112 1047 1113 1048 if (!params->no_aa) { 1114 - if (params->aa_only) { 1115 - /* as top is not used for display, use it for aa */ 1116 - aa = top; 1117 - } else { 1118 - /* otherwise, a new instance is needed */ 1119 - aa = osnoise_init_tool("timerlat_aa"); 1120 - if (!aa) 1121 - goto out_top; 1122 - } 1049 + aa = osnoise_init_tool("timerlat_aa"); 1050 + if (!aa) 1051 + goto out_top; 1123 1052 1124 1053 retval = timerlat_aa_init(aa, params->dump_tasks); 1125 1054 if (retval) { ··· 1164 1105 */ 1165 1106 if (params->trace_output) 1166 1107 trace_instance_start(&record->trace); 1167 - if (!params->no_aa && aa != top) 1108 + if (!params->no_aa) 1168 1109 trace_instance_start(&aa->trace); 1169 - trace_instance_start(trace); 1110 + if (no_bpf) { 1111 + trace_instance_start(trace); 1112 + } else { 1113 + retval = timerlat_bpf_attach(); 1114 + if (retval) { 1115 + err_msg("Error attaching BPF program\n"); 1116 + goto out_top; 1117 + } 1118 + } 1170 1119 1171 1120 top->start_time = time(NULL); 1172 1121 timerlat_top_set_signals(params); 1173 1122 1174 - while (!stop_tracing) { 1175 - sleep(params->sleep_time); 1123 + if (no_bpf) 1124 + retval = timerlat_top_main_loop(top, record, params, &params_u); 1125 + else 1126 + retval = timerlat_top_bpf_main_loop(top, record, params, &params_u); 1176 1127 1177 - if (params->aa_only && !osnoise_trace_is_off(top, record)) 1178 - continue; 1128 + if (retval) 1129 + goto out_top; 1179 1130 1180 - retval = tracefs_iterate_raw_events(trace->tep, 1181 - trace->inst, 1182 - NULL, 1183 - 0, 1184 - collect_registered_events, 1185 - trace); 1186 - if (retval < 0) { 1187 - err_msg("Error iterating on events\n"); 1188 - goto out_top; 1189 - } 1190 - 1191 - if (!params->quiet) 1192 - timerlat_print_stats(params, top); 1193 - 1194 - if (osnoise_trace_is_off(top, record)) 1195 - break; 1196 - 1197 - /* is there still any user-threads ? */ 1198 - if (params->user_workload) { 1199 - if (params_u.stopped_running) { 1200 - debug_msg("timerlat user space threads stopped!\n"); 1201 - break; 1202 - } 1203 - } 1204 - } 1131 + if (!no_bpf) 1132 + timerlat_bpf_detach(); 1205 1133 1206 1134 if (params->user_workload && !params_u.stopped_running) { 1207 1135 params_u.should_run = 0; ··· 1205 1159 if (!params->no_aa) 1206 1160 timerlat_auto_analysis(params->stop_us, params->stop_total_us); 1207 1161 1208 - if (params->trace_output) { 1209 - printf(" Saving trace to %s\n", params->trace_output); 1210 - save_trace_to_file(record->trace.inst, params->trace_output); 1211 - } 1162 + save_trace_to_file(record ? record->trace.inst : NULL, 1163 + params->trace_output); 1212 1164 } else if (params->aa_only) { 1213 1165 /* 1214 1166 * If the trace did not stop with --aa-only, at least print the
+4
tools/tracing/rtla/src/trace.c
··· 75 75 int out_fd, in_fd; 76 76 int retval = -1; 77 77 78 + if (!inst || !filename) 79 + return 0; 80 + 78 81 in_fd = tracefs_instance_file_open(inst, file, O_RDONLY); 79 82 if (in_fd < 0) { 80 83 err_msg("Failed to open trace file\n"); 81 84 return -1; 82 85 } 83 86 87 + printf(" Saving trace to %s\n", filename); 84 88 out_fd = creat(filename, mode); 85 89 if (out_fd < 0) { 86 90 err_msg("Failed to create output file %s\n", filename);
+66
tools/tracing/rtla/tests/engine.sh
··· 8 8 [ -n "$TEST_COUNT" ] && echo "1..$TEST_COUNT" 9 9 } 10 10 11 + reset_osnoise() { 12 + # Reset osnoise options to default and remove any dangling instances created 13 + # by improperly exited rtla runs. 14 + pushd /sys/kernel/tracing || return 1 15 + 16 + # Remove dangling instances created by previous rtla run 17 + echo 0 > tracing_thresh 18 + cd instances 19 + for i in osnoise_top osnoise_hist timerlat_top timerlat_hist 20 + do 21 + [ ! -d "$i" ] && continue 22 + rmdir "$i" 23 + done 24 + 25 + # Reset options to default 26 + # Note: those are copied from the default values of osnoise_data 27 + # in kernel/trace/trace_osnoise.c 28 + cd ../osnoise 29 + echo all > cpus 30 + echo DEFAULTS > options 31 + echo 1000000 > period_us 32 + echo 0 > print_stack 33 + echo 1000000 > runtime_us 34 + echo 0 > stop_tracing_total_us 35 + echo 0 > stop_tracing_us 36 + echo 1000 > timerlat_period_us 37 + 38 + popd 39 + } 40 + 11 41 check() { 12 42 # Simple check: run rtla with given arguments and test exit code. 13 43 # If TEST_COUNT is set, run the test. Otherwise, just count. 14 44 ctr=$(($ctr + 1)) 15 45 if [ -n "$TEST_COUNT" ] 16 46 then 47 + # Reset osnoise options before running test. 48 + [ "$NO_RESET_OSNOISE" == 1 ] || reset_osnoise 17 49 # Run rtla; in case of failure, include its output as comment 18 50 # in the test results. 19 51 result=$(stdbuf -oL $TIMEOUT "$RTLA" $2 2>&1); exitcode=$? ··· 61 29 fi 62 30 } 63 31 32 + check_with_osnoise_options() { 33 + # Do the same as "check", but with pre-set osnoise options. 34 + # Note: rtla should reset the osnoise options, this is used to test 35 + # if it indeed does so. 36 + # Save original arguments 37 + arg1=$1 38 + arg2=$2 39 + 40 + # Apply osnoise options (if not dry run) 41 + if [ -n "$TEST_COUNT" ] 42 + then 43 + [ "$NO_RESET_OSNOISE" == 1 ] || reset_osnoise 44 + shift 45 + while shift 46 + do 47 + [ "$1" == "" ] && continue 48 + option=$(echo $1 | cut -d '=' -f 1) 49 + value=$(echo $1 | cut -d '=' -f 2) 50 + echo "option: $option, value: $value" 51 + echo "$value" > "/sys/kernel/tracing/osnoise/$option" || return 1 52 + done 53 + fi 54 + 55 + NO_RESET_OSNOISE=1 check "$arg1" "$arg2" 56 + } 57 + 64 58 set_timeout() { 65 59 TIMEOUT="timeout -v -k 15s $1" 66 60 } 67 61 68 62 unset_timeout() { 69 63 unset TIMEOUT 64 + } 65 + 66 + set_no_reset_osnoise() { 67 + NO_RESET_OSNOISE=1 68 + } 69 + 70 + unset_no_reset_osnoise() { 71 + unset NO_RESET_OSNOISE 70 72 } 71 73 72 74 test_end() {
+6
tools/tracing/rtla/tests/osnoise.t
··· 16 16 check "verify the --entries/-E param" \ 17 17 "osnoise hist -P F:1 -c 0 -r 900000 -d 1M -b 10 -E 25" 18 18 19 + # Test setting default period by putting an absurdly high period 20 + # and stopping on threshold. 21 + # If default period is not set, this will time out. 22 + check_with_osnoise_options "apply default period" \ 23 + "osnoise hist -s 1" period_us=600000000 24 + 19 25 test_end
+14
tools/tracing/rtla/tests/timerlat.t
··· 4 4 test_begin 5 5 6 6 set_timeout 2m 7 + timerlat_sample_event='/sys/kernel/tracing/events/osnoise/timerlat_sample' 7 8 9 + if ldd $RTLA | grep libbpf >/dev/null && [ -d "$timerlat_sample_event" ] 10 + then 11 + # rtla build with BPF and system supports BPF mode 12 + no_bpf_options='0 1' 13 + else 14 + no_bpf_options='1' 15 + fi 16 + 17 + # Do every test with and without BPF 18 + for option in $no_bpf_options 19 + do 20 + export RTLA_NO_BPF=$option 8 21 check "verify help page" \ 9 22 "timerlat --help" 10 23 check "verify -s/--stack" \ ··· 36 23 "timerlat hist -c 0 -d 30s" 37 24 check "hist test in nanoseconds" \ 38 25 "timerlat hist -i 2 -c 0 -n -d 30s" 26 + done 39 27 40 28 test_end
+1 -1
tools/verification/rv/Makefile.rv
··· 27 27 28 28 INCLUDE := -Iinclude/ 29 29 CFLAGS := -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(WOPTS) $(EXTRA_CFLAGS) $(INCLUDE) 30 - LDFLAGS := -ggdb $(EXTRA_LDFLAGS) 30 + LDFLAGS := -ggdb $(LDFLAGS) $(EXTRA_LDFLAGS) 31 31 32 32 INSTALL := install 33 33 MKDIR := mkdir