summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-19 14:00:15 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-19 14:00:15 -0700
commit3793b558ff3b1cae64a3eddb497ab9e5636bf022 (patch)
treef63886c002647346e7dfbf78e10ed9d03baff282
parent55ee4b931a7ffedc886175d265dd6e6d08fd4151 (diff)
parent0ad45018ace734e3a21c8b15280df65b429135d1 (diff)
Merge tag 'trace-tools-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull RTLA updates from Steven Rostedt: - Extend support for unsetting CLI options libsubcmd auto-generates "--no-<option>" to unset options, provided the option callback supports it. Implement this for RTLA CLI beyond boolean options, and document the few exceptions that are left out. - Test all tracer options in runtime tests Verify that RTLA sets osnoise/timerlat options correctly by reading them from tracefs during runtime tests. - Improve range validation for option arguments Make CLI range validation consistent with the kernel limits and unify implementation and error messages between options. - Improve invalid option argument parsing Consistently reject invalid values for numeric option arguments with a unified error message for all options. * tag 'trace-tools-v7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: rtla/cli: Unify and improve handling of invalid option arguments rtla/cli: Unify and improve range validation logic rtla/tests: Test all tracer options in runtime tests Documentation/rtla: Document unsetting options rtla: Add unit tests for CLI with unset rtla: Add unit tests for unset in opt callbacks rtla: Allow unsetting non-list custom-callback CLI options
-rw-r--r--Documentation/tools/rtla/common_appendix.txt17
-rw-r--r--Documentation/tools/rtla/common_options.txt13
-rw-r--r--Documentation/tools/rtla/common_osnoise_options.txt4
-rw-r--r--Documentation/tools/rtla/common_timerlat_options.txt4
-rw-r--r--tools/tracing/rtla/src/cli.c42
-rw-r--r--tools/tracing/rtla/src/cli_p.h497
-rw-r--r--tools/tracing/rtla/tests/engine.sh39
-rw-r--r--tools/tracing/rtla/tests/hwnoise.t3
-rw-r--r--tools/tracing/rtla/tests/osnoise.t39
-rwxr-xr-xtools/tracing/rtla/tests/scripts/check-osnoise-option.sh16
-rwxr-xr-xtools/tracing/rtla/tests/scripts/check-tracefs-value.sh11
-rw-r--r--tools/tracing/rtla/tests/timerlat.t40
-rw-r--r--tools/tracing/rtla/tests/unit/cli_opt_callback.c534
-rw-r--r--tools/tracing/rtla/tests/unit/osnoise_hist_cli.c18
-rw-r--r--tools/tracing/rtla/tests/unit/osnoise_top_cli.c18
-rw-r--r--tools/tracing/rtla/tests/unit/timerlat_hist_cli.c18
-rw-r--r--tools/tracing/rtla/tests/unit/timerlat_top_cli.c18
17 files changed, 948 insertions, 383 deletions
diff --git a/Documentation/tools/rtla/common_appendix.txt b/Documentation/tools/rtla/common_appendix.txt
index 68cb15840d3a..ad610ed02a24 100644
--- a/Documentation/tools/rtla/common_appendix.txt
+++ b/Documentation/tools/rtla/common_appendix.txt
@@ -1,5 +1,22 @@
.. SPDX-License-Identifier: GPL-2.0
+UNSETTING OPTIONS
+=================
+
+The effect of most command line options can be reverted by prepending "no-" to
+the long variant of the option, for example:
+
+$ rtla timerlat top -p 100 --no-period
+
+resets the period back to the default value of 1000 us.
+
+If a command line option sets multiple RTLA parameters at once, the inverted
+option will revert all of them, even if they were not set by the particular
+option. For example, since using "--auto" implies "--trace", specifying
+"--trace --no-auto" will also disable trace output, just like if "--no-trace"
+was specified.
+
+
SIGINT BEHAVIOR
===============
diff --git a/Documentation/tools/rtla/common_options.txt b/Documentation/tools/rtla/common_options.txt
index 6caa51d02934..38da1cf443a4 100644
--- a/Documentation/tools/rtla/common_options.txt
+++ b/Documentation/tools/rtla/common_options.txt
@@ -22,10 +22,14 @@
Enable an event in the trace (**-t**) session. The argument can be a specific event, e.g., **-e** *sched:sched_switch*, or all events of a system group, e.g., **-e** *sched*. Multiple **-e** are allowed. It is only active when **-t** or **-a** are set.
+ This option cannot be unset.
+
**--filter** *<filter>*
Filter the previous **-e** *sys:event* event with *<filter>*. For further information about event filtering see https://www.kernel.org/doc/html/latest/trace/events.html#event-filtering.
+ This option cannot be unset.
+
**--trigger** *<trigger>*
Enable a trace event trigger to the previous **-e** *sys:event*.
If the *hist:* trigger is activated, the output histogram will be automatically saved to a file named *system_event_hist.txt*.
@@ -37,6 +41,8 @@
For further information about event trigger see https://www.kernel.org/doc/html/latest/trace/events.html#event-triggers.
+ This option cannot be unset.
+
**-P**, **--priority** *o:prio|r:prio|f:prio|d:runtime:period*
Set scheduling parameters to the |tool| tracer threads, the format to set the priority are:
@@ -78,7 +84,8 @@
Saves trace output, optionally taking a filename. Alternative to -t/--trace.
Note that unlike -t/--trace, specifying this multiple times will result in
- the trace being saved multiple times.
+ the trace being saved multiple times, and --no-trace will not disable trace
+ output when enabled through this option.
- *signal,num=<sig>,pid=<pid>*
@@ -107,6 +114,8 @@
|actionsperf|
+ This option cannot be unset.
+
**--on-end** *action*
Defines an action to be executed at the end of tracing.
@@ -124,6 +133,8 @@
This runs rtla with the default options, and saves trace output at the end.
+ This option cannot be unset.
+
**-h**, **--help**
Print help menu.
diff --git a/Documentation/tools/rtla/common_osnoise_options.txt b/Documentation/tools/rtla/common_osnoise_options.txt
index bd3c4f499193..5fc70c001615 100644
--- a/Documentation/tools/rtla/common_osnoise_options.txt
+++ b/Documentation/tools/rtla/common_osnoise_options.txt
@@ -24,11 +24,15 @@
Stop the trace if a single sample is higher than the argument in microseconds.
If **-T** is set, it will also save the trace to the output.
+ This option cannot be unset.
+
**-S**, **--stop-total** *us*
Stop the trace if the total sample is higher than the argument in microseconds.
If **-T** is set, it will also save the trace to the output.
+ This option cannot be unset.
+
**-T**, **--threshold** *us*
Specify the minimum delta between two time reads to be considered noise.
diff --git a/Documentation/tools/rtla/common_timerlat_options.txt b/Documentation/tools/rtla/common_timerlat_options.txt
index 100840f4c0ed..e36898438a0b 100644
--- a/Documentation/tools/rtla/common_timerlat_options.txt
+++ b/Documentation/tools/rtla/common_timerlat_options.txt
@@ -23,10 +23,14 @@
Stop trace if the *IRQ* latency is higher than the argument in us.
+ This option cannot be unset.
+
**-T**, **--thread** *us*
Stop trace if the *Thread* latency is higher than the argument in us.
+ This option cannot be unset.
+
**-s**, **--stack** *us*
Save the stack trace at the *IRQ* if a *Thread* latency is higher than the
diff --git a/tools/tracing/rtla/src/cli.c b/tools/tracing/rtla/src/cli.c
index c5279c987531..fb8c972c0746 100644
--- a/tools/tracing/rtla/src/cli.c
+++ b/tools/tracing/rtla/src/cli.c
@@ -192,10 +192,10 @@ struct common_params *osnoise_hist_parse_args(int argc, char **argv)
actions_init(&params->common.threshold_actions);
actions_init(&params->common.end_actions);
- /* display data in microseconds */
- params->common.output_divisor = 1000;
- params->common.hist.bucket_size = 1;
- params->common.hist.entries = 256;
+ /* set default values */
+ params->common.output_divisor = default_output_divisor;
+ params->common.hist.bucket_size = default_bucket_size;
+ params->common.hist.entries = default_entries;
argc = parse_options(argc, (const char **)argv,
osnoise_hist_options, osnoise_hist_usage,
@@ -280,19 +280,15 @@ struct common_params *timerlat_top_parse_args(int argc, char **argv)
actions_init(&params->common.threshold_actions);
actions_init(&params->common.end_actions);
- /* disabled by default */
- params->dma_latency = -1;
- params->deepest_idle_state = -2;
-
- /* display data in microseconds */
- params->common.output_divisor = 1000;
+ /* set default values */
+ params->dma_latency = default_dma_latency;
+ params->deepest_idle_state = default_deepest_idle_state;
+ params->common.output_divisor = default_output_divisor;
+ params->stack_format = default_stack_format;
/* default to BPF mode */
params->mode = TRACING_MODE_BPF;
- /* default to truncate stack format */
- params->stack_format = STACK_FORMAT_TRUNCATE;
-
argc = parse_options(argc, (const char **)argv,
timerlat_top_options, timerlat_top_usage,
common_parse_options_flags);
@@ -403,23 +399,17 @@ struct common_params *timerlat_hist_parse_args(int argc, char **argv)
actions_init(&params->common.threshold_actions);
actions_init(&params->common.end_actions);
- /* disabled by default */
- params->dma_latency = -1;
-
- /* disabled by default */
- params->deepest_idle_state = -2;
-
- /* display data in microseconds */
- params->common.output_divisor = 1000;
- params->common.hist.bucket_size = 1;
- params->common.hist.entries = 256;
+ /* set default values */
+ params->dma_latency = default_dma_latency;
+ params->deepest_idle_state = default_deepest_idle_state;
+ params->common.output_divisor = default_output_divisor;
+ params->common.hist.bucket_size = default_bucket_size;
+ params->common.hist.entries = default_entries;
+ params->stack_format = default_stack_format;
/* default to BPF mode */
params->mode = TRACING_MODE_BPF;
- /* default to truncate stack format */
- params->stack_format = STACK_FORMAT_TRUNCATE;
-
argc = parse_options(argc, (const char **)argv,
timerlat_hist_options, timerlat_hist_usage,
common_parse_options_flags);
diff --git a/tools/tracing/rtla/src/cli_p.h b/tools/tracing/rtla/src/cli_p.h
index 3c939de9abf0..661240d44ad9 100644
--- a/tools/tracing/rtla/src/cli_p.h
+++ b/tools/tracing/rtla/src/cli_p.h
@@ -5,6 +5,8 @@
#error "Private header file included outside of cli.c module"
#endif
+#include <errno.h>
+#include <limits.h>
#include <linux/kernel.h>
#include <subcmd/parse-options.h>
@@ -23,6 +25,111 @@ struct timerlat_cb_data {
};
/*
+ * Non-zero default values for parameters
+ */
+static const int default_dma_latency = -1; /* -1 = unset */
+static const int default_deepest_idle_state = -2; /* -1 = disable all, -2 = unset */
+static const int default_output_divisor = 1000;
+static const int default_bucket_size = 1;
+static const int default_entries = 256;
+static const enum stack_format default_stack_format = STACK_FORMAT_TRUNCATE;
+
+/*
+ * Range checking for long long and int option callbacks.
+ *
+ * Pass a pointer to a const struct as opt->data to enable range checking.
+ * If opt->data is NULL, no range check is performed.
+ */
+struct llong_range {
+ long long min;
+ long long max;
+};
+
+struct int_range {
+ int min;
+ int max;
+};
+
+#define LLONG_RANGE(lo, hi) \
+ (&(const struct llong_range){ .min = (lo), .max = (hi) })
+
+#define INT_RANGE(lo, hi) \
+ (&(const struct int_range){ .min = (lo), .max = (hi) })
+
+static int check_llong_range(const struct option *opt, long long value)
+{
+ const struct llong_range *range = opt->data;
+
+ if (!range)
+ return 0;
+ if (value < range->min || value > range->max) {
+ fprintf(stderr, " Error: --%s value %lld is out of range [%lld, %lld]\n",
+ opt->long_name, value, range->min, range->max);
+ return -1;
+ }
+ return 0;
+}
+
+static int check_int_range(const struct option *opt, int value)
+{
+ const struct int_range *range = opt->data;
+
+ if (!range)
+ return 0;
+ if (value < range->min || value > range->max) {
+ fprintf(stderr, " Error: --%s value %d is out of range [%d, %d]\n",
+ opt->long_name, value, range->min, range->max);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * OPT_CALLBACK variant that populates .data (for range checking).
+ */
+#define RTLA_OPT_CALLBACK_DATA(s, l, v, a, h, f, d) \
+ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
+ .value = (v), .argh = (a), .help = (h), .callback = (f), \
+ .data = (void *)(d) }
+
+#define RTLA_OPT_CALLBACK_DATA_DEFVAL(s, l, v, a, h, f, d, dv) \
+ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
+ .value = (v), .argh = (a), .help = (h), .callback = (f), \
+ .data = (void *)(d), .defval = (intptr_t)(dv) }
+
+/*
+ * Shorthand macros for integer/long long command line options using
+ * opt_int_callback/opt_llong_callback, with variants that set defval
+ * and/or data (for range checking).
+ *
+ * Note: defval's type is intptr_t. opt_int_callback interprets it directly as
+ * an int, opt_llong_callback interprets it as a pointer to a long long, as
+ * long long does not fit into intptr_t on 32-bit architectures.
+ */
+#define RTLA_OPT_LLONG(s, l, v, a, h) \
+ OPT_CALLBACK(s, l, v, a, h, opt_llong_callback)
+
+#define RTLA_OPT_LLONG_DEFVAL(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
+ .short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
+ .help = (h), .callback = opt_llong_callback, .defval = (intptr_t)(d) }
+
+#define RTLA_OPT_LLONG_DATA(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
+ .short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
+ .help = (h), .callback = opt_llong_callback, .data = (void *)(d) }
+
+#define RTLA_OPT_INT(s, l, v, a, h) \
+ OPT_CALLBACK(s, l, v, a, h, opt_int_callback)
+
+#define RTLA_OPT_INT_DEFVAL(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
+ .short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
+ .help = (h), .callback = opt_int_callback, .defval = (intptr_t)(d) }
+
+#define RTLA_OPT_INT_DATA_DEFVAL(s, l, v, a, h, d, dv) { .type = OPTION_CALLBACK, \
+ .short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
+ .help = (h), .callback = opt_int_callback, \
+ .data = (void *)(d), .defval = (intptr_t)(dv) }
+
+/*
* Macros for command line options common to all tools
*
* Note: Some of the options are common to both timerlat and osnoise, but
@@ -108,14 +215,12 @@ struct timerlat_cb_data {
#define RTLA_OPT_QUIET OPT_BOOLEAN('q', "quiet", &params->common.quiet, \
"print only a summary at the end")
-#define RTLA_OPT_TRACE_BUFFER_SIZE OPT_CALLBACK(0, "trace-buffer-size", \
+#define RTLA_OPT_TRACE_BUFFER_SIZE RTLA_OPT_INT(0, "trace-buffer-size", \
&params->common.buffer_size, "kB", \
- "set the per-cpu trace buffer size in kB", \
- opt_int_callback)
+ "set the per-cpu trace buffer size in kB")
-#define RTLA_OPT_WARM_UP OPT_CALLBACK(0, "warm-up", &params->common.warmup, "s", \
- "let the workload run for s seconds before collecting data", \
- opt_int_callback)
+#define RTLA_OPT_WARM_UP RTLA_OPT_INT(0, "warm-up", &params->common.warmup, "s", \
+ "let the workload run for s seconds before collecting data")
#define RTLA_OPT_AUTO(cb) OPT_CALLBACK('a', "auto", &cb_data, "us", \
"set automatic trace mode, stopping the session if argument in us sample is hit", \
@@ -136,6 +241,41 @@ struct timerlat_cb_data {
"print debug info")
/*
+ * Helper functions for parsing numeric option arguments.
+ */
+static void opt_err(const struct option *opt, const char *arg, const char *msg)
+{
+ fprintf(stderr, " Error: --%s: '%s' %s\n", opt->long_name, arg, msg);
+}
+
+static int strtoll_safe(const struct option *opt, const char *arg, long long *value)
+{
+ long long tmp;
+ char *end;
+
+ errno = 0;
+ tmp = strtoll(arg, &end, 10);
+ if (errno || *end || end == arg) {
+ opt_err(opt, arg, "is not a valid number");
+ return -1;
+ }
+ *value = tmp;
+ return 0;
+}
+
+static int strtoi_safe(const struct option *opt, const char *arg, int *value)
+{
+ int tmp;
+
+ if (strtoi(arg, &tmp)) {
+ opt_err(opt, arg, "is not a valid number");
+ return -1;
+ }
+ *value = tmp;
+ return 0;
+}
+
+/*
* Common callback functions for command line options
*/
@@ -143,10 +283,18 @@ static int opt_llong_callback(const struct option *opt, const char *arg, int uns
{
long long *value = opt->value;
- if (unset || !arg)
+ if (unset) {
+ *value = opt->defval ? *(long long *)opt->defval : 0;
+ return 0;
+ }
+
+ if (!arg)
return -1;
- *value = get_llong_from_str((char *)arg);
+ if (strtoll_safe(opt, arg, value))
+ return -1;
+ if (check_llong_range(opt, *value))
+ return -1;
return 0;
}
@@ -154,10 +302,17 @@ static int opt_int_callback(const struct option *opt, const char *arg, int unset
{
int *value = opt->value;
- if (unset || !arg)
+ if (unset) {
+ *value = (int)opt->defval;
+ return 0;
+ }
+
+ if (!arg)
return -1;
- if (strtoi(arg, value))
+ if (strtoi_safe(opt, arg, value))
+ return -1;
+ if (check_int_range(opt, *value))
return -1;
return 0;
@@ -168,12 +323,20 @@ static int opt_cpus_cb(const struct option *opt, const char *arg, int unset)
struct common_params *params = opt->value;
int retval;
- if (unset || !arg)
+ if (unset) {
+ CPU_ZERO(&params->monitored_cpus);
+ params->cpus = NULL;
+ return 0;
+ }
+
+ if (!arg)
return -1;
retval = parse_cpu_set((char *)arg, &params->monitored_cpus);
- if (retval)
- fatal("Invalid -c cpu list");
+ if (retval) {
+ opt_err(opt, arg, "is not a valid cpu set");
+ return -1;
+ }
params->cpus = (char *)arg;
return 0;
@@ -183,8 +346,11 @@ static int opt_cgroup_cb(const struct option *opt, const char *arg, int unset)
{
struct common_params *params = opt->value;
- if (unset)
- return -1;
+ if (unset) {
+ params->cgroup = 0;
+ params->cgroup_name = NULL;
+ return 0;
+ }
params->cgroup = 1;
params->cgroup_name = (char *)arg;
@@ -199,12 +365,19 @@ static int opt_duration_cb(const struct option *opt, const char *arg, int unset)
{
struct common_params *params = opt->value;
- if (unset || !arg)
+ if (unset) {
+ params->duration = 0;
+ return 0;
+ }
+
+ if (!arg)
return -1;
params->duration = parse_seconds_duration((char *)arg);
- if (!params->duration)
- fatal("Invalid -d duration");
+ if (!params->duration) {
+ opt_err(opt, arg, "is not a valid duration");
+ return -1;
+ }
return 0;
}
@@ -233,13 +406,21 @@ static int opt_housekeeping_cb(const struct option *opt, const char *arg, int un
struct common_params *params = opt->value;
int retval;
- if (unset || !arg)
+ if (unset) {
+ params->hk_cpus = 0;
+ CPU_ZERO(&params->hk_cpu_set);
+ return 0;
+ }
+
+ if (!arg)
return -1;
params->hk_cpus = 1;
retval = parse_cpu_set((char *)arg, &params->hk_cpu_set);
- if (retval)
- fatal("Error parsing house keeping CPUs");
+ if (retval) {
+ opt_err(opt, arg, "is not a valid cpu set");
+ return -1;
+ }
return 0;
}
@@ -249,12 +430,20 @@ static int opt_priority_cb(const struct option *opt, const char *arg, int unset)
struct common_params *params = opt->value;
int retval;
- if (unset || !arg)
+ if (unset) {
+ memset(&params->sched_param, 0, sizeof(params->sched_param));
+ params->set_sched = 0;
+ return 0;
+ }
+
+ if (!arg)
return -1;
retval = parse_prio((char *)arg, &params->sched_param);
- if (retval == -1)
- fatal("Invalid -P priority");
+ if (retval == -1) {
+ opt_err(opt, arg, "is not a valid priority");
+ return -1;
+ }
params->set_sched = 1;
return 0;
@@ -267,8 +456,10 @@ static int opt_trigger_cb(const struct option *opt, const char *arg, int unset)
if (unset || !arg)
return -1;
- if (!*events)
- fatal("--trigger requires a previous -e");
+ if (!*events) {
+ opt_err(opt, arg, "has no previous event to apply to");
+ return -1;
+ }
trace_event_add_trigger(*events, (char *)arg);
@@ -282,8 +473,10 @@ static int opt_filter_cb(const struct option *opt, const char *arg, int unset)
if (unset || !arg)
return -1;
- if (!*events)
- fatal("--filter requires a previous -e");
+ if (!*events) {
+ opt_err(opt, arg, "has no previous event to apply to");
+ return -1;
+ }
trace_event_add_filter(*events, (char *)arg);
@@ -293,17 +486,16 @@ static int opt_filter_cb(const struct option *opt, const char *arg, int unset)
/*
* Macros for command line options specific to osnoise
*/
-#define OSNOISE_OPT_PERIOD OPT_CALLBACK('p', "period", &params->period, "us", \
+#define OSNOISE_OPT_PERIOD RTLA_OPT_LLONG_DATA('p', "period", &params->period, "us", \
"osnoise period in us", \
- opt_osnoise_period_cb)
+ LLONG_RANGE(1, 10000000))
-#define OSNOISE_OPT_RUNTIME OPT_CALLBACK('r', "runtime", &params->runtime, "us", \
+#define OSNOISE_OPT_RUNTIME RTLA_OPT_LLONG_DATA('r', "runtime", &params->runtime, "us", \
"osnoise runtime in us", \
- opt_osnoise_runtime_cb)
+ LLONG_RANGE(100, LLONG_MAX))
-#define OSNOISE_OPT_THRESHOLD OPT_CALLBACK('T', "threshold", &params->threshold, "us", \
- "the minimum delta to be considered a noise", \
- opt_llong_callback)
+#define OSNOISE_OPT_THRESHOLD RTLA_OPT_LLONG('T', "threshold", &params->threshold, "us", \
+ "the minimum delta to be considered a noise")
/*
* Callback functions for command line options for osnoise tools
@@ -315,10 +507,18 @@ static int opt_osnoise_auto_cb(const struct option *opt, const char *arg, int un
struct osnoise_params *params = cb_data->params;
long long auto_thresh;
- if (unset || !arg)
+ if (unset) {
+ params->common.stop_us = 0;
+ params->threshold = 0;
+ cb_data->trace_output = NULL;
+ return 0;
+ }
+
+ if (!arg)
return -1;
- auto_thresh = get_llong_from_str((char *)arg);
+ if (strtoll_safe(opt, arg, &auto_thresh))
+ return -1;
params->common.stop_us = auto_thresh;
params->threshold = 1;
@@ -328,40 +528,14 @@ static int opt_osnoise_auto_cb(const struct option *opt, const char *arg, int un
return 0;
}
-static int opt_osnoise_period_cb(const struct option *opt, const char *arg, int unset)
-{
- unsigned long long *period = opt->value;
-
- if (unset || !arg)
- return -1;
-
- *period = get_llong_from_str((char *)arg);
- if (*period > 10000000)
- fatal("Period longer than 10 s");
-
- return 0;
-}
-
-static int opt_osnoise_runtime_cb(const struct option *opt, const char *arg, int unset)
-{
- unsigned long long *runtime = opt->value;
-
- if (unset || !arg)
- return -1;
-
- *runtime = get_llong_from_str((char *)arg);
- if (*runtime < 100)
- fatal("Runtime shorter than 100 us");
-
- return 0;
-}
-
static int opt_osnoise_trace_output_cb(const struct option *opt, const char *arg, int unset)
{
const char **trace_output = opt->value;
- if (unset)
- return -1;
+ if (unset) {
+ *trace_output = NULL;
+ return 0;
+ }
if (!arg) {
*trace_output = "osnoise_trace.txt";
@@ -384,8 +558,10 @@ static int opt_osnoise_on_threshold_cb(const struct option *opt, const char *arg
return -1;
retval = actions_parse(actions, (char *)arg, "osnoise_trace.txt");
- if (retval)
- fatal("Invalid action %s", arg);
+ if (retval) {
+ opt_err(opt, arg, "is not a valid action");
+ return -1;
+ }
return 0;
}
@@ -399,8 +575,10 @@ static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int
return -1;
retval = actions_parse(actions, (char *)arg, "osnoise_trace.txt");
- if (retval)
- fatal("Invalid action %s", arg);
+ if (retval) {
+ opt_err(opt, arg, "is not a valid action");
+ return -1;
+ }
return 0;
}
@@ -408,26 +586,26 @@ static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int
/*
* Macros for command line options specific to timerlat
*/
-#define TIMERLAT_OPT_PERIOD OPT_CALLBACK('p', "period", &params->timerlat_period_us, "us", \
+#define TIMERLAT_OPT_PERIOD RTLA_OPT_LLONG_DATA('p', "period", &params->timerlat_period_us, "us", \
"timerlat period in us", \
- opt_timerlat_period_cb)
+ LLONG_RANGE(100, 1000000))
-#define TIMERLAT_OPT_STACK OPT_CALLBACK('s', "stack", &params->print_stack, "us", \
- "save the stack trace at the IRQ if a thread latency is higher than the argument in us", \
- opt_llong_callback)
+#define TIMERLAT_OPT_STACK RTLA_OPT_LLONG('s', "stack", &params->print_stack, "us", \
+ "save the stack trace at the IRQ if a thread latency is higher than the argument in us")
#define TIMERLAT_OPT_NANO OPT_CALLBACK_NOOPT('n', "nano", params, NULL, \
"display data in nanoseconds", \
opt_nano_cb)
-#define TIMERLAT_OPT_DMA_LATENCY OPT_CALLBACK(0, "dma-latency", &params->dma_latency, "us", \
+#define TIMERLAT_OPT_DMA_LATENCY RTLA_OPT_INT_DATA_DEFVAL(0, "dma-latency", \
+ &params->dma_latency, "us", \
"set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency", \
- opt_dma_latency_cb)
+ INT_RANGE(0, 10000), default_dma_latency)
-#define TIMERLAT_OPT_DEEPEST_IDLE_STATE OPT_CALLBACK(0, "deepest-idle-state", \
+#define TIMERLAT_OPT_DEEPEST_IDLE_STATE RTLA_OPT_INT_DATA_DEFVAL(0, "deepest-idle-state", \
&params->deepest_idle_state, "n", \
"only go down to idle state n on cpus used by timerlat to reduce exit from idle latency", \
- opt_int_callback)
+ INT_RANGE(-1, INT_MAX), default_deepest_idle_state)
#define TIMERLAT_OPT_AA_ONLY OPT_CALLBACK(0, "aa-only", params, "us", \
"stop if <us> latency is hit, only printing the auto analysis (reduces CPU usage)", \
@@ -447,38 +625,33 @@ static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int
"set the stack format (truncate, skip, full)", \
opt_stack_format_cb)
-#define TIMERLAT_OPT_ALIGNED OPT_CALLBACK('A', "aligned", params, "us", \
+#define TIMERLAT_OPT_ALIGNED RTLA_OPT_CALLBACK_DATA('A', "aligned", params, "us", \
"align thread wakeups to a specific offset", \
- opt_timerlat_align_cb)
+ opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX))
/*
* Callback functions for command line options for timerlat tools
*/
-static int opt_timerlat_period_cb(const struct option *opt, const char *arg, int unset)
-{
- long long *period = opt->value;
-
- if (unset || !arg)
- return -1;
-
- *period = get_llong_from_str((char *)arg);
- if (*period > 1000000)
- fatal("Period longer than 1 s");
-
- return 0;
-}
-
static int opt_timerlat_auto_cb(const struct option *opt, const char *arg, int unset)
{
struct timerlat_cb_data *cb_data = opt->value;
struct timerlat_params *params = cb_data->params;
long long auto_thresh;
- if (unset || !arg)
+ if (unset) {
+ params->common.stop_total_us = 0;
+ params->common.stop_us = 0;
+ params->print_stack = 0;
+ cb_data->trace_output = NULL;
+ return 0;
+ }
+
+ if (!arg)
return -1;
- auto_thresh = get_llong_from_str((char *)arg);
+ if (strtoll_safe(opt, arg, &auto_thresh))
+ return -1;
params->common.stop_total_us = auto_thresh;
params->common.stop_us = auto_thresh;
params->print_stack = auto_thresh;
@@ -489,32 +662,24 @@ static int opt_timerlat_auto_cb(const struct option *opt, const char *arg, int u
return 0;
}
-static int opt_dma_latency_cb(const struct option *opt, const char *arg, int unset)
-{
- int *dma_latency = opt->value;
- int retval;
-
- if (unset || !arg)
- return -1;
-
- retval = strtoi((char *)arg, dma_latency);
- if (retval)
- fatal("Invalid -dma-latency %s", arg);
- if (*dma_latency < 0 || *dma_latency > 10000)
- fatal("--dma-latency needs to be >= 0 and <= 10000");
-
- return 0;
-}
-
static int opt_aa_only_cb(const struct option *opt, const char *arg, int unset)
{
struct timerlat_params *params = opt->value;
long long auto_thresh;
- if (unset || !arg)
+ if (unset) {
+ params->common.stop_total_us = 0;
+ params->common.stop_us = 0;
+ params->print_stack = 0;
+ params->common.aa_only = 0;
+ return 0;
+ }
+
+ if (!arg)
return -1;
- auto_thresh = get_llong_from_str((char *)arg);
+ if (strtoll_safe(opt, arg, &auto_thresh))
+ return -1;
params->common.stop_total_us = auto_thresh;
params->common.stop_us = auto_thresh;
params->print_stack = auto_thresh;
@@ -527,8 +692,10 @@ static int opt_timerlat_trace_output_cb(const struct option *opt, const char *ar
{
const char **trace_output = opt->value;
- if (unset)
- return -1;
+ if (unset) {
+ *trace_output = NULL;
+ return 0;
+ }
if (!arg) {
*trace_output = "timerlat_trace.txt";
@@ -551,8 +718,10 @@ static int opt_timerlat_on_threshold_cb(const struct option *opt, const char *ar
return -1;
retval = actions_parse(actions, (char *)arg, "timerlat_trace.txt");
- if (retval)
- fatal("Invalid action %s", arg);
+ if (retval) {
+ opt_err(opt, arg, "is not a valid action");
+ return -1;
+ }
return 0;
}
@@ -566,8 +735,10 @@ static int opt_timerlat_on_end_cb(const struct option *opt, const char *arg, int
return -1;
retval = actions_parse(actions, (char *)arg, "timerlat_trace.txt");
- if (retval)
- fatal("Invalid action %s", arg);
+ if (retval) {
+ opt_err(opt, arg, "is not a valid action");
+ return -1;
+ }
return 0;
}
@@ -576,8 +747,11 @@ static int opt_user_threads_cb(const struct option *opt, const char *arg, int un
{
struct timerlat_params *params = opt->value;
- if (unset)
- return -1;
+ if (unset) {
+ params->common.user_workload = false;
+ params->common.user_data = false;
+ return 0;
+ }
params->common.user_workload = true;
params->common.user_data = true;
@@ -589,8 +763,10 @@ static int opt_nano_cb(const struct option *opt, const char *arg, int unset)
{
struct timerlat_params *params = opt->value;
- if (unset)
- return -1;
+ if (unset) {
+ params->common.output_divisor = default_output_divisor;
+ return 0;
+ }
params->common.output_divisor = 1;
@@ -601,13 +777,20 @@ static int opt_stack_format_cb(const struct option *opt, const char *arg, int un
{
int *format = opt->value;
- if (unset || !arg)
+ if (unset) {
+ *format = default_stack_format;
+ return 0;
+ }
+
+ if (!arg)
return -1;
*format = parse_stack_format((char *)arg);
- if (*format == -1)
- fatal("Invalid --stack-format option");
+ if (*format == -1) {
+ opt_err(opt, arg, "is not a valid stack format");
+ return -1;
+ }
return 0;
}
@@ -615,12 +798,24 @@ static int opt_stack_format_cb(const struct option *opt, const char *arg, int un
static int opt_timerlat_align_cb(const struct option *opt, const char *arg, int unset)
{
struct timerlat_params *params = opt->value;
+ long long val;
- if (unset || !arg)
+ if (unset) {
+ params->timerlat_align = false;
+ params->timerlat_align_us = 0;
+ return 0;
+ }
+
+ if (!arg)
+ return -1;
+
+ if (strtoll_safe(opt, arg, &val))
+ return -1;
+ if (check_llong_range(opt, val))
return -1;
params->timerlat_align = true;
- params->timerlat_align_us = get_llong_from_str((char *)arg);
+ params->timerlat_align_us = val;
return 0;
}
@@ -629,14 +824,15 @@ static int opt_timerlat_align_cb(const struct option *opt, const char *arg, int
* Macros for command line options specific to histogram-based tools
*/
-#define HIST_OPT_BUCKET_SIZE OPT_CALLBACK('b', "bucket-size", \
+#define HIST_OPT_BUCKET_SIZE RTLA_OPT_INT_DATA_DEFVAL('b', "bucket-size", \
&params->common.hist.bucket_size, "N", \
"set the histogram bucket size (default 1)", \
- opt_bucket_size_cb)
+ INT_RANGE(1, 999999), default_bucket_size)
-#define HIST_OPT_ENTRIES OPT_CALLBACK('E', "entries", &params->common.hist.entries, "N", \
+#define HIST_OPT_ENTRIES RTLA_OPT_INT_DATA_DEFVAL('E', "entries", \
+ &params->common.hist.entries, "N", \
"set the number of entries of the histogram (default 256)", \
- opt_entries_cb)
+ INT_RANGE(10, 9999999), default_entries)
#define HIST_OPT_NO_IRQ OPT_BOOLEAN_FLAG(0, "no-irq", &params->common.hist.no_irq, \
"ignore IRQ latencies", PARSE_OPT_NOAUTONEG)
@@ -656,32 +852,3 @@ static int opt_timerlat_align_cb(const struct option *opt, const char *arg, int
#define HIST_OPT_WITH_ZEROS OPT_BOOLEAN(0, "with-zeros", &params->common.hist.with_zeros, \
"print zero only entries")
-/* Histogram-specific callbacks */
-
-static int opt_bucket_size_cb(const struct option *opt, const char *arg, int unset)
-{
- int *bucket_size = opt->value;
-
- if (unset || !arg)
- return -1;
-
- *bucket_size = get_llong_from_str((char *)arg);
- if (*bucket_size == 0 || *bucket_size >= 1000000)
- fatal("Bucket size needs to be > 0 and <= 1000000");
-
- return 0;
-}
-
-static int opt_entries_cb(const struct option *opt, const char *arg, int unset)
-{
- int *entries = opt->value;
-
- if (unset || !arg)
- return -1;
-
- *entries = get_llong_from_str((char *)arg);
- if (*entries < 10 || *entries > 9999999)
- fatal("Entries must be > 10 and < 10000000");
-
- return 0;
-}
diff --git a/tools/tracing/rtla/tests/engine.sh b/tools/tracing/rtla/tests/engine.sh
index 5bf8453d354d..4287cd64ac31 100644
--- a/tools/tracing/rtla/tests/engine.sh
+++ b/tools/tracing/rtla/tests/engine.sh
@@ -98,30 +98,37 @@ check() {
}
check_with_osnoise_options() {
- # Do the same as "check", but with pre-set osnoise options.
- # Note: rtla should reset the osnoise options, this is used to test
- # if it indeed does so.
- # Save original arguments
- arg1=$1
- arg2=$2
- arg3=$3
+ # Do the same as "check", but with pre-set tracefs options.
+ # Resets osnoise first, then writes the given tracefs option=value
+ # pairs before running the check with NO_RESET_OSNOISE=1.
+ # Arguments: test_name command exit_code expected_output [path=value ...]
+ # Each path is relative to /sys/kernel/tracing/
+ local arg1=$1
+ local arg2=$2
+ local arg3=$3
+ local arg4=$4
+ local opt option value
- # Apply osnoise options (if not dry run)
+ # Apply tracefs options (if not dry run)
if [ -n "$TEST_COUNT" ]
then
[ "$NO_RESET_OSNOISE" == 1 ] || reset_osnoise
- shift
- shift
- while shift
+ shift 4
+ for opt in "$@"
do
- [ "$1" == "" ] && continue
- option=$(echo $1 | cut -d '=' -f 1)
- value=$(echo $1 | cut -d '=' -f 2)
- echo "$value" > "/sys/kernel/tracing/osnoise/$option" || return 1
+ [ -z "$opt" ] && continue
+ option="${opt%%=*}"
+ value="${opt#*=}"
+ # Try to apply the option, ignore errors: when pre-setting fails
+ # (e.g. kernel does not know the option), the test itself will likely
+ # also fail.
+ # Throwing an error here would cause the test to be incorrectly
+ # skipped.
+ echo "$value" > "/sys/kernel/tracing/$option"
done
fi
- NO_RESET_OSNOISE=1 check "$arg1" "$arg2" "$arg3"
+ NO_RESET_OSNOISE=1 check "$arg1" "$arg2" "$arg3" "$arg4"
}
check_top_hist() {
diff --git a/tools/tracing/rtla/tests/hwnoise.t b/tools/tracing/rtla/tests/hwnoise.t
index cfe687ff5ee1..b53d8d440fc5 100644
--- a/tools/tracing/rtla/tests/hwnoise.t
+++ b/tools/tracing/rtla/tests/hwnoise.t
@@ -18,5 +18,8 @@ check "stop the trace if a single sample is higher than 1 us" \
check "enable a trace event trigger" \
"hwnoise -t -e osnoise:irq_noise --trigger=\"hist:key=desc,duration:sort=desc,duration:vals=hitcount\" -d 10s" \
0 "Saving event osnoise:irq_noise hist to osnoise_irq_noise_hist.txt"
+check "verify OSNOISE_IRQ_DISABLE" \
+ "hwnoise -S 1 --on-threshold shell,command=\"$testdir/scripts/check-osnoise-option.sh OSNOISE_IRQ_DISABLE\"" \
+ 2 "^OSNOISE_IRQ_DISABLE=enabled$"
test_end
diff --git a/tools/tracing/rtla/tests/osnoise.t b/tools/tracing/rtla/tests/osnoise.t
index 346a14a860c8..214fd40fc610 100644
--- a/tools/tracing/rtla/tests/osnoise.t
+++ b/tools/tracing/rtla/tests/osnoise.t
@@ -32,7 +32,7 @@ check "hist with -b/--bucket-size" \
check "hist with -E/--entries" \
"osnoise hist -E 10 -d 1s"
check "hist with -E/--entries out of range" \
- "osnoise hist -E 1 -d 1s" 1 "^Entries must be > 10 and < 10000000$"
+ "osnoise hist -E 1 -d 1s" 129 "out of range \[10, 9999999\]"
check "hist with --no-header" \
"osnoise hist --no-header -d 1s" 0 "" "RTLA osnoise histogram"
check "hist with --with-zeros" \
@@ -42,11 +42,40 @@ check "hist with --no-index" \
check "hist with --no-summary" \
"osnoise hist --no-summary -d 1s" 0 "" "^count:"
-# Test setting default period by putting an absurdly high period
-# and stopping on threshold.
-# If default period is not set, this will time out.
+# Tracer option tests - verify that rtla correctly sets tracefs options
+# Default tests: poison tracefs with wrong values, verify rtla resets to defaults
check_with_osnoise_options "apply default period" \
- "osnoise hist -s 1" 2 period_us=600000000
+ "osnoise top -q -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/period_us\"" \
+ 2 "^osnoise/period_us=1000000$" osnoise/period_us=600000000
+check_with_osnoise_options "apply default runtime" \
+ "osnoise top -q -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/runtime_us\"" \
+ 2 "^osnoise/runtime_us=1000000$" osnoise/runtime_us=100
+check_with_osnoise_options "apply default tracing_thresh" \
+ "osnoise top -q -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh tracing_thresh\"" \
+ 2 "^tracing_thresh=0$" tracing_thresh=999999
+check_with_osnoise_options "apply default stop_tracing_us" \
+ "osnoise top -q -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_us\"" \
+ 2 "^osnoise/stop_tracing_us=0$" osnoise/stop_tracing_us=999999
+check_with_osnoise_options "apply default stop_tracing_total_us" \
+ "osnoise top -q -s 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_total_us\"" \
+ 2 "^osnoise/stop_tracing_total_us=0$" osnoise/stop_tracing_total_us=999999
+
+# Non-default tracer option tests: verify CLI options correctly set tracefs values
+check_top_q_hist "verify -p sets period_us" \
+ "osnoise TOOL -p 2000000 -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/period_us\"" \
+ 2 "^osnoise/period_us=2000000$"
+check_top_q_hist "verify -r sets runtime_us" \
+ "osnoise TOOL -r 500000 -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/runtime_us\"" \
+ 2 "^osnoise/runtime_us=500000$"
+check_top_q_hist "verify -T sets tracing_thresh" \
+ "osnoise TOOL -T 5 -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh tracing_thresh\"" \
+ 2 "^tracing_thresh=5$"
+check_top_q_hist "verify -s sets stop_tracing_us" \
+ "osnoise TOOL -s 30 -S 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_us\"" \
+ 2 "^osnoise/stop_tracing_us=30$"
+check_top_q_hist "verify -S sets stop_tracing_total_us" \
+ "osnoise TOOL -S 100 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_total_us\"" \
+ 2 "^osnoise/stop_tracing_total_us=100$"
# Actions tests
check_top_q_hist "trace output through -t with custom filename" \
diff --git a/tools/tracing/rtla/tests/scripts/check-osnoise-option.sh b/tools/tracing/rtla/tests/scripts/check-osnoise-option.sh
new file mode 100755
index 000000000000..37c62268cc15
--- /dev/null
+++ b/tools/tracing/rtla/tests/scripts/check-osnoise-option.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Check if osnoise options are enabled or disabled.
+# Usage: check-osnoise-option.sh <OPTION1> [<OPTION2> ...]
+# Output: one line per option in the format "OPTION=enabled" or "OPTION=disabled"
+
+options=$(tr ' ' '\n' < /sys/kernel/tracing/osnoise/options)
+for name in "$@"; do
+ if echo "$options" | grep -q "^NO_${name}$"; then
+ echo "$name=disabled"
+ elif echo "$options" | grep -q "^${name}$"; then
+ echo "$name=enabled"
+ else
+ echo "$name=unsupported"
+ fi
+done
diff --git a/tools/tracing/rtla/tests/scripts/check-tracefs-value.sh b/tools/tracing/rtla/tests/scripts/check-tracefs-value.sh
new file mode 100755
index 000000000000..12d0eacd6a85
--- /dev/null
+++ b/tools/tracing/rtla/tests/scripts/check-tracefs-value.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Read tracefs values and print them.
+# Usage: check-tracefs-value.sh <relative_path1> [<relative_path2> ...]
+# Each path is relative to /sys/kernel/tracing/
+# Output: one line per file in the format "path=value"
+
+for file in "$@"; do
+ read value < "/sys/kernel/tracing/$file"
+ echo "$file=$value"
+done
diff --git a/tools/tracing/rtla/tests/timerlat.t b/tools/tracing/rtla/tests/timerlat.t
index 8193048e8c8c..5116857d7da4 100644
--- a/tools/tracing/rtla/tests/timerlat.t
+++ b/tools/tracing/rtla/tests/timerlat.t
@@ -55,13 +55,51 @@ check_top_q_hist "verify -k/--kernel-threads" \
check_top_q_hist "verify -u/--user-threads" \
"timerlat TOOL -u -c 0 -d 10s -T 1 --on-threshold shell,command=$testdir/scripts/check-user-kernel-threads.sh" 2 "0 kernel threads, 1 user threads"
+# Tracer option tests - verify that rtla correctly sets tracefs options
+# Default tests: poison tracefs with wrong values, verify rtla resets to defaults
+check_with_osnoise_options "apply default timerlat_period_us" \
+ "timerlat top -q -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/timerlat_period_us\"" \
+ 2 "^osnoise/timerlat_period_us=1000$" osnoise/timerlat_period_us=999999
+check_with_osnoise_options "apply default print_stack" \
+ "timerlat top -q -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/print_stack\"" \
+ 2 "^osnoise/print_stack=0$" osnoise/print_stack=999999
+check_with_osnoise_options "apply default stop_tracing_us" \
+ "timerlat top -q -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_us\"" \
+ 2 "^osnoise/stop_tracing_us=0$" osnoise/stop_tracing_us=999999
+check_with_osnoise_options "apply default stop_tracing_total_us" \
+ "timerlat top -q -i 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_total_us\"" \
+ 2 "^osnoise/stop_tracing_total_us=0$" osnoise/stop_tracing_total_us=999999
+
+# Non-default tracer option tests: verify CLI options correctly set tracefs values
+check_top_q_hist "verify -p sets timerlat_period_us" \
+ "timerlat TOOL -p 2000 -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/timerlat_period_us\"" \
+ 2 "^osnoise/timerlat_period_us=2000$"
+check_top_q_hist "verify -s sets print_stack" \
+ "timerlat TOOL -s 5 -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/print_stack\"" \
+ 2 "^osnoise/print_stack=5$"
+check_top_q_hist "verify -i sets stop_tracing_us" \
+ "timerlat TOOL -i 2 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_us\"" \
+ 2 "^osnoise/stop_tracing_us=2$"
+check_top_q_hist "verify -T sets stop_tracing_total_us" \
+ "timerlat TOOL -T 2 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/stop_tracing_total_us\"" \
+ 2 "^osnoise/stop_tracing_total_us=2$"
+check_with_osnoise_options "apply default TIMERLAT_ALIGN" \
+ "timerlat top -q -T 1 --on-threshold shell,command=\"$testdir/scripts/check-osnoise-option.sh TIMERLAT_ALIGN\"" \
+ 2 "^TIMERLAT_ALIGN=disabled$" osnoise/options=TIMERLAT_ALIGN
+check_top_q_hist "verify -A sets TIMERLAT_ALIGN" \
+ "timerlat TOOL -A 100 -T 1 --on-threshold shell,command=\"$testdir/scripts/check-osnoise-option.sh TIMERLAT_ALIGN\"" \
+ 2 "^TIMERLAT_ALIGN=enabled$"
+check_top_q_hist "verify -A sets timerlat_align_us" \
+ "timerlat TOOL -A 100 -T 1 --on-threshold shell,command=\"$testdir/scripts/check-tracefs-value.sh osnoise/timerlat_align_us\"" \
+ 2 "^osnoise/timerlat_align_us=100$"
+
# Histogram tests
check "hist with -b/--bucket-size" \
"timerlat hist -b 1 -d 1s"
check "hist with -E/--entries" \
"timerlat hist -E 10 -d 1s"
check "hist with -E/--entries out of range" \
- "timerlat hist -E 1 -d 1s" 1 "^Entries must be > 10 and < 10000000$"
+ "timerlat hist -E 1 -d 1s" 129 "out of range \[10, 9999999\]"
check "hist with --no-header" \
"timerlat hist --no-header -d 1s" 0 "" "RTLA timerlat histogram"
check "hist with --with-zeros" \
diff --git a/tools/tracing/rtla/tests/unit/cli_opt_callback.c b/tools/tracing/rtla/tests/unit/cli_opt_callback.c
index 4a406af42821..70e2576b1336 100644
--- a/tools/tracing/rtla/tests/unit/cli_opt_callback.c
+++ b/tools/tracing/rtla/tests/unit/cli_opt_callback.c
@@ -9,6 +9,12 @@
#include "cli_params_assert.h"
#define TEST_CALLBACK(value, cb) OPT_CALLBACK('t', "test", value, "test value", "test help", cb)
+#define TEST_LLONG_RANGE(value, lo, hi) \
+ RTLA_OPT_CALLBACK_DATA('t', "test", value, "test value", "test help", \
+ opt_llong_callback, LLONG_RANGE(lo, hi))
+#define TEST_INT_RANGE(value, lo, hi) \
+ RTLA_OPT_CALLBACK_DATA('t', "test", value, "test value", "test help", \
+ opt_int_callback, INT_RANGE(lo, hi))
START_TEST(test_opt_llong_callback_simple)
{
@@ -40,6 +46,52 @@ START_TEST(test_opt_llong_callback_min)
}
END_TEST
+START_TEST(test_opt_llong_callback_non_numeric)
+{
+ long long test_value = 0;
+ const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
+
+ assert(freopen("/dev/null", "w", stderr));
+ ck_assert_int_eq(opt_llong_callback(&opt, "abc", 0), -1);
+ ck_assert_int_eq(test_value, 0);
+}
+END_TEST
+
+START_TEST(test_opt_llong_callback_non_numeric_suffix)
+{
+ long long test_value = 0;
+ const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
+
+ assert(freopen("/dev/null", "w", stderr));
+ ck_assert_int_eq(opt_llong_callback(&opt, "1234567890abc", 0), -1);
+ ck_assert_int_eq(test_value, 0);
+}
+END_TEST
+
+START_TEST(test_opt_llong_callback_unset)
+{
+ long long test_value = 0;
+ const struct option opt = TEST_CALLBACK(&test_value, opt_llong_callback);
+
+ ck_assert_int_eq(opt_llong_callback(&opt, "1234567890", 0), 0);
+ ck_assert_int_eq(opt_llong_callback(&opt, NULL, 1), 0);
+ ck_assert_int_eq(test_value, 0);
+}
+END_TEST
+
+START_TEST(test_opt_llong_callback_unset_defval)
+{
+ long long test_value = 0;
+ const long long default_value = 42;
+ const struct option opt = RTLA_OPT_LLONG_DEFVAL('t', "test", &test_value, "test value",
+ "test help", &default_value);
+
+ ck_assert_int_eq(opt_llong_callback(&opt, "1234567890", 0), 0);
+ ck_assert_int_eq(opt_llong_callback(&opt, NULL, 1), 0);
+ ck_assert_int_eq(test_value, default_value);
+}
+END_TEST
+
START_TEST(test_opt_int_callback_simple)
{
int test_value = 0;
@@ -75,6 +127,7 @@ START_TEST(test_opt_int_callback_non_numeric)
int test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
+ assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_int_callback(&opt, "abc", 0), -1);
ck_assert_int_eq(test_value, 0);
}
@@ -85,11 +138,119 @@ START_TEST(test_opt_int_callback_non_numeric_suffix)
int test_value = 0;
const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
+ assert(freopen("/dev/null", "w", stderr));
ck_assert_int_eq(opt_int_callback(&opt, "1234567890abc", 0), -1);
ck_assert_int_eq(test_value, 0);
}
END_TEST
+START_TEST(test_opt_int_callback_unset)
+{
+ int test_value = 0;
+ const struct option opt = TEST_CALLBACK(&test_value, opt_int_callback);
+
+ ck_assert_int_eq(opt_int_callback(&opt, "1234567890", 0), 0);
+ ck_assert_int_eq(opt_int_callback(&opt, NULL, 1), 0);
+ ck_assert_int_eq(test_value, 0);
+}
+END_TEST
+
+START_TEST(test_opt_int_callback_unset_defval)
+{
+ int test_value = 0;
+ const struct option opt = RTLA_OPT_INT_DEFVAL('t', "test", &test_value, "test value",
+ "test help", 42);
+
+ ck_assert_int_eq(opt_int_callback(&opt, "1234567890", 0), 0);
+ ck_assert_int_eq(opt_int_callback(&opt, NULL, 1), 0);
+ ck_assert_int_eq(test_value, 42);
+}
+END_TEST
+
+START_TEST(test_opt_llong_callback_range_in)
+{
+ long long test_value = 0;
+ const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
+
+ ck_assert_int_eq(opt_llong_callback(&opt, "50", 0), 0);
+ ck_assert_int_eq(test_value, 50);
+}
+END_TEST
+
+START_TEST(test_opt_llong_callback_range_below)
+{
+ long long test_value = 0;
+ const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
+
+ assert(freopen("/dev/null", "w", stderr));
+ ck_assert_int_eq(opt_llong_callback(&opt, "9", 0), -1);
+}
+END_TEST
+
+START_TEST(test_opt_llong_callback_range_above)
+{
+ long long test_value = 0;
+ const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
+
+ assert(freopen("/dev/null", "w", stderr));
+ ck_assert_int_eq(opt_llong_callback(&opt, "101", 0), -1);
+}
+END_TEST
+
+START_TEST(test_opt_llong_callback_range_boundary)
+{
+ long long test_value = 0;
+ const struct option opt = TEST_LLONG_RANGE(&test_value, 10, 100);
+
+ ck_assert_int_eq(opt_llong_callback(&opt, "10", 0), 0);
+ ck_assert_int_eq(test_value, 10);
+ ck_assert_int_eq(opt_llong_callback(&opt, "100", 0), 0);
+ ck_assert_int_eq(test_value, 100);
+}
+END_TEST
+
+START_TEST(test_opt_int_callback_range_in)
+{
+ int test_value = 0;
+ const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
+
+ ck_assert_int_eq(opt_int_callback(&opt, "5000", 0), 0);
+ ck_assert_int_eq(test_value, 5000);
+}
+END_TEST
+
+START_TEST(test_opt_int_callback_range_below)
+{
+ int test_value = 0;
+ const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
+
+ assert(freopen("/dev/null", "w", stderr));
+ ck_assert_int_eq(opt_int_callback(&opt, "-1", 0), -1);
+}
+END_TEST
+
+START_TEST(test_opt_int_callback_range_above)
+{
+ int test_value = 0;
+ const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
+
+ assert(freopen("/dev/null", "w", stderr));
+ ck_assert_int_eq(opt_int_callback(&opt, "10001", 0), -1);
+}
+END_TEST
+
+START_TEST(test_opt_int_callback_range_boundary)
+{
+ int test_value = 0;
+ const struct option opt = TEST_INT_RANGE(&test_value, 0, 10000);
+
+ ck_assert_int_eq(opt_int_callback(&opt, "0", 0), 0);
+ ck_assert_int_eq(test_value, 0);
+ ck_assert_int_eq(opt_int_callback(&opt, "10000", 0), 0);
+ ck_assert_int_eq(test_value, 10000);
+}
+END_TEST
+
START_TEST(test_opt_cpus_cb)
{
struct common_params params = {0};
@@ -108,7 +269,7 @@ START_TEST(test_opt_cpus_cb_invalid)
nr_cpus = 4;
assert(freopen("/dev/null", "w", stderr));
- opt_cpus_cb(&opt, "0-3,5", 0);
+ ck_assert_int_eq(opt_cpus_cb(&opt, "0-3,5", 0), -1);
}
END_TEST
@@ -134,6 +295,18 @@ START_TEST(test_opt_cgroup_cb_equals)
}
END_TEST
+START_TEST(test_opt_cgroup_cb_unset)
+{
+ struct common_params params = {0};
+ const struct option opt = TEST_CALLBACK(&params, opt_cgroup_cb);
+
+ ck_assert_int_eq(opt_cgroup_cb(&opt, "cgroup", 0), 0);
+ ck_assert_int_eq(opt_cgroup_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.cgroup, 0);
+ ck_assert_ptr_null(params.cgroup_name);
+}
+END_TEST
+
START_TEST(test_opt_duration_cb)
{
struct common_params params = {0};
@@ -150,7 +323,18 @@ START_TEST(test_opt_duration_cb_invalid)
const struct option opt = TEST_CALLBACK(&params, opt_duration_cb);
assert(freopen("/dev/null", "w", stderr));
- opt_duration_cb(&opt, "abc", 0);
+ ck_assert_int_eq(opt_duration_cb(&opt, "abc", 0), -1);
+}
+END_TEST
+
+START_TEST(test_opt_duration_cb_unset)
+{
+ struct common_params params = {0};
+ const struct option opt = TEST_CALLBACK(&params, opt_duration_cb);
+
+ ck_assert_int_eq(opt_duration_cb(&opt, "1m", 0), 0);
+ ck_assert_int_eq(opt_duration_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.duration, 0);
}
END_TEST
@@ -201,7 +385,20 @@ START_TEST(test_opt_housekeeping_cb_invalid)
nr_cpus = 4;
assert(freopen("/dev/null", "w", stderr));
- opt_housekeeping_cb(&opt, "0-3,5", 0);
+ ck_assert_int_eq(opt_housekeeping_cb(&opt, "0-3,5", 0), -1);
+}
+END_TEST
+
+START_TEST(test_opt_housekeeping_cb_unset)
+{
+ struct common_params params = {0};
+ const struct option opt = TEST_CALLBACK(&params, opt_housekeeping_cb);
+
+ nr_cpus = 4;
+ ck_assert_int_eq(opt_housekeeping_cb(&opt, "0-3", 0), 0);
+ ck_assert_int_eq(opt_housekeeping_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.hk_cpus, 0);
+ ck_assert_int_eq(CPU_COUNT(&params.hk_cpu_set), 0);
}
END_TEST
@@ -222,7 +419,19 @@ START_TEST(test_opt_priority_cb_invalid)
const struct option opt = TEST_CALLBACK(&params, opt_priority_cb);
assert(freopen("/dev/null", "w", stderr));
- opt_priority_cb(&opt, "abc", 0);
+ ck_assert_int_eq(opt_priority_cb(&opt, "abc", 0), -1);
+}
+END_TEST
+
+START_TEST(test_opt_priority_cb_unset)
+{
+ struct common_params params = {0};
+ const struct option opt = TEST_CALLBACK(&params, opt_priority_cb);
+
+ ck_assert_int_eq(opt_priority_cb(&opt, "f:95", 0), 0);
+ ck_assert_int_eq(opt_priority_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.sched_param.sched_policy, 0);
+ ck_assert_int_eq(params.sched_param.sched_priority, 0);
}
END_TEST
@@ -242,7 +451,7 @@ START_TEST(test_opt_trigger_cb_no_event)
const struct option opt = TEST_CALLBACK(&events, opt_trigger_cb);
assert(freopen("/dev/null", "w", stderr));
- opt_trigger_cb(&opt, "stacktrace", 0);
+ ck_assert_int_eq(opt_trigger_cb(&opt, "stacktrace", 0), -1);
}
END_TEST
@@ -262,7 +471,7 @@ START_TEST(test_opt_filter_cb_no_event)
const struct option opt = TEST_CALLBACK(&events, opt_filter_cb);
assert(freopen("/dev/null", "w", stderr));
- opt_filter_cb(&opt, "comm ~ \"rtla\"", 0);
+ ck_assert_int_eq(opt_filter_cb(&opt, "comm ~ \"rtla\"", 0), -1);
}
END_TEST
@@ -279,45 +488,20 @@ START_TEST(test_opt_osnoise_auto_cb)
}
END_TEST
-START_TEST(test_opt_osnoise_period_cb)
-{
- unsigned long long period = 0;
- const struct option opt = TEST_CALLBACK(&period, opt_osnoise_period_cb);
-
- ck_assert_int_eq(opt_osnoise_period_cb(&opt, "1000000", 0), 0);
- ck_assert_int_eq(period, 1000000);
-}
-END_TEST
-
-START_TEST(test_opt_osnoise_period_cb_invalid)
-{
- unsigned long long period = 0;
- const struct option opt = TEST_CALLBACK(&period, opt_osnoise_period_cb);
-
- assert(freopen("/dev/null", "w", stderr));
- opt_osnoise_period_cb(&opt, "10000001", 0);
-}
-END_TEST
-
-START_TEST(test_opt_osnoise_runtime_cb)
+START_TEST(test_opt_osnoise_auto_cb_unset)
{
- unsigned long long runtime = 0;
- const struct option opt = TEST_CALLBACK(&runtime, opt_osnoise_runtime_cb);
+ struct osnoise_params params = {0};
+ struct osnoise_cb_data cb_data = {&params};
+ const struct option opt = TEST_CALLBACK(&cb_data, opt_osnoise_auto_cb);
- ck_assert_int_eq(opt_osnoise_runtime_cb(&opt, "900000", 0), 0);
- ck_assert_int_eq(runtime, 900000);
+ ck_assert_int_eq(opt_osnoise_auto_cb(&opt, "10", 0), 0);
+ ck_assert_int_eq(opt_osnoise_auto_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.common.stop_us, 0);
+ ck_assert_int_eq(params.threshold, 0);
+ ck_assert_ptr_null(cb_data.trace_output);
}
END_TEST
-START_TEST(test_opt_osnoise_runtime_cb_invalid)
-{
- unsigned long long runtime = 0;
- const struct option opt = TEST_CALLBACK(&runtime, opt_osnoise_runtime_cb);
-
- assert(freopen("/dev/null", "w", stderr));
- opt_osnoise_runtime_cb(&opt, "99", 0);
-}
-END_TEST
START_TEST(test_opt_osnoise_trace_output_cb)
{
@@ -339,6 +523,17 @@ START_TEST(test_opt_osnoise_trace_output_cb_noarg)
}
END_TEST
+START_TEST(test_opt_osnoise_trace_output_cb_unset)
+{
+ const char *trace_output = NULL;
+ const struct option opt = TEST_CALLBACK(&trace_output, opt_osnoise_trace_output_cb);
+
+ ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, "trace.txt", 0), 0);
+ ck_assert_int_eq(opt_osnoise_trace_output_cb(&opt, NULL, 1), 0);
+ ck_assert_ptr_null(trace_output);
+}
+END_TEST
+
START_TEST(test_opt_osnoise_on_threshold_cb)
{
struct actions actions = {0};
@@ -357,7 +552,7 @@ START_TEST(test_opt_osnoise_on_threshold_cb_invalid)
const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_threshold_cb);
assert(freopen("/dev/null", "w", stderr));
- opt_osnoise_on_threshold_cb(&opt, "abc", 0);
+ ck_assert_int_eq(opt_osnoise_on_threshold_cb(&opt, "abc", 0), -1);
}
END_TEST
@@ -379,27 +574,7 @@ START_TEST(test_opt_osnoise_on_end_cb_invalid)
const struct option opt = TEST_CALLBACK(&actions, opt_osnoise_on_end_cb);
assert(freopen("/dev/null", "w", stderr));
- opt_osnoise_on_end_cb(&opt, "abc", 0);
-}
-END_TEST
-
-START_TEST(test_opt_timerlat_period_cb)
-{
- long long period = 0;
- const struct option opt = TEST_CALLBACK(&period, opt_timerlat_period_cb);
-
- ck_assert_int_eq(opt_timerlat_period_cb(&opt, "1000", 0), 0);
- ck_assert_int_eq(period, 1000);
-}
-END_TEST
-
-START_TEST(test_opt_timerlat_period_cb_invalid)
-{
- long long period = 0;
- const struct option opt = TEST_CALLBACK(&period, opt_timerlat_period_cb);
-
- assert(freopen("/dev/null", "w", stderr));
- opt_timerlat_period_cb(&opt, "1000001", 0);
+ ck_assert_int_eq(opt_osnoise_on_end_cb(&opt, "abc", 0), -1);
}
END_TEST
@@ -417,35 +592,21 @@ START_TEST(test_opt_timerlat_auto_cb)
}
END_TEST
-START_TEST(test_opt_dma_latency_cb)
-{
- int dma_latency = 0;
- const struct option opt = TEST_CALLBACK(&dma_latency, opt_dma_latency_cb);
-
- ck_assert_int_eq(opt_dma_latency_cb(&opt, "1000", 0), 0);
- ck_assert_int_eq(dma_latency, 1000);
-}
-END_TEST
-
-START_TEST(test_opt_dma_latency_cb_min)
+START_TEST(test_opt_timerlat_auto_cb_unset)
{
- int dma_latency = 0;
- const struct option opt = TEST_CALLBACK(&dma_latency, opt_dma_latency_cb);
+ struct timerlat_params params = {0};
+ struct timerlat_cb_data cb_data = {&params};
+ const struct option opt = TEST_CALLBACK(&cb_data, opt_timerlat_auto_cb);
- assert(freopen("/dev/null", "w", stderr));
- opt_dma_latency_cb(&opt, "-1", 0);
+ ck_assert_int_eq(opt_timerlat_auto_cb(&opt, "10", 0), 0);
+ ck_assert_int_eq(opt_timerlat_auto_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.common.stop_us, 0);
+ ck_assert_int_eq(params.common.stop_total_us, 0);
+ ck_assert_int_eq(params.print_stack, 0);
+ ck_assert_ptr_null(cb_data.trace_output);
}
END_TEST
-START_TEST(test_opt_dma_latency_cb_max)
-{
- int dma_latency = 0;
- const struct option opt = TEST_CALLBACK(&dma_latency, opt_dma_latency_cb);
-
- assert(freopen("/dev/null", "w", stderr));
- opt_dma_latency_cb(&opt, "10001", 0);
-}
-END_TEST
START_TEST(test_opt_aa_only_cb)
{
@@ -460,6 +621,20 @@ START_TEST(test_opt_aa_only_cb)
}
END_TEST
+START_TEST(test_opt_aa_only_cb_unset)
+{
+ struct timerlat_params params = {0};
+ const struct option opt = TEST_CALLBACK(&params, opt_aa_only_cb);
+
+ ck_assert_int_eq(opt_aa_only_cb(&opt, "10", 0), 0);
+ ck_assert_int_eq(opt_aa_only_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.common.stop_us, 0);
+ ck_assert_int_eq(params.common.stop_total_us, 0);
+ ck_assert_int_eq(params.print_stack, 0);
+ ck_assert_int_eq(params.common.aa_only, 0);
+}
+END_TEST
+
START_TEST(test_opt_timerlat_trace_output_cb)
{
const char *trace_output = NULL;
@@ -480,6 +655,17 @@ START_TEST(test_opt_timerlat_trace_output_cb_noarg)
}
END_TEST
+START_TEST(test_opt_timerlat_trace_output_cb_unset)
+{
+ const char *trace_output = NULL;
+ const struct option opt = TEST_CALLBACK(&trace_output, opt_timerlat_trace_output_cb);
+
+ ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, "trace.txt", 0), 0);
+ ck_assert_int_eq(opt_timerlat_trace_output_cb(&opt, NULL, 1), 0);
+ ck_assert_ptr_null(trace_output);
+}
+END_TEST
+
START_TEST(test_opt_timerlat_on_threshold_cb)
{
struct actions actions = {0};
@@ -498,7 +684,7 @@ START_TEST(test_opt_timerlat_on_threshold_cb_invalid)
const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_threshold_cb);
assert(freopen("/dev/null", "w", stderr));
- opt_timerlat_on_threshold_cb(&opt, "abc", 0);
+ ck_assert_int_eq(opt_timerlat_on_threshold_cb(&opt, "abc", 0), -1);
}
END_TEST
@@ -520,7 +706,7 @@ START_TEST(test_opt_timerlat_on_end_cb_invalid)
const struct option opt = TEST_CALLBACK(&actions, opt_timerlat_on_end_cb);
assert(freopen("/dev/null", "w", stderr));
- opt_timerlat_on_end_cb(&opt, "abc", 0);
+ ck_assert_int_eq(opt_timerlat_on_end_cb(&opt, "abc", 0), -1);
}
END_TEST
@@ -535,107 +721,107 @@ START_TEST(test_opt_user_threads_cb)
}
END_TEST
-START_TEST(test_opt_nano_cb)
+START_TEST(test_opt_user_threads_cb_unset)
{
struct timerlat_params params = {0};
- const struct option opt = TEST_CALLBACK(&params, opt_nano_cb);
+ const struct option opt = TEST_CALLBACK(&params, opt_user_threads_cb);
- ck_assert_int_eq(opt_nano_cb(&opt, NULL, 0), 0);
- ck_assert_int_eq(params.common.output_divisor, 1);
+ ck_assert_int_eq(opt_user_threads_cb(&opt, NULL, 0), 0);
+ ck_assert_int_eq(opt_user_threads_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.common.user_workload, 0);
+ ck_assert_int_eq(params.common.user_data, 0);
}
END_TEST
-START_TEST(test_opt_timerlat_align_cb)
+START_TEST(test_opt_nano_cb)
{
struct timerlat_params params = {0};
- const struct option opt = TEST_CALLBACK(&params, opt_timerlat_align_cb);
-
- ck_assert_int_eq(opt_timerlat_align_cb(&opt, "500", 0), 0);
- ck_assert(params.timerlat_align);
- ck_assert_int_eq(params.timerlat_align_us, 500);
-}
-END_TEST
-
-START_TEST(test_opt_stack_format_cb)
-{
- int stack_format = 0;
- const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
+ const struct option opt = TEST_CALLBACK(&params, opt_nano_cb);
- ck_assert_int_eq(opt_stack_format_cb(&opt, "full", 0), 0);
- ck_assert_int_eq(stack_format, STACK_FORMAT_FULL);
+ ck_assert_int_eq(opt_nano_cb(&opt, NULL, 0), 0);
+ ck_assert_int_eq(params.common.output_divisor, 1);
}
END_TEST
-START_TEST(test_opt_stack_format_cb_invalid)
+START_TEST(test_opt_nano_cb_unset)
{
- int stack_format = 0;
- const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
+ struct timerlat_params params = {0};
+ const struct option opt = TEST_CALLBACK(&params, opt_nano_cb);
- assert(freopen("/dev/null", "w", stderr));
- opt_stack_format_cb(&opt, "abc", 0);
+ ck_assert_int_eq(opt_nano_cb(&opt, NULL, 0), 0);
+ ck_assert_int_eq(opt_nano_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.common.output_divisor, default_output_divisor);
}
END_TEST
-START_TEST(test_opt_bucket_size_cb)
+START_TEST(test_opt_timerlat_align_cb)
{
- int bucket_size = 0;
- const struct option opt = TEST_CALLBACK(&bucket_size, opt_bucket_size_cb);
+ struct timerlat_params params = {0};
+ const struct option opt = RTLA_OPT_CALLBACK_DATA('A', "aligned", &params, "us",
+ "test", opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX));
- ck_assert_int_eq(opt_bucket_size_cb(&opt, "100", 0), 0);
- ck_assert_int_eq(bucket_size, 100);
+ ck_assert_int_eq(opt_timerlat_align_cb(&opt, "500", 0), 0);
+ ck_assert(params.timerlat_align);
+ ck_assert_int_eq(params.timerlat_align_us, 500);
}
END_TEST
-START_TEST(test_opt_bucket_size_min)
+START_TEST(test_opt_timerlat_align_cb_invalid)
{
- int bucket_size = 0;
- const struct option opt = TEST_CALLBACK(&bucket_size, opt_bucket_size_cb);
+ struct timerlat_params params = {0};
+ const struct option opt = RTLA_OPT_CALLBACK_DATA('A', "aligned", &params, "us",
+ "test", opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX));
assert(freopen("/dev/null", "w", stderr));
- opt_bucket_size_cb(&opt, "0", 0);
+ ck_assert_int_eq(opt_timerlat_align_cb(&opt, "-1", 0), -1);
}
END_TEST
-START_TEST(test_opt_bucket_size_max)
+START_TEST(test_opt_timerlat_align_cb_unset)
{
- int bucket_size = 0;
- const struct option opt = TEST_CALLBACK(&bucket_size, opt_bucket_size_cb);
+ struct timerlat_params params = {0};
+ const struct option opt = RTLA_OPT_CALLBACK_DATA('A', "aligned", &params, "us",
+ "test", opt_timerlat_align_cb, LLONG_RANGE(0, LLONG_MAX));
- assert(freopen("/dev/null", "w", stderr));
- opt_bucket_size_cb(&opt, "1000001", 0);
+ ck_assert_int_eq(opt_timerlat_align_cb(&opt, "500", 0), 0);
+ ck_assert_int_eq(opt_timerlat_align_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(params.timerlat_align, 0);
+ ck_assert_int_eq(params.timerlat_align_us, 0);
}
END_TEST
-START_TEST(test_opt_entries_cb)
+START_TEST(test_opt_stack_format_cb)
{
- int entries = 0;
- const struct option opt = TEST_CALLBACK(&entries, opt_entries_cb);
+ int stack_format = 0;
+ const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
- ck_assert_int_eq(opt_entries_cb(&opt, "100", 0), 0);
- ck_assert_int_eq(entries, 100);
+ ck_assert_int_eq(opt_stack_format_cb(&opt, "full", 0), 0);
+ ck_assert_int_eq(stack_format, STACK_FORMAT_FULL);
}
END_TEST
-START_TEST(test_opt_entries_min)
+START_TEST(test_opt_stack_format_cb_invalid)
{
- int entries = 0;
- const struct option opt = TEST_CALLBACK(&entries, opt_entries_cb);
+ int stack_format = 0;
+ const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
assert(freopen("/dev/null", "w", stderr));
- opt_entries_cb(&opt, "9", 0);
+ ck_assert_int_eq(opt_stack_format_cb(&opt, "abc", 0), -1);
}
END_TEST
-START_TEST(test_opt_entries_max)
+START_TEST(test_opt_stack_format_cb_unset)
{
- int entries = 0;
- const struct option opt = TEST_CALLBACK(&entries, opt_entries_cb);
+ int stack_format = 0;
+ const struct option opt = TEST_CALLBACK(&stack_format, opt_stack_format_cb);
- assert(freopen("/dev/null", "w", stderr));
- opt_entries_cb(&opt, "10000000", 0);
+ ck_assert_int_eq(opt_stack_format_cb(&opt, "full", 0), 0);
+ ck_assert_int_eq(opt_stack_format_cb(&opt, NULL, 1), 0);
+ ck_assert_int_eq(stack_format, default_stack_format);
}
END_TEST
+
Suite *cli_opt_callback_suite(void)
{
Suite *s = suite_create("cli_opt_callback");
@@ -645,71 +831,81 @@ Suite *cli_opt_callback_suite(void)
tcase_add_test(tc, test_opt_llong_callback_simple);
tcase_add_test(tc, test_opt_llong_callback_max);
tcase_add_test(tc, test_opt_llong_callback_min);
+ tcase_add_test(tc, test_opt_llong_callback_non_numeric);
+ tcase_add_test(tc, test_opt_llong_callback_non_numeric_suffix);
+ tcase_add_test(tc, test_opt_llong_callback_unset);
+ tcase_add_test(tc, test_opt_llong_callback_unset_defval);
+ tcase_add_test(tc, test_opt_llong_callback_range_in);
+ tcase_add_test(tc, test_opt_llong_callback_range_below);
+ tcase_add_test(tc, test_opt_llong_callback_range_above);
+ tcase_add_test(tc, test_opt_llong_callback_range_boundary);
tcase_add_test(tc, test_opt_int_callback_simple);
tcase_add_test(tc, test_opt_int_callback_max);
tcase_add_test(tc, test_opt_int_callback_min);
tcase_add_test(tc, test_opt_int_callback_non_numeric);
tcase_add_test(tc, test_opt_int_callback_non_numeric_suffix);
+ tcase_add_test(tc, test_opt_int_callback_unset);
+ tcase_add_test(tc, test_opt_int_callback_unset_defval);
+ tcase_add_test(tc, test_opt_int_callback_range_in);
+ tcase_add_test(tc, test_opt_int_callback_range_below);
+ tcase_add_test(tc, test_opt_int_callback_range_above);
+ tcase_add_test(tc, test_opt_int_callback_range_boundary);
tcase_add_test(tc, test_opt_cpus_cb);
- tcase_add_exit_test(tc, test_opt_cpus_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_cpus_cb_invalid);
tcase_add_test(tc, test_opt_cgroup_cb);
tcase_add_test(tc, test_opt_cgroup_cb_equals);
+ tcase_add_test(tc, test_opt_cgroup_cb_unset);
tcase_add_test(tc, test_opt_duration_cb);
- tcase_add_exit_test(tc, test_opt_duration_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_duration_cb_unset);
+ tcase_add_test(tc, test_opt_duration_cb_invalid);
tcase_add_test(tc, test_opt_event_cb);
tcase_add_test(tc, test_opt_event_cb_multiple);
tcase_add_test(tc, test_opt_housekeeping_cb);
- tcase_add_exit_test(tc, test_opt_housekeeping_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_housekeeping_cb_invalid);
+ tcase_add_test(tc, test_opt_housekeeping_cb_unset);
tcase_add_test(tc, test_opt_priority_cb);
- tcase_add_exit_test(tc, test_opt_priority_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_priority_cb_invalid);
+ tcase_add_test(tc, test_opt_priority_cb_unset);
tcase_add_test(tc, test_opt_trigger_cb);
- tcase_add_exit_test(tc, test_opt_trigger_cb_no_event, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_trigger_cb_no_event);
tcase_add_test(tc, test_opt_filter_cb);
- tcase_add_exit_test(tc, test_opt_filter_cb_no_event, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_filter_cb_no_event);
suite_add_tcase(s, tc);
tc = tcase_create("osnoise");
tcase_add_test(tc, test_opt_osnoise_auto_cb);
- tcase_add_test(tc, test_opt_osnoise_period_cb);
- tcase_add_exit_test(tc, test_opt_osnoise_period_cb_invalid, EXIT_FAILURE);
- tcase_add_test(tc, test_opt_osnoise_runtime_cb);
- tcase_add_exit_test(tc, test_opt_osnoise_runtime_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_osnoise_auto_cb_unset);
tcase_add_test(tc, test_opt_osnoise_trace_output_cb);
tcase_add_test(tc, test_opt_osnoise_trace_output_cb_noarg);
+ tcase_add_test(tc, test_opt_osnoise_trace_output_cb_unset);
tcase_add_test(tc, test_opt_osnoise_on_threshold_cb);
- tcase_add_exit_test(tc, test_opt_osnoise_on_threshold_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_osnoise_on_threshold_cb_invalid);
tcase_add_test(tc, test_opt_osnoise_on_end_cb);
- tcase_add_exit_test(tc, test_opt_osnoise_on_end_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_osnoise_on_end_cb_invalid);
suite_add_tcase(s, tc);
tc = tcase_create("timerlat");
- tcase_add_test(tc, test_opt_timerlat_period_cb);
- tcase_add_exit_test(tc, test_opt_timerlat_period_cb_invalid, EXIT_FAILURE);
tcase_add_test(tc, test_opt_timerlat_auto_cb);
- tcase_add_test(tc, test_opt_dma_latency_cb);
- tcase_add_exit_test(tc, test_opt_dma_latency_cb_min, EXIT_FAILURE);
- tcase_add_exit_test(tc, test_opt_dma_latency_cb_max, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_timerlat_auto_cb_unset);
tcase_add_test(tc, test_opt_aa_only_cb);
+ tcase_add_test(tc, test_opt_aa_only_cb_unset);
tcase_add_test(tc, test_opt_timerlat_trace_output_cb);
tcase_add_test(tc, test_opt_timerlat_trace_output_cb_noarg);
+ tcase_add_test(tc, test_opt_timerlat_trace_output_cb_unset);
tcase_add_test(tc, test_opt_timerlat_on_threshold_cb);
- tcase_add_exit_test(tc, test_opt_timerlat_on_threshold_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_timerlat_on_threshold_cb_invalid);
tcase_add_test(tc, test_opt_timerlat_on_end_cb);
- tcase_add_exit_test(tc, test_opt_timerlat_on_end_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_timerlat_on_end_cb_invalid);
tcase_add_test(tc, test_opt_user_threads_cb);
+ tcase_add_test(tc, test_opt_user_threads_cb_unset);
tcase_add_test(tc, test_opt_nano_cb);
+ tcase_add_test(tc, test_opt_nano_cb_unset);
tcase_add_test(tc, test_opt_stack_format_cb);
- tcase_add_exit_test(tc, test_opt_stack_format_cb_invalid, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_stack_format_cb_invalid);
+ tcase_add_test(tc, test_opt_stack_format_cb_unset);
tcase_add_test(tc, test_opt_timerlat_align_cb);
- suite_add_tcase(s, tc);
-
- tc = tcase_create("histogram");
- tcase_add_test(tc, test_opt_bucket_size_cb);
- tcase_add_exit_test(tc, test_opt_bucket_size_min, EXIT_FAILURE);
- tcase_add_exit_test(tc, test_opt_bucket_size_max, EXIT_FAILURE);
- tcase_add_test(tc, test_opt_entries_cb);
- tcase_add_exit_test(tc, test_opt_entries_min, EXIT_FAILURE);
- tcase_add_exit_test(tc, test_opt_entries_max, EXIT_FAILURE);
+ tcase_add_test(tc, test_opt_timerlat_align_cb_invalid);
+ tcase_add_test(tc, test_opt_timerlat_align_cb_unset);
suite_add_tcase(s, tc);
return s;
diff --git a/tools/tracing/rtla/tests/unit/osnoise_hist_cli.c b/tools/tracing/rtla/tests/unit/osnoise_hist_cli.c
index 3661529f93dc..221985e6759f 100644
--- a/tools/tracing/rtla/tests/unit/osnoise_hist_cli.c
+++ b/tools/tracing/rtla/tests/unit/osnoise_hist_cli.c
@@ -37,6 +37,22 @@ START_TEST(test_period_long)
}
END_TEST
+START_TEST(test_period_unset_short)
+{
+ PARSE_ARGS("osnoise", "hist", "-p", "100000", "--no-period");
+
+ ck_assert_int_eq(osn_params->period, 0);
+}
+END_TEST
+
+START_TEST(test_period_unset_long)
+{
+ PARSE_ARGS("osnoise", "hist", "--period", "100000", "--no-period");
+
+ ck_assert_int_eq(osn_params->period, 0);
+}
+END_TEST
+
START_TEST(test_runtime_short)
{
PARSE_ARGS("osnoise", "hist", "-r", "95000");
@@ -481,6 +497,8 @@ Suite *osnoise_hist_cli_suite(void)
tc = tcase_create("tracing_options");
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
+ tcase_add_test(tc, test_period_unset_short);
+ tcase_add_test(tc, test_period_unset_long);
tcase_add_test(tc, test_runtime_short);
tcase_add_test(tc, test_runtime_long);
tcase_add_test(tc, test_stop_short);
diff --git a/tools/tracing/rtla/tests/unit/osnoise_top_cli.c b/tools/tracing/rtla/tests/unit/osnoise_top_cli.c
index f3a8633cc84e..057dbe574b07 100644
--- a/tools/tracing/rtla/tests/unit/osnoise_top_cli.c
+++ b/tools/tracing/rtla/tests/unit/osnoise_top_cli.c
@@ -37,6 +37,22 @@ START_TEST(test_period_long)
}
END_TEST
+START_TEST(test_period_unset_short)
+{
+ PARSE_ARGS("osnoise", "top", "-p", "100000", "--no-period");
+
+ ck_assert_int_eq(osn_params->period, 0);
+}
+END_TEST
+
+START_TEST(test_period_unset_long)
+{
+ PARSE_ARGS("osnoise", "top", "--period", "100000", "--no-period");
+
+ ck_assert_int_eq(osn_params->period, 0);
+}
+END_TEST
+
START_TEST(test_runtime_short)
{
PARSE_ARGS("osnoise", "top", "-r", "95000");
@@ -433,6 +449,8 @@ Suite *osnoise_top_cli_suite(void)
tc = tcase_create("tracing_options");
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
+ tcase_add_test(tc, test_period_unset_short);
+ tcase_add_test(tc, test_period_unset_long);
tcase_add_test(tc, test_runtime_short);
tcase_add_test(tc, test_runtime_long);
tcase_add_test(tc, test_stop_short);
diff --git a/tools/tracing/rtla/tests/unit/timerlat_hist_cli.c b/tools/tracing/rtla/tests/unit/timerlat_hist_cli.c
index 968bf962f53f..d8dd9d752636 100644
--- a/tools/tracing/rtla/tests/unit/timerlat_hist_cli.c
+++ b/tools/tracing/rtla/tests/unit/timerlat_hist_cli.c
@@ -55,6 +55,22 @@ START_TEST(test_period_long)
}
END_TEST
+START_TEST(test_period_unset_short)
+{
+ PARSE_ARGS("timerlat", "hist", "-p", "200", "--no-period");
+
+ ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
+}
+END_TEST
+
+START_TEST(test_period_unset_long)
+{
+ PARSE_ARGS("timerlat", "hist", "--period", "200", "--no-period");
+
+ ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
+}
+END_TEST
+
START_TEST(test_stack_short)
{
PARSE_ARGS("timerlat", "hist", "-s", "20");
@@ -629,6 +645,8 @@ Suite *timerlat_hist_cli_suite(void)
tcase_add_test(tc, test_irq_long);
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
+ tcase_add_test(tc, test_period_unset_short);
+ tcase_add_test(tc, test_period_unset_long);
tcase_add_test(tc, test_stack_short);
tcase_add_test(tc, test_stack_long);
tcase_add_test(tc, test_thread_short);
diff --git a/tools/tracing/rtla/tests/unit/timerlat_top_cli.c b/tools/tracing/rtla/tests/unit/timerlat_top_cli.c
index 33aa6588d503..e9fb1a86ab8c 100644
--- a/tools/tracing/rtla/tests/unit/timerlat_top_cli.c
+++ b/tools/tracing/rtla/tests/unit/timerlat_top_cli.c
@@ -55,6 +55,22 @@ START_TEST(test_period_long)
}
END_TEST
+START_TEST(test_period_unset_short)
+{
+ PARSE_ARGS("timerlat", "top", "-p", "200", "--no-period");
+
+ ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
+}
+END_TEST
+
+START_TEST(test_period_unset_long)
+{
+ PARSE_ARGS("timerlat", "top", "--period", "200", "--no-period");
+
+ ck_assert_int_eq(tlat_params->timerlat_period_us, 0);
+}
+END_TEST
+
START_TEST(test_stack_short)
{
PARSE_ARGS("timerlat", "top", "-s", "20");
@@ -571,6 +587,8 @@ Suite *timerlat_top_cli_suite(void)
tcase_add_test(tc, test_irq_long);
tcase_add_test(tc, test_period_short);
tcase_add_test(tc, test_period_long);
+ tcase_add_test(tc, test_period_unset_short);
+ tcase_add_test(tc, test_period_unset_long);
tcase_add_test(tc, test_stack_short);
tcase_add_test(tc, test_stack_long);
tcase_add_test(tc, test_thread_short);