Commit 26aa834f authored by Linus Torvalds's avatar Linus Torvalds

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

Pull tracing tool updates from Steven Rostedt:
 "Specific for timerlat:

   - Improve the output of timerlat top by adding a missing \n, and by
     avoiding printing color-formatting characters where they are
     translated to regular characters.

   - Improve timerlat auto-analysis output by replacing '\t' with spaces
     to avoid copy-and-paste issues when reporting problems.

   - Make the user-space (-u) option the default, as it is the most
     complete test. Add a -k option to use the in-kernel workload.

   - On timerlat top and hist, add a summary with the overall results.
     For instance, the minimum value for all CPUs, the overall average
     and the maximum value from all CPUs.

   - timerlat hist was printing initial values (i.e., 0 as max, and ~0
     as min) if the trace stopped before the first Ret-User event. This
     problem was fixed by printing the " - " no value string to the
     output if that was the case.

  For all RTLA tools:

   - Add a --warm-up <seconds> option, allowing the workload to run for
     <seconds> before starting to collect results.

   - Add a --trace-buffer-size option, allowing the user to set the
     tracing buffer size for -t option. This option is mainly useful for
     reducing the trace file. Now rtla depends on libtracefs >= 1.6.

   - Fix the -t [trace_file] parsing, now it does not require the '='
     before the option parameter, and better handles the multiple ways a
     user can pass the trace_file.txt"

* tag 'trace-tools-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
  rtla: Documentation: Fix -t, --trace
  rtla: Fix -t\--trace[=file]
  rtla/timerlat: Fix histogram report when a cpu count is 0
  rtla: Add --trace-buffer-size option
  rtla/timerlat: Make user-space threads the default
  rtla: Add the --warm-up option
  rtla/timerlat: Add a summary for hist mode
  rtla/timerlat: Add a summary for top mode
  rtla/timerlat: Use pretty formatting only on interactive tty
  rtla/auto-analysis: Replace \t with spaces
  rtla/timerlat: Simplify "no value" printing on top
parents fa3889d9 59c22f70
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
Print debug info. Print debug info.
**-t**, **--trace**\[*=file*]
Save the stopped trace to [*file|osnoise_trace.txt*].
**-e**, **--event** *sys:event* **-e**, **--event** *sys:event*
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. 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.
...@@ -50,6 +46,13 @@ ...@@ -50,6 +46,13 @@
Set a *cgroup* to the tracer's threads. If the **-C** option is passed without arguments, the tracer's thread will inherit **rtla**'s *cgroup*. Otherwise, the threads will be placed on the *cgroup* passed to the option. Set a *cgroup* to the tracer's threads. If the **-C** option is passed without arguments, the tracer's thread will inherit **rtla**'s *cgroup*. Otherwise, the threads will be placed on the *cgroup* passed to the option.
**--warm-up** *s*
After starting the workload, let it run for *s* seconds before starting collecting the data, allowing the system to warm-up. Statistical data generated during warm-up is discarded.
**--trace-buffer-size** *kB*
Set the per-cpu trace buffer size in kB for the tracing output.
**-h**, **--help** **-h**, **--help**
Print help menu. Print help menu.
...@@ -25,3 +25,7 @@ ...@@ -25,3 +25,7 @@
Specify the minimum delta between two time reads to be considered noise. Specify the minimum delta between two time reads to be considered noise.
The default threshold is *5 us*. The default threshold is *5 us*.
**-t**, **--trace** \[*file*]
Save the stopped trace to [*file|osnoise_trace.txt*].
...@@ -22,17 +22,25 @@ ...@@ -22,17 +22,25 @@
Save the stack trace at the *IRQ* if a *Thread* latency is higher than the Save the stack trace at the *IRQ* if a *Thread* latency is higher than the
argument in us. argument in us.
**-t**, **--trace** \[*file*]
Save the stopped trace to [*file|timerlat_trace.txt*].
**--dma-latency** *us* **--dma-latency** *us*
Set the /dev/cpu_dma_latency to *us*, aiming to bound exit from idle latencies. Set the /dev/cpu_dma_latency to *us*, aiming to bound exit from idle latencies.
*cyclictest* sets this value to *0* by default, use **--dma-latency** *0* to have *cyclictest* sets this value to *0* by default, use **--dma-latency** *0* to have
similar results. similar results.
**-k**, **--kernel-threads**
Use timerlat kernel-space threads, in contrast of **-u**.
**-u**, **--user-threads** **-u**, **--user-threads**
Set timerlat to run without a workload, and then dispatches user-space workloads Set timerlat to run without a workload, and then dispatches user-space workloads
to wait on the timerlat_fd. Once the workload is awakes, it goes to sleep again to wait on the timerlat_fd. Once the workload is awakes, it goes to sleep again
adding so the measurement for the kernel-to-user and user-to-kernel to the tracer adding so the measurement for the kernel-to-user and user-to-kernel to the tracer
output. output. **--user-threads** will be used unless the user specify **-k**.
**-U**, **--user-load** **-U**, **--user-load**
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
STOP_ERROR := STOP_ERROR :=
LIBTRACEEVENT_MIN_VERSION = 1.5 LIBTRACEEVENT_MIN_VERSION = 1.5
LIBTRACEFS_MIN_VERSION = 1.3 LIBTRACEFS_MIN_VERSION = 1.6
define lib_setup define lib_setup
$(eval LIB_INCLUDES += $(shell sh -c "$(PKG_CONFIG) --cflags lib$(1)")) $(eval LIB_INCLUDES += $(shell sh -c "$(PKG_CONFIG) --cflags lib$(1)"))
......
...@@ -36,13 +36,14 @@ struct osnoise_hist_params { ...@@ -36,13 +36,14 @@ struct osnoise_hist_params {
cpu_set_t hk_cpu_set; cpu_set_t hk_cpu_set;
struct sched_attr sched_param; struct sched_attr sched_param;
struct trace_events *events; struct trace_events *events;
char no_header; char no_header;
char no_summary; char no_summary;
char no_index; char no_index;
char with_zeros; char with_zeros;
int bucket_size; int bucket_size;
int entries; int entries;
int warmup;
int buffer_size;
}; };
struct osnoise_hist_cpu { struct osnoise_hist_cpu {
...@@ -436,9 +437,9 @@ static void osnoise_hist_usage(char *usage) ...@@ -436,9 +437,9 @@ static void osnoise_hist_usage(char *usage)
static const char * const msg[] = { static const char * const msg[] = {
"", "",
" usage: rtla osnoise hist [-h] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\", " usage: rtla osnoise hist [-h] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\",
" [-T us] [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\", " [-T us] [-t[file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\",
" [-c cpu-list] [-H cpu-list] [-P priority] [-b N] [-E N] [--no-header] [--no-summary] \\", " [-c cpu-list] [-H cpu-list] [-P priority] [-b N] [-E N] [--no-header] [--no-summary] \\",
" [--no-index] [--with-zeros] [-C[=cgroup_name]]", " [--no-index] [--with-zeros] [-C[=cgroup_name]] [--warm-up]",
"", "",
" -h/--help: print this menu", " -h/--help: print this menu",
" -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit", " -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit",
...@@ -452,7 +453,7 @@ static void osnoise_hist_usage(char *usage) ...@@ -452,7 +453,7 @@ static void osnoise_hist_usage(char *usage)
" -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited", " -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited",
" -d/--duration time[s|m|h|d]: duration of the session", " -d/--duration time[s|m|h|d]: duration of the session",
" -D/--debug: print debug info", " -D/--debug: print debug info",
" -t/--trace[=file]: save the stopped trace to [file|osnoise_trace.txt]", " -t/--trace[file]: save the stopped trace to [file|osnoise_trace.txt]",
" -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed", " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed",
" --filter <filter>: enable a trace event filter to the previous -e event", " --filter <filter>: enable a trace event filter to the previous -e event",
" --trigger <trigger>: enable a trace event trigger to the previous -e event", " --trigger <trigger>: enable a trace event trigger to the previous -e event",
...@@ -468,6 +469,8 @@ static void osnoise_hist_usage(char *usage) ...@@ -468,6 +469,8 @@ static void osnoise_hist_usage(char *usage)
" f:prio - use SCHED_FIFO with prio", " f:prio - use SCHED_FIFO with prio",
" d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period", " d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period",
" in nanoseconds", " in nanoseconds",
" --warm-up: let the workload run for s seconds before collecting data",
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
NULL, NULL,
}; };
...@@ -531,13 +534,15 @@ static struct osnoise_hist_params ...@@ -531,13 +534,15 @@ static struct osnoise_hist_params
{"with-zeros", no_argument, 0, '3'}, {"with-zeros", no_argument, 0, '3'},
{"trigger", required_argument, 0, '4'}, {"trigger", required_argument, 0, '4'},
{"filter", required_argument, 0, '5'}, {"filter", required_argument, 0, '5'},
{"warm-up", required_argument, 0, '6'},
{"trace-buffer-size", required_argument, 0, '7'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
/* getopt_long stores the option index here. */ /* getopt_long stores the option index here. */
int option_index = 0; int option_index = 0;
c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:", c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:p:P:r:s:S:t::T:01234:5:6:7:",
long_options, &option_index); long_options, &option_index);
/* detect the end of the options. */ /* detect the end of the options. */
...@@ -640,9 +645,13 @@ static struct osnoise_hist_params ...@@ -640,9 +645,13 @@ static struct osnoise_hist_params
params->threshold = get_llong_from_str(optarg); params->threshold = get_llong_from_str(optarg);
break; break;
case 't': case 't':
if (optarg) if (optarg) {
/* skip = */ if (optarg[0] == '=')
params->trace_output = &optarg[1]; params->trace_output = &optarg[1];
else
params->trace_output = &optarg[0];
} else if (optind < argc && argv[optind][0] != '0')
params->trace_output = argv[optind];
else else
params->trace_output = "osnoise_trace.txt"; params->trace_output = "osnoise_trace.txt";
break; break;
...@@ -680,6 +689,12 @@ static struct osnoise_hist_params ...@@ -680,6 +689,12 @@ static struct osnoise_hist_params
osnoise_hist_usage("--filter requires a previous -e\n"); osnoise_hist_usage("--filter requires a previous -e\n");
} }
break; break;
case '6':
params->warmup = get_llong_from_str(optarg);
break;
case '7':
params->buffer_size = get_llong_from_str(optarg);
break;
default: default:
osnoise_hist_usage("Invalid option"); osnoise_hist_usage("Invalid option");
} }
...@@ -886,6 +901,11 @@ int osnoise_hist_main(int argc, char *argv[]) ...@@ -886,6 +901,11 @@ int osnoise_hist_main(int argc, char *argv[])
goto out_hist; goto out_hist;
} }
if (params->buffer_size > 0) {
retval = trace_set_buffer_size(&record->trace, params->buffer_size);
if (retval)
goto out_hist;
}
} }
/* /*
...@@ -899,6 +919,25 @@ int osnoise_hist_main(int argc, char *argv[]) ...@@ -899,6 +919,25 @@ int osnoise_hist_main(int argc, char *argv[])
trace_instance_start(&record->trace); trace_instance_start(&record->trace);
trace_instance_start(trace); trace_instance_start(trace);
if (params->warmup > 0) {
debug_msg("Warming up for %d seconds\n", params->warmup);
sleep(params->warmup);
if (stop_tracing)
goto out_hist;
/*
* Clean up the buffer. The osnoise workload do not run
* with tracing off to avoid creating a performance penalty
* when not needed.
*/
retval = tracefs_instance_file_write(trace->inst, "trace", "");
if (retval < 0) {
debug_msg("Error cleaning up the buffer");
goto out_hist;
}
}
tool->start_time = time(NULL); tool->start_time = time(NULL);
osnoise_hist_set_signals(params); osnoise_hist_set_signals(params);
......
...@@ -40,6 +40,8 @@ struct osnoise_top_params { ...@@ -40,6 +40,8 @@ struct osnoise_top_params {
int set_sched; int set_sched;
int cgroup; int cgroup;
int hk_cpus; int hk_cpus;
int warmup;
int buffer_size;
cpu_set_t hk_cpu_set; cpu_set_t hk_cpu_set;
struct sched_attr sched_param; struct sched_attr sched_param;
struct trace_events *events; struct trace_events *events;
...@@ -281,8 +283,8 @@ static void osnoise_top_usage(struct osnoise_top_params *params, char *usage) ...@@ -281,8 +283,8 @@ static void osnoise_top_usage(struct osnoise_top_params *params, char *usage)
static const char * const msg[] = { static const char * const msg[] = {
" [-h] [-q] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\", " [-h] [-q] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\",
" [-T us] [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\", " [-T us] [-t[file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\",
" [-c cpu-list] [-H cpu-list] [-P priority] [-C[=cgroup_name]]", " [-c cpu-list] [-H cpu-list] [-P priority] [-C[=cgroup_name]] [--warm-up s]",
"", "",
" -h/--help: print this menu", " -h/--help: print this menu",
" -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit", " -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit",
...@@ -296,7 +298,7 @@ static void osnoise_top_usage(struct osnoise_top_params *params, char *usage) ...@@ -296,7 +298,7 @@ static void osnoise_top_usage(struct osnoise_top_params *params, char *usage)
" -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited", " -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited",
" -d/--duration time[s|m|h|d]: duration of the session", " -d/--duration time[s|m|h|d]: duration of the session",
" -D/--debug: print debug info", " -D/--debug: print debug info",
" -t/--trace[=file]: save the stopped trace to [file|osnoise_trace.txt]", " -t/--trace[file]: save the stopped trace to [file|osnoise_trace.txt]",
" -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed", " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed",
" --filter <filter>: enable a trace event filter to the previous -e event", " --filter <filter>: enable a trace event filter to the previous -e event",
" --trigger <trigger>: enable a trace event trigger to the previous -e event", " --trigger <trigger>: enable a trace event trigger to the previous -e event",
...@@ -307,6 +309,8 @@ static void osnoise_top_usage(struct osnoise_top_params *params, char *usage) ...@@ -307,6 +309,8 @@ static void osnoise_top_usage(struct osnoise_top_params *params, char *usage)
" f:prio - use SCHED_FIFO with prio", " f:prio - use SCHED_FIFO with prio",
" d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period", " d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period",
" in nanoseconds", " in nanoseconds",
" --warm-up s: let the workload run for s seconds before collecting data",
" --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
NULL, NULL,
}; };
...@@ -381,13 +385,15 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) ...@@ -381,13 +385,15 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
{"trace", optional_argument, 0, 't'}, {"trace", optional_argument, 0, 't'},
{"trigger", required_argument, 0, '0'}, {"trigger", required_argument, 0, '0'},
{"filter", required_argument, 0, '1'}, {"filter", required_argument, 0, '1'},
{"warm-up", required_argument, 0, '2'},
{"trace-buffer-size", required_argument, 0, '3'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
/* getopt_long stores the option index here. */ /* getopt_long stores the option index here. */
int option_index = 0; int option_index = 0;
c = getopt_long(argc, argv, "a:c:C::d:De:hH:p:P:qr:s:S:t::T:0:1:", c = getopt_long(argc, argv, "a:c:C::d:De:hH:p:P:qr:s:S:t::T:0:1:2:3:",
long_options, &option_index); long_options, &option_index);
/* Detect the end of the options. */ /* Detect the end of the options. */
...@@ -480,9 +486,13 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) ...@@ -480,9 +486,13 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
params->stop_total_us = get_llong_from_str(optarg); params->stop_total_us = get_llong_from_str(optarg);
break; break;
case 't': case 't':
if (optarg) if (optarg) {
/* skip = */ if (optarg[0] == '=')
params->trace_output = &optarg[1]; params->trace_output = &optarg[1];
else
params->trace_output = &optarg[0];
} else if (optind < argc && argv[optind][0] != '-')
params->trace_output = argv[optind];
else else
params->trace_output = "osnoise_trace.txt"; params->trace_output = "osnoise_trace.txt";
break; break;
...@@ -511,6 +521,12 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) ...@@ -511,6 +521,12 @@ struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv)
osnoise_top_usage(params, "--filter requires a previous -e\n"); osnoise_top_usage(params, "--filter requires a previous -e\n");
} }
break; break;
case '2':
params->warmup = get_llong_from_str(optarg);
break;
case '3':
params->buffer_size = get_llong_from_str(optarg);
break;
default: default:
osnoise_top_usage(params, "Invalid option"); osnoise_top_usage(params, "Invalid option");
} }
...@@ -719,6 +735,12 @@ int osnoise_top_main(int argc, char **argv) ...@@ -719,6 +735,12 @@ int osnoise_top_main(int argc, char **argv)
if (retval) if (retval)
goto out_top; goto out_top;
} }
if (params->buffer_size > 0) {
retval = trace_set_buffer_size(&record->trace, params->buffer_size);
if (retval)
goto out_top;
}
} }
/* /*
...@@ -732,6 +754,25 @@ int osnoise_top_main(int argc, char **argv) ...@@ -732,6 +754,25 @@ int osnoise_top_main(int argc, char **argv)
trace_instance_start(&record->trace); trace_instance_start(&record->trace);
trace_instance_start(trace); trace_instance_start(trace);
if (params->warmup > 0) {
debug_msg("Warming up for %d seconds\n", params->warmup);
sleep(params->warmup);
if (stop_tracing)
goto out_top;
/*
* Clean up the buffer. The osnoise workload do not run
* with tracing off to avoid creating a performance penalty
* when not needed.
*/
retval = tracefs_instance_file_write(trace->inst, "trace", "");
if (retval < 0) {
debug_msg("Error cleaning up the buffer");
goto out_top;
}
}
tool->start_time = time(NULL); tool->start_time = time(NULL);
osnoise_top_set_signals(params); osnoise_top_set_signals(params);
......
...@@ -16,6 +16,9 @@ enum timelat_state { ...@@ -16,6 +16,9 @@ enum timelat_state {
TIMERLAT_WAITING_THREAD, TIMERLAT_WAITING_THREAD,
}; };
/* Used to fill spaces in the output */
static const char *spaces = " ";
#define MAX_COMM 24 #define MAX_COMM 24
/* /*
...@@ -274,14 +277,17 @@ static int timerlat_aa_nmi_handler(struct trace_seq *s, struct tep_record *recor ...@@ -274,14 +277,17 @@ static int timerlat_aa_nmi_handler(struct trace_seq *s, struct tep_record *recor
taa_data->prev_irq_timstamp = start; taa_data->prev_irq_timstamp = start;
trace_seq_reset(taa_data->prev_irqs_seq); trace_seq_reset(taa_data->prev_irqs_seq);
trace_seq_printf(taa_data->prev_irqs_seq, "\t%24s \t\t\t%9.2f us\n", trace_seq_printf(taa_data->prev_irqs_seq, " %24s %.*s %9.2f us\n",
"nmi", ns_to_usf(duration)); "nmi",
24, spaces,
ns_to_usf(duration));
return 0; return 0;
} }
taa_data->thread_nmi_sum += duration; taa_data->thread_nmi_sum += duration;
trace_seq_printf(taa_data->nmi_seq, " %24s \t\t\t%9.2f us\n", trace_seq_printf(taa_data->nmi_seq, " %24s %.*s %9.2f us\n",
"nmi", ns_to_usf(duration)); "nmi",
24, spaces, ns_to_usf(duration));
return 0; return 0;
} }
...@@ -323,8 +329,10 @@ static int timerlat_aa_irq_handler(struct trace_seq *s, struct tep_record *recor ...@@ -323,8 +329,10 @@ static int timerlat_aa_irq_handler(struct trace_seq *s, struct tep_record *recor
taa_data->prev_irq_timstamp = start; taa_data->prev_irq_timstamp = start;
trace_seq_reset(taa_data->prev_irqs_seq); trace_seq_reset(taa_data->prev_irqs_seq);
trace_seq_printf(taa_data->prev_irqs_seq, "\t%24s:%-3llu \t\t%9.2f us\n", trace_seq_printf(taa_data->prev_irqs_seq, " %24s:%-3llu %.*s %9.2f us\n",
desc, vector, ns_to_usf(duration)); desc, vector,
15, spaces,
ns_to_usf(duration));
return 0; return 0;
} }
...@@ -372,8 +380,10 @@ static int timerlat_aa_irq_handler(struct trace_seq *s, struct tep_record *recor ...@@ -372,8 +380,10 @@ static int timerlat_aa_irq_handler(struct trace_seq *s, struct tep_record *recor
* IRQ interference. * IRQ interference.
*/ */
taa_data->thread_irq_sum += duration; taa_data->thread_irq_sum += duration;
trace_seq_printf(taa_data->irqs_seq, " %24s:%-3llu \t %9.2f us\n", trace_seq_printf(taa_data->irqs_seq, " %24s:%-3llu %.*s %9.2f us\n",
desc, vector, ns_to_usf(duration)); desc, vector,
24, spaces,
ns_to_usf(duration));
return 0; return 0;
} }
...@@ -408,8 +418,10 @@ static int timerlat_aa_softirq_handler(struct trace_seq *s, struct tep_record *r ...@@ -408,8 +418,10 @@ static int timerlat_aa_softirq_handler(struct trace_seq *s, struct tep_record *r
taa_data->thread_softirq_sum += duration; taa_data->thread_softirq_sum += duration;
trace_seq_printf(taa_data->softirqs_seq, "\t%24s:%-3llu \t %9.2f us\n", trace_seq_printf(taa_data->softirqs_seq, " %24s:%-3llu %.*s %9.2f us\n",
softirq_name[vector], vector, ns_to_usf(duration)); softirq_name[vector], vector,
24, spaces,
ns_to_usf(duration));
return 0; return 0;
} }
...@@ -452,8 +464,10 @@ static int timerlat_aa_thread_handler(struct trace_seq *s, struct tep_record *re ...@@ -452,8 +464,10 @@ static int timerlat_aa_thread_handler(struct trace_seq *s, struct tep_record *re
} else { } else {
taa_data->thread_thread_sum += duration; taa_data->thread_thread_sum += duration;
trace_seq_printf(taa_data->threads_seq, "\t%24s:%-3llu \t\t%9.2f us\n", trace_seq_printf(taa_data->threads_seq, " %24s:%-12llu %.*s %9.2f us\n",
comm, pid, ns_to_usf(duration)); comm, pid,
15, spaces,
ns_to_usf(duration));
} }
return 0; return 0;
...@@ -482,7 +496,8 @@ static int timerlat_aa_stack_handler(struct trace_seq *s, struct tep_record *rec ...@@ -482,7 +496,8 @@ static int timerlat_aa_stack_handler(struct trace_seq *s, struct tep_record *rec
function = tep_find_function(taa_ctx->tool->trace.tep, caller[i]); function = tep_find_function(taa_ctx->tool->trace.tep, caller[i]);
if (!function) if (!function)
break; break;
trace_seq_printf(taa_data->stack_seq, "\t\t-> %s\n", function); trace_seq_printf(taa_data->stack_seq, " %.*s -> %s\n",
14, spaces, function);
} }
} }
return 0; return 0;
...@@ -568,23 +583,24 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, ...@@ -568,23 +583,24 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
exp_irq_ts = taa_data->timer_irq_start_time - taa_data->timer_irq_start_delay; exp_irq_ts = taa_data->timer_irq_start_time - taa_data->timer_irq_start_delay;
if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) { if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) {
if (taa_data->prev_irq_timstamp < taa_data->timer_irq_start_time) if (taa_data->prev_irq_timstamp < taa_data->timer_irq_start_time)
printf(" Previous IRQ interference: \t\t up to %9.2f us\n", printf(" Previous IRQ interference: %.*s up to %9.2f us\n",
ns_to_usf(taa_data->prev_irq_duration)); 16, spaces,
ns_to_usf(taa_data->prev_irq_duration));
} }
/* /*
* The delay that the IRQ suffered before starting. * The delay that the IRQ suffered before starting.
*/ */
printf(" IRQ handler delay: %16s %9.2f us (%.2f %%)\n", printf(" IRQ handler delay: %.*s %16s %9.2f us (%.2f %%)\n", 16, spaces,
(ns_to_usf(taa_data->timer_exit_from_idle) > 10) ? "(exit from idle)" : "", (ns_to_usf(taa_data->timer_exit_from_idle) > 10) ? "(exit from idle)" : "",
ns_to_usf(taa_data->timer_irq_start_delay), ns_to_usf(taa_data->timer_irq_start_delay),
ns_to_per(total, taa_data->timer_irq_start_delay)); ns_to_per(total, taa_data->timer_irq_start_delay));
/* /*
* Timerlat IRQ. * Timerlat IRQ.
*/ */
printf(" IRQ latency: \t\t\t\t %9.2f us\n", printf(" IRQ latency: %.*s %9.2f us\n", 40, spaces,
ns_to_usf(taa_data->tlat_irq_latency)); ns_to_usf(taa_data->tlat_irq_latency));
if (irq) { if (irq) {
/* /*
...@@ -595,15 +611,16 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, ...@@ -595,15 +611,16 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
* so it will be displayed, it is the key. * so it will be displayed, it is the key.
*/ */
printf(" Blocking thread:\n"); printf(" Blocking thread:\n");
printf(" %24s:%-9llu\n", printf(" %.*s %24s:%-9llu\n", 6, spaces, taa_data->run_thread_comm,
taa_data->run_thread_comm, taa_data->run_thread_pid); taa_data->run_thread_pid);
} else { } else {
/* /*
* The duration of the IRQ handler that handled the timerlat IRQ. * The duration of the IRQ handler that handled the timerlat IRQ.
*/ */
printf(" Timerlat IRQ duration: \t\t %9.2f us (%.2f %%)\n", printf(" Timerlat IRQ duration: %.*s %9.2f us (%.2f %%)\n",
ns_to_usf(taa_data->timer_irq_duration), 30, spaces,
ns_to_per(total, taa_data->timer_irq_duration)); ns_to_usf(taa_data->timer_irq_duration),
ns_to_per(total, taa_data->timer_irq_duration));
/* /*
* The amount of time that the current thread postponed the scheduler. * The amount of time that the current thread postponed the scheduler.
...@@ -611,13 +628,13 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, ...@@ -611,13 +628,13 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
* Recalling that it is net from NMI/IRQ/Softirq interference, so there * Recalling that it is net from NMI/IRQ/Softirq interference, so there
* is no need to compute values here. * is no need to compute values here.
*/ */
printf(" Blocking thread: \t\t\t %9.2f us (%.2f %%)\n", printf(" Blocking thread: %.*s %9.2f us (%.2f %%)\n", 36, spaces,
ns_to_usf(taa_data->thread_blocking_duration), ns_to_usf(taa_data->thread_blocking_duration),
ns_to_per(total, taa_data->thread_blocking_duration)); ns_to_per(total, taa_data->thread_blocking_duration));
printf(" %24s:%-9llu %9.2f us\n", printf(" %.*s %24s:%-9llu %.*s %9.2f us\n", 6, spaces,
taa_data->run_thread_comm, taa_data->run_thread_pid, taa_data->run_thread_comm, taa_data->run_thread_pid,
ns_to_usf(taa_data->thread_blocking_duration)); 12, spaces, ns_to_usf(taa_data->thread_blocking_duration));
} }
/* /*
...@@ -629,9 +646,9 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, ...@@ -629,9 +646,9 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
* NMIs can happen during the IRQ, so they are always possible. * NMIs can happen during the IRQ, so they are always possible.
*/ */
if (taa_data->thread_nmi_sum) if (taa_data->thread_nmi_sum)
printf(" NMI interference \t\t\t %9.2f us (%.2f %%)\n", printf(" NMI interference %.*s %9.2f us (%.2f %%)\n", 36, spaces,
ns_to_usf(taa_data->thread_nmi_sum), ns_to_usf(taa_data->thread_nmi_sum),
ns_to_per(total, taa_data->thread_nmi_sum)); ns_to_per(total, taa_data->thread_nmi_sum));
/* /*
* If it is an IRQ latency, the other factors can be skipped. * If it is an IRQ latency, the other factors can be skipped.
...@@ -643,9 +660,9 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, ...@@ -643,9 +660,9 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
* Prints the interference caused by IRQs to the thread latency. * Prints the interference caused by IRQs to the thread latency.
*/ */
if (taa_data->thread_irq_sum) { if (taa_data->thread_irq_sum) {
printf(" IRQ interference \t\t\t %9.2f us (%.2f %%)\n", printf(" IRQ interference %.*s %9.2f us (%.2f %%)\n", 36, spaces,
ns_to_usf(taa_data->thread_irq_sum), ns_to_usf(taa_data->thread_irq_sum),
ns_to_per(total, taa_data->thread_irq_sum)); ns_to_per(total, taa_data->thread_irq_sum));
trace_seq_do_printf(taa_data->irqs_seq); trace_seq_do_printf(taa_data->irqs_seq);
} }
...@@ -654,9 +671,9 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, ...@@ -654,9 +671,9 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
* Prints the interference caused by Softirqs to the thread latency. * Prints the interference caused by Softirqs to the thread latency.
*/ */
if (taa_data->thread_softirq_sum) { if (taa_data->thread_softirq_sum) {
printf(" Softirq interference \t\t\t %9.2f us (%.2f %%)\n", printf(" Softirq interference %.*s %9.2f us (%.2f %%)\n", 32, spaces,
ns_to_usf(taa_data->thread_softirq_sum), ns_to_usf(taa_data->thread_softirq_sum),
ns_to_per(total, taa_data->thread_softirq_sum)); ns_to_per(total, taa_data->thread_softirq_sum));
trace_seq_do_printf(taa_data->softirqs_seq); trace_seq_do_printf(taa_data->softirqs_seq);
} }
...@@ -670,9 +687,9 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, ...@@ -670,9 +687,9 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
* timer handling latency. * timer handling latency.
*/ */
if (taa_data->thread_thread_sum) { if (taa_data->thread_thread_sum) {
printf(" Thread interference \t\t\t %9.2f us (%.2f %%)\n", printf(" Thread interference %.*s %9.2f us (%.2f %%)\n", 33, spaces,
ns_to_usf(taa_data->thread_thread_sum), ns_to_usf(taa_data->thread_thread_sum),
ns_to_per(total, taa_data->thread_thread_sum)); ns_to_per(total, taa_data->thread_thread_sum));
trace_seq_do_printf(taa_data->threads_seq); trace_seq_do_printf(taa_data->threads_seq);
} }
...@@ -682,8 +699,8 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, ...@@ -682,8 +699,8 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
*/ */
print_total: print_total:
printf("------------------------------------------------------------------------\n"); printf("------------------------------------------------------------------------\n");
printf(" %s latency: \t\t\t %9.2f us (100%%)\n", irq ? "IRQ" : "Thread", printf(" %s latency: %.*s %9.2f us (100%%)\n", irq ? " IRQ" : "Thread",
ns_to_usf(total)); 37, spaces, ns_to_usf(total));
} }
static int timerlat_auto_analysis_collect_trace(struct timerlat_aa_context *taa_ctx) static int timerlat_auto_analysis_collect_trace(struct timerlat_aa_context *taa_ctx)
......
This diff is collapsed.
This diff is collapsed.
...@@ -540,3 +540,18 @@ int trace_is_off(struct trace_instance *tool, struct trace_instance *trace) ...@@ -540,3 +540,18 @@ int trace_is_off(struct trace_instance *tool, struct trace_instance *trace)
return 0; return 0;
} }
/*
* trace_set_buffer_size - set the per-cpu tracing buffer size.
*/
int trace_set_buffer_size(struct trace_instance *trace, int size)
{
int retval;
debug_msg("Setting trace buffer size to %d Kb\n", size);
retval = tracefs_instance_set_buffer_size(trace->inst, size, -1);
if (retval)
err_msg("Error setting trace buffer size\n");
return retval;
}
...@@ -48,3 +48,4 @@ int trace_events_enable(struct trace_instance *instance, ...@@ -48,3 +48,4 @@ int trace_events_enable(struct trace_instance *instance,
int trace_event_add_filter(struct trace_events *event, char *filter); int trace_event_add_filter(struct trace_events *event, char *filter);
int trace_event_add_trigger(struct trace_events *event, char *trigger); int trace_event_add_trigger(struct trace_events *event, char *trigger);
int trace_is_off(struct trace_instance *tool, struct trace_instance *trace); int trace_is_off(struct trace_instance *tool, struct trace_instance *trace);
int trace_set_buffer_size(struct trace_instance *trace, int size);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment