Skip to content

Commit 6b5a2b7

Browse files
committed
Merge tag 'trace-tools-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull RTLA tool updates from Steven Rostedt: - Fix discrepancy in --dump-tasks option Due to a mistake, rtla-timerlat-hist used the CLI syntax "--dump-task" instead of the documented "--dump-tasks". Change the option to match both documentation and the other timerlat tool, rtla-timerlat-top. - Extend coverage of runtime tests Cover both top and hist tools in all applicable test cases, add tests for a few uncovered options, and extend checks for some existing tests. - Add unit tests for actions rtla's actions feature is implemented in its source file and contains non-trivial parsing logic. Cover it with unit tests. - Stop record trace on interrupt Fix a bug where an interval exists after receiving a signal in which the main instance is stopped but the record instance is not, leading to discrepancies in reported results and sometimes rtla hanging. - Restore continue flag in actions_perform() Fix a bug where rtla always continues tracing after hitting a threshold even if the continue action was triggered just once, and add tests verifying that the flag is reset properly. - Migrate command line interface to libsubcmd Replace rtla's argument parsing using getopt_long() with libsubcmd, used by perf and objtool, to reuse existing code and auto-generate better help messages. Extensive unit tests are included to detect regressions. - Add -A/--aligned option to timerlat tools Add an option to align timerlat threads, based on the recently introduced TIMERLAT_ALIGN option of the timerlat tracer, together with unit tests and documentation. - Document tests in README Document how to run unit and runtime tests in rtla's README.txt, including the dependencies needed to run them. * tag 'trace-tools-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: (26 commits) rtla: Document tests in README Documentation/rtla: Add -A/--aligned option rtla/tests: Add unit tests for -A/--aligned option rtla/timerlat: Add -A/--aligned CLI option rtla/tests: Add unit tests for CLI option callbacks rtla/tests: Add unit tests for _parse_args() functions rtla: Parse cmdline using libsubcmd tools subcmd: allow parsing distinct --opt and --no-opt tools subcmd: support optarg as separate argument rtla: Add libsubcmd dependency rtla/tests: Add runtime tests for restoring continue flag rtla/tests: Run runtime tests in temporary directory rtla/tests: Add unit test for restoring continue flag rtla/actions: Restore continue flag in actions_perform() rtla: Stop the record trace on interrupt rtla/tests: Add unit tests for actions module rtla/tests: Add runtime tests for -C/--cgroup rtla/tests: Add runtime test for -k and -u options rtla/tests: Add runtime test for -H/--house-keeping rtla/tests: Cover all hist options in runtime tests ...
2 parents c071a4f + db956bc commit 6b5a2b7

46 files changed

Lines changed: 5591 additions & 1483 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Documentation/tools/rtla/common_appendix.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ EXIT STATUS
2626

2727
::
2828

29-
0 Passed: the test did not hit the stop tracing condition
30-
1 Error: invalid argument
31-
2 Failed: the test hit the stop tracing condition
29+
0 Passed: the test did not hit the stop tracing condition
30+
1 Error: invalid argument
31+
2 Failed: the test hit the stop tracing condition
32+
129 Help: either user requested help or incorrect option was specified
3233

3334
REPORTING BUGS
3435
==============

Documentation/tools/rtla/common_timerlat_options.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,14 @@
9595
* **full** Print the entire stack trace, including unknown addresses.
9696

9797
For unknown addresses, the raw pointer is printed.
98+
99+
**-A**, **--aligned** *us*
100+
101+
Align wake-up of timerlat threads to a set offset in microseconds.
102+
103+
The alignment will be applied when the threads wake up at the start of tracing while
104+
the timer for the first cycle is armed. Each thread sets its timer to the wake-up time
105+
of the previous thread plus the alignment.
106+
107+
This option may be used with any non-negative argument, including zero, which will
108+
align threads so that they wake up all at the same time.

tools/lib/subcmd/parse-options.c

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static int get_value(struct parse_opt_ctx_t *p,
7272
const char *s, *arg = NULL;
7373
const int unset = flags & OPT_UNSET;
7474
int err;
75+
bool force_defval = false;
7576

7677
if (unset && p->opt)
7778
return opterror(opt, "takes no value", flags);
@@ -123,6 +124,42 @@ static int get_value(struct parse_opt_ctx_t *p,
123124
}
124125
}
125126

127+
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
128+
if (!(p->flags & PARSE_OPT_OPTARG_ALLOW_NEXT)) {
129+
/*
130+
* If the option has an optional argument, and the argument is not
131+
* provided in the option itself, do not attempt to get it from
132+
* the next argument, unless PARSE_OPT_OPTARG_ALLOW_NEXT is set.
133+
*
134+
* This prevents a non-option argument from being interpreted as an
135+
* optional argument of a preceding option, for example:
136+
*
137+
* $ cmd --opt val
138+
* -> is "val" argument of "--opt" or a separate non-option
139+
* argument?
140+
*
141+
* With PARSE_OPT_OPTARG_ALLOW_NEXT, "val" is interpreted as
142+
* the argument of "--opt", i.e. the same as "--opt=val".
143+
* Without PARSE_OPT_OPTARG_ALLOW_NEXT, --opt is interpreted
144+
* as having the default value, and "val" as a separate non-option
145+
* argument.
146+
*
147+
* PARSE_OPT_OPTARG_ALLOW_NEXT is useful for commands that take no
148+
* non-option arguments and want to allow more flexibility in
149+
* optional argument passing.
150+
*/
151+
force_defval = true;
152+
}
153+
154+
if (p->argc <= 1 || p->argv[1][0] == '-') {
155+
/*
156+
* If next argument is an option or does not exist,
157+
* use the default value.
158+
*/
159+
force_defval = true;
160+
}
161+
}
162+
126163
if (opt->flags & PARSE_OPT_NOBUILD) {
127164
char reason[128];
128165
bool noarg = false;
@@ -148,7 +185,7 @@ static int get_value(struct parse_opt_ctx_t *p,
148185
noarg = true;
149186
if (opt->flags & PARSE_OPT_NOARG)
150187
noarg = true;
151-
if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
188+
if (force_defval)
152189
noarg = true;
153190

154191
switch (opt->type) {
@@ -212,7 +249,7 @@ static int get_value(struct parse_opt_ctx_t *p,
212249
err = 0;
213250
if (unset)
214251
*(const char **)opt->value = NULL;
215-
else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
252+
else if (force_defval)
216253
*(const char **)opt->value = (const char *)opt->defval;
217254
else
218255
err = get_arg(p, opt, flags, (const char **)opt->value);
@@ -244,7 +281,7 @@ static int get_value(struct parse_opt_ctx_t *p,
244281
return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
245282
if (opt->flags & PARSE_OPT_NOARG)
246283
return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
247-
if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
284+
if (force_defval)
248285
return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
249286
if (get_arg(p, opt, flags, &arg))
250287
return -1;
@@ -255,7 +292,7 @@ static int get_value(struct parse_opt_ctx_t *p,
255292
*(int *)opt->value = 0;
256293
return 0;
257294
}
258-
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
295+
if (force_defval) {
259296
*(int *)opt->value = opt->defval;
260297
return 0;
261298
}
@@ -271,7 +308,7 @@ static int get_value(struct parse_opt_ctx_t *p,
271308
*(unsigned int *)opt->value = 0;
272309
return 0;
273310
}
274-
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
311+
if (force_defval) {
275312
*(unsigned int *)opt->value = opt->defval;
276313
return 0;
277314
}
@@ -289,7 +326,7 @@ static int get_value(struct parse_opt_ctx_t *p,
289326
*(long *)opt->value = 0;
290327
return 0;
291328
}
292-
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
329+
if (force_defval) {
293330
*(long *)opt->value = opt->defval;
294331
return 0;
295332
}
@@ -305,7 +342,7 @@ static int get_value(struct parse_opt_ctx_t *p,
305342
*(unsigned long *)opt->value = 0;
306343
return 0;
307344
}
308-
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
345+
if (force_defval) {
309346
*(unsigned long *)opt->value = opt->defval;
310347
return 0;
311348
}
@@ -321,7 +358,7 @@ static int get_value(struct parse_opt_ctx_t *p,
321358
*(u64 *)opt->value = 0;
322359
return 0;
323360
}
324-
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
361+
if (force_defval) {
325362
*(u64 *)opt->value = opt->defval;
326363
return 0;
327364
}
@@ -390,7 +427,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
390427
return 0;
391428
}
392429
if (!rest) {
393-
if (strstarts(options->long_name, "no-")) {
430+
if (strstarts(options->long_name, "no-") &&
431+
!(options->flags & PARSE_OPT_NOAUTONEG)) {
394432
/*
395433
* The long name itself starts with "no-", so
396434
* accept the option without "no-" so that users
@@ -428,12 +466,12 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
428466
continue;
429467
}
430468
/* negated and abbreviated very much? */
431-
if (strstarts("no-", arg)) {
469+
if (strstarts("no-", arg) && !(options->flags & PARSE_OPT_NOAUTONEG)) {
432470
flags |= OPT_UNSET;
433471
goto is_abbreviated;
434472
}
435473
/* negated? */
436-
if (strncmp(arg, "no-", 3))
474+
if (strncmp(arg, "no-", 3) || (options->flags & PARSE_OPT_NOAUTONEG))
437475
continue;
438476
flags |= OPT_UNSET;
439477
rest = skip_prefix(arg + 3, options->long_name);
@@ -982,7 +1020,8 @@ int parse_options_usage(const char * const *usagestr,
9821020
if (strstarts(opts->long_name, optstr))
9831021
print_option_help(opts, 0);
9841022
if (strstarts("no-", optstr) &&
985-
strstarts(opts->long_name, optstr + 3))
1023+
strstarts(opts->long_name, optstr + 3) &&
1024+
!(opts->flags & PARSE_OPT_NOAUTONEG))
9861025
print_option_help(opts, 0);
9871026
}
9881027

tools/lib/subcmd/parse-options.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum parse_opt_flags {
3333
PARSE_OPT_KEEP_ARGV0 = 4,
3434
PARSE_OPT_KEEP_UNKNOWN = 8,
3535
PARSE_OPT_NO_INTERNAL_HELP = 16,
36+
PARSE_OPT_OPTARG_ALLOW_NEXT = 32,
3637
};
3738

3839
enum parse_opt_option_flags {
@@ -46,6 +47,7 @@ enum parse_opt_option_flags {
4647
PARSE_OPT_NOEMPTY = 128,
4748
PARSE_OPT_NOBUILD = 256,
4849
PARSE_OPT_CANSKIP = 512,
50+
PARSE_OPT_NOAUTONEG = 1024,
4951
};
5052

5153
struct option;
@@ -148,6 +150,8 @@ struct option {
148150
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
149151
#define OPT_CALLBACK(s, l, v, a, h, f) \
150152
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f) }
153+
#define OPT_CALLBACK_FLAG(s, l, v, a, h, f, fl) \
154+
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .flags = (fl) }
151155
#define OPT_CALLBACK_SET(s, l, v, os, a, h, f) \
152156
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .set = check_vtype(os, bool *)}
153157
#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \

tools/tracing/rtla/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
rtla
33
rtla-static
4+
unit_tests
45
fixdep
56
feature
67
FEATURE-DUMP
@@ -9,3 +10,5 @@ custom_filename.txt
910
osnoise_irq_noise_hist.txt
1011
osnoise_trace.txt
1112
timerlat_trace.txt
13+
libsubcmd/
14+
lib/

tools/tracing/rtla/Makefile

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,30 @@ endif
2727
RTLA := $(OUTPUT)rtla
2828
RTLA_IN := $(RTLA)-in.o
2929

30+
LIBSUBCMD_DIR = $(srctree)/tools/lib/subcmd/
31+
ifneq ($(OUTPUT),)
32+
LIBSUBCMD_OUTPUT = $(abspath $(OUTPUT))/libsubcmd
33+
else
34+
LIBSUBCMD_OUTPUT = $(CURDIR)/libsubcmd
35+
endif
36+
LIBSUBCMD = $(LIBSUBCMD_OUTPUT)/libsubcmd.a
37+
LIBSUBCMD_INCLUDES = $(LIBSUBCMD_OUTPUT)/include
38+
LIBSUBCMD_MAKEFLAGS = O=$(LIBSUBCMD_OUTPUT) DESTDIR=$(LIBSUBCMD_OUTPUT) prefix= subdir=
39+
40+
TOOLS_INCLUDES = -I$(srctree)/tools/include
41+
42+
ifneq ($(OUTPUT),)
43+
LIB_OUTPUT = $(abspath $(OUTPUT))/lib
44+
else
45+
LIB_OUTPUT = $(CURDIR)/lib
46+
endif
47+
48+
LIB_STRING = $(LIB_OUTPUT)/string.o
49+
LIB_STRING_SRC = $(srctree)/tools/lib/string.c
50+
51+
LIB_STR_ERROR_R = $(LIB_OUTPUT)/str_error_r.o
52+
LIB_STR_ERROR_R_SRC = $(srctree)/tools/lib/str_error_r.c
53+
3054
VERSION := $(shell sh -c "make -sC ../../.. kernelversion | grep -v make")
3155
DOCSRC := ../../../Documentation/tools/rtla/
3256

@@ -66,7 +90,7 @@ ifeq ($(config),1)
6690
include Makefile.config
6791
endif
6892

69-
CFLAGS += $(INCLUDES) $(LIB_INCLUDES)
93+
CFLAGS += $(INCLUDES) $(LIB_INCLUDES) $(TOOLS_INCLUDES) -I$(LIBSUBCMD_INCLUDES)
7094

7195
export CFLAGS OUTPUT srctree
7296

@@ -93,20 +117,48 @@ tests/bpf/bpf_action_map.o: tests/bpf/bpf_action_map.c
93117
$(Q)echo "BPF skeleton support is disabled, skipping tests/bpf/bpf_action_map.o"
94118
endif
95119

96-
$(RTLA): $(RTLA_IN)
97-
$(QUIET_LINK)$(CC) $(LDFLAGS) -o $(RTLA) $(RTLA_IN) $(EXTLIBS)
120+
$(RTLA): $(RTLA_IN) $(LIBSUBCMD) $(LIB_STRING) $(LIB_STR_ERROR_R)
121+
$(QUIET_LINK)$(CC) $(LDFLAGS) -o $(RTLA) $(RTLA_IN) $(LIBSUBCMD) $(LIB_STRING) $(LIB_STR_ERROR_R) $(EXTLIBS)
98122

99-
static: $(RTLA_IN)
123+
static: $(RTLA_IN) $(LIBSUBCMD) $(LIB_STRING) $(LIB_STR_ERROR_R)
100124
$(eval LDFLAGS += -static)
101-
$(QUIET_LINK)$(CC) -static $(LDFLAGS) -o $(RTLA)-static $(RTLA_IN) $(EXTLIBS)
125+
$(QUIET_LINK)$(CC) -static $(LDFLAGS) -o $(RTLA)-static $(RTLA_IN) $(LIBSUBCMD) $(LIB_STRING) $(LIB_STR_ERROR_R) $(EXTLIBS)
102126

103127
rtla.%: fixdep FORCE
104128
make -f $(srctree)/tools/build/Makefile.build dir=. $@
105129

106-
$(RTLA_IN): fixdep FORCE src/timerlat.skel.h
130+
$(RTLA_IN): fixdep FORCE src/timerlat.skel.h $(LIBSUBCMD_INCLUDES)
107131
make $(build)=rtla
108132

109-
clean: doc_clean fixdep-clean
133+
$(LIBSUBCMD_OUTPUT):
134+
$(Q)$(MKDIR) -p $@
135+
136+
$(LIBSUBCMD_INCLUDES): FORCE | $(LIBSUBCMD_OUTPUT)
137+
$(Q)$(MAKE) -C $(LIBSUBCMD_DIR) $(LIBSUBCMD_MAKEFLAGS) \
138+
install_headers
139+
140+
$(LIBSUBCMD): FORCE | $(LIBSUBCMD_OUTPUT)
141+
$(Q)$(MAKE) -C $(LIBSUBCMD_DIR) $(LIBSUBCMD_MAKEFLAGS) \
142+
$@
143+
144+
$(LIB_OUTPUT):
145+
$(Q)$(MKDIR) -p $@
146+
147+
$(LIB_STR_ERROR_R): $(LIB_STR_ERROR_R_SRC) | $(LIB_OUTPUT)
148+
$(QUIET_CC)$(CC) $(CFLAGS) -c -o $@ $<
149+
150+
$(LIB_STRING): $(LIB_STRING_SRC) | $(LIB_OUTPUT)
151+
$(QUIET_CC)$(CC) $(CFLAGS) -c -o $@ $<
152+
153+
libsubcmd-clean:
154+
$(call QUIET_CLEAN, libsubcmd)
155+
$(Q)$(RM) -r -- $(LIBSUBCMD_OUTPUT)
156+
157+
lib-clean:
158+
$(call QUIET_CLEAN, lib)
159+
$(Q)$(RM) -r -- $(LIB_OUTPUT)
160+
161+
clean: doc_clean fixdep-clean libsubcmd-clean lib-clean
110162
$(call QUIET_CLEAN, rtla)
111163
$(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
112164
$(Q)rm -f rtla rtla-static fixdep FEATURE-DUMP rtla-*

tools/tracing/rtla/README.txt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,34 @@ For development, we suggest the following steps for compiling rtla:
4242
$ make
4343
$ sudo make install
4444

45+
Running tests
46+
47+
RTLA has two test suites: a runtime test suite and a unit test suite.
48+
49+
The runtime test suite is available as "make check" (root required) and has
50+
the following dependencies, in addition to RTLA build dependencies:
51+
52+
- Perl
53+
- Test::Harness (libtest-harness-perl on Debian/Ubuntu, perl-Test-Harness on Fedora/RHEL)
54+
- bash
55+
- coreutils
56+
- ldd
57+
- util-linux
58+
- procps(-ng)
59+
- bpftool (if rtla is built against libbpf)
60+
61+
as well as the following required system configuration:
62+
63+
- CONFIG_OSNOISE_TRACER=y
64+
- CONFIG_TIMERLAT_TRACER=y
65+
- tracefs mounted and readable at /sys/kernel/tracing
66+
67+
The unit test suite is available as "make unit-tests" and has the following
68+
dependencies:
69+
70+
- libcheck
71+
72+
Unlike the runtime test suite, root is not required to run unit tests, nor is
73+
a tracefs/osnoise/timerlat-capable kernel required.
74+
4575
For further information, please refer to the rtla man page.

tools/tracing/rtla/src/Build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ rtla-y += timerlat_hist.o
1111
rtla-y += timerlat_u.o
1212
rtla-y += timerlat_aa.o
1313
rtla-y += timerlat_bpf.o
14-
rtla-y += rtla.o
14+
rtla-y += cli.o

tools/tracing/rtla/src/actions.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ actions_perform(struct actions *self)
247247
int pid, retval;
248248
const struct action *action;
249249

250+
self->continue_flag = false;
251+
250252
for_each_action(self, action) {
251253
switch (action->type) {
252254
case ACTION_TRACE_OUTPUT:

0 commit comments

Comments
 (0)