rtla/timerlat: Add --dma-latency option
Add the --dma-latency to set /dev/cpu_dma_latency to the specified value, this aims to avoid having exit from idle states latencies that could be influencing the analysis. Link: https://lkml.kernel.org/r/72ddb0d913459f13217086dadafad88a7c46dd28.1646247211.git.bristot@kernel.org Cc: Daniel Bristot de Oliveira <bristot@kernel.org> Cc: Clark Williams <williams@redhat.com> Cc: Juri Lelli <juri.lelli@redhat.com> Cc: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Daniel Bristot de Oliveira <bristot@kernel.org> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
7d38c35167
commit
7d0dc9576d
5 changed files with 91 additions and 4 deletions
|
@ -21,3 +21,8 @@
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
**--dma-latency** *us*
|
||||||
|
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
|
||||||
|
similar results.
|
||||||
|
|
|
@ -28,6 +28,7 @@ struct timerlat_hist_params {
|
||||||
int output_divisor;
|
int output_divisor;
|
||||||
int duration;
|
int duration;
|
||||||
int set_sched;
|
int set_sched;
|
||||||
|
int dma_latency;
|
||||||
struct sched_attr sched_param;
|
struct sched_attr sched_param;
|
||||||
struct trace_events *events;
|
struct trace_events *events;
|
||||||
|
|
||||||
|
@ -432,7 +433,7 @@ static void timerlat_hist_usage(char *usage)
|
||||||
" usage: [rtla] timerlat hist [-h] [-q] [-d s] [-D] [-n] [-a us] [-p us] [-i us] [-T us] [-s us] \\",
|
" usage: [rtla] timerlat hist [-h] [-q] [-d s] [-D] [-n] [-a us] [-p us] [-i us] [-T us] [-s us] \\",
|
||||||
" [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] \\",
|
" [-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] \\",
|
||||||
" [-P priority] [-E N] [-b N] [--no-irq] [--no-thread] [--no-header] [--no-summary] \\",
|
" [-P priority] [-E N] [-b N] [--no-irq] [--no-thread] [--no-header] [--no-summary] \\",
|
||||||
" [--no-index] [--with-zeros]",
|
" [--no-index] [--with-zeros] [--dma-latency us]",
|
||||||
"",
|
"",
|
||||||
" -h/--help: print this menu",
|
" -h/--help: print this menu",
|
||||||
" -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
|
" -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
|
||||||
|
@ -456,6 +457,7 @@ static void timerlat_hist_usage(char *usage)
|
||||||
" --no-summary: do not print summary",
|
" --no-summary: do not print summary",
|
||||||
" --no-index: do not print index",
|
" --no-index: do not print index",
|
||||||
" --with-zeros: print zero only entries",
|
" --with-zeros: print zero only entries",
|
||||||
|
" --dma-latency us: set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency",
|
||||||
" -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters",
|
" -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters",
|
||||||
" o:prio - use SCHED_OTHER with prio",
|
" o:prio - use SCHED_OTHER with prio",
|
||||||
" r:prio - use SCHED_RR with prio",
|
" r:prio - use SCHED_RR with prio",
|
||||||
|
@ -492,6 +494,9 @@ static struct timerlat_hist_params
|
||||||
if (!params)
|
if (!params)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
|
/* disabled by default */
|
||||||
|
params->dma_latency = -1;
|
||||||
|
|
||||||
/* display data in microseconds */
|
/* display data in microseconds */
|
||||||
params->output_divisor = 1000;
|
params->output_divisor = 1000;
|
||||||
params->bucket_size = 1;
|
params->bucket_size = 1;
|
||||||
|
@ -522,13 +527,14 @@ static struct timerlat_hist_params
|
||||||
{"with-zeros", no_argument, 0, '5'},
|
{"with-zeros", no_argument, 0, '5'},
|
||||||
{"trigger", required_argument, 0, '6'},
|
{"trigger", required_argument, 0, '6'},
|
||||||
{"filter", required_argument, 0, '7'},
|
{"filter", required_argument, 0, '7'},
|
||||||
|
{"dma-latency", required_argument, 0, '8'},
|
||||||
{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:b:d:e:E:Dhi:np:P:s:t::T:0123456:7:",
|
c = getopt_long(argc, argv, "a:c:b:d:e:E:Dhi:np:P:s:t::T:0123456:7:8:",
|
||||||
long_options, &option_index);
|
long_options, &option_index);
|
||||||
|
|
||||||
/* detect the end of the options. */
|
/* detect the end of the options. */
|
||||||
|
@ -659,6 +665,13 @@ static struct timerlat_hist_params
|
||||||
timerlat_hist_usage("--filter requires a previous -e\n");
|
timerlat_hist_usage("--filter requires a previous -e\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case '8':
|
||||||
|
params->dma_latency = get_llong_from_str(optarg);
|
||||||
|
if (params->dma_latency < 0 || params->dma_latency > 10000) {
|
||||||
|
err_msg("--dma-latency needs to be >= 0 and < 10000");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
timerlat_hist_usage("Invalid option");
|
timerlat_hist_usage("Invalid option");
|
||||||
}
|
}
|
||||||
|
@ -791,6 +804,7 @@ int timerlat_hist_main(int argc, char *argv[])
|
||||||
struct osnoise_tool *record = NULL;
|
struct osnoise_tool *record = NULL;
|
||||||
struct osnoise_tool *tool = NULL;
|
struct osnoise_tool *tool = NULL;
|
||||||
struct trace_instance *trace;
|
struct trace_instance *trace;
|
||||||
|
int dma_latency_fd = -1;
|
||||||
int return_value = 1;
|
int return_value = 1;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
@ -826,6 +840,14 @@ int timerlat_hist_main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params->dma_latency >= 0) {
|
||||||
|
dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
|
||||||
|
if (dma_latency_fd < 0) {
|
||||||
|
err_msg("Could not set /dev/cpu_dma_latency.\n");
|
||||||
|
goto out_hist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trace_instance_start(trace);
|
trace_instance_start(trace);
|
||||||
|
|
||||||
if (params->trace_output) {
|
if (params->trace_output) {
|
||||||
|
@ -878,6 +900,8 @@ int timerlat_hist_main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
out_hist:
|
out_hist:
|
||||||
|
if (dma_latency_fd >= 0)
|
||||||
|
close(dma_latency_fd);
|
||||||
trace_events_destroy(&record->trace, params->events);
|
trace_events_destroy(&record->trace, params->events);
|
||||||
params->events = NULL;
|
params->events = NULL;
|
||||||
timerlat_free_histogram(tool->data);
|
timerlat_free_histogram(tool->data);
|
||||||
|
|
|
@ -29,6 +29,7 @@ struct timerlat_top_params {
|
||||||
int duration;
|
int duration;
|
||||||
int quiet;
|
int quiet;
|
||||||
int set_sched;
|
int set_sched;
|
||||||
|
int dma_latency;
|
||||||
struct sched_attr sched_param;
|
struct sched_attr sched_param;
|
||||||
struct trace_events *events;
|
struct trace_events *events;
|
||||||
};
|
};
|
||||||
|
@ -269,7 +270,7 @@ static void timerlat_top_usage(char *usage)
|
||||||
"",
|
"",
|
||||||
" usage: rtla timerlat [top] [-h] [-q] [-a us] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] \\",
|
" usage: rtla timerlat [top] [-h] [-q] [-a us] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] \\",
|
||||||
" [[-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] \\",
|
" [[-t[=file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] \\",
|
||||||
" [-P priority]",
|
" [-P priority] [--dma-latency us]",
|
||||||
"",
|
"",
|
||||||
" -h/--help: print this menu",
|
" -h/--help: print this menu",
|
||||||
" -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
|
" -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
|
||||||
|
@ -286,6 +287,7 @@ static void timerlat_top_usage(char *usage)
|
||||||
" --trigger <command>: enable a trace event trigger to the previous -e event",
|
" --trigger <command>: enable a trace event trigger to the previous -e event",
|
||||||
" -n/--nano: display data in nanoseconds",
|
" -n/--nano: display data in nanoseconds",
|
||||||
" -q/--quiet print only a summary at the end",
|
" -q/--quiet print only a summary at the end",
|
||||||
|
" --dma-latency us: set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency",
|
||||||
" -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters",
|
" -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters",
|
||||||
" o:prio - use SCHED_OTHER with prio",
|
" o:prio - use SCHED_OTHER with prio",
|
||||||
" r:prio - use SCHED_RR with prio",
|
" r:prio - use SCHED_RR with prio",
|
||||||
|
@ -322,6 +324,9 @@ static struct timerlat_top_params
|
||||||
if (!params)
|
if (!params)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
|
/* disabled by default */
|
||||||
|
params->dma_latency = -1;
|
||||||
|
|
||||||
/* display data in microseconds */
|
/* display data in microseconds */
|
||||||
params->output_divisor = 1000;
|
params->output_divisor = 1000;
|
||||||
|
|
||||||
|
@ -343,13 +348,14 @@ static struct timerlat_top_params
|
||||||
{"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'},
|
||||||
|
{"dma-latency", required_argument, 0, '2'},
|
||||||
{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:d:De:hi:np:P:qs:t::T:0:1:",
|
c = getopt_long(argc, argv, "a:c:d:De:hi:np:P:qs:t::T:0:1:2:",
|
||||||
long_options, &option_index);
|
long_options, &option_index);
|
||||||
|
|
||||||
/* detect the end of the options. */
|
/* detect the end of the options. */
|
||||||
|
@ -454,6 +460,13 @@ static struct timerlat_top_params
|
||||||
timerlat_top_usage("--filter requires a previous -e\n");
|
timerlat_top_usage("--filter requires a previous -e\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case '2': /* dma-latency */
|
||||||
|
params->dma_latency = get_llong_from_str(optarg);
|
||||||
|
if (params->dma_latency < 0 || params->dma_latency > 10000) {
|
||||||
|
err_msg("--dma-latency needs to be >= 0 and < 10000");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
timerlat_top_usage("Invalid option");
|
timerlat_top_usage("Invalid option");
|
||||||
}
|
}
|
||||||
|
@ -582,6 +595,7 @@ int timerlat_top_main(int argc, char *argv[])
|
||||||
struct osnoise_tool *record = NULL;
|
struct osnoise_tool *record = NULL;
|
||||||
struct osnoise_tool *top = NULL;
|
struct osnoise_tool *top = NULL;
|
||||||
struct trace_instance *trace;
|
struct trace_instance *trace;
|
||||||
|
int dma_latency_fd = -1;
|
||||||
int return_value = 1;
|
int return_value = 1;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
@ -617,6 +631,14 @@ int timerlat_top_main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params->dma_latency >= 0) {
|
||||||
|
dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
|
||||||
|
if (dma_latency_fd < 0) {
|
||||||
|
err_msg("Could not set /dev/cpu_dma_latency.\n");
|
||||||
|
goto out_top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trace_instance_start(trace);
|
trace_instance_start(trace);
|
||||||
|
|
||||||
if (params->trace_output) {
|
if (params->trace_output) {
|
||||||
|
@ -673,6 +695,8 @@ int timerlat_top_main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
out_top:
|
out_top:
|
||||||
|
if (dma_latency_fd >= 0)
|
||||||
|
close(dma_latency_fd);
|
||||||
trace_events_destroy(&record->trace, params->events);
|
trace_events_destroy(&record->trace, params->events);
|
||||||
params->events = NULL;
|
params->events = NULL;
|
||||||
timerlat_free_top(top->data);
|
timerlat_free_top(top->data);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@ -431,3 +432,35 @@ int parse_prio(char *arg, struct sched_attr *sched_param)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set_cpu_dma_latency - set the /dev/cpu_dma_latecy
|
||||||
|
*
|
||||||
|
* This is used to reduce the exit from idle latency. The value
|
||||||
|
* will be reset once the file descriptor of /dev/cpu_dma_latecy
|
||||||
|
* is closed.
|
||||||
|
*
|
||||||
|
* Return: the /dev/cpu_dma_latecy file descriptor
|
||||||
|
*/
|
||||||
|
int set_cpu_dma_latency(int32_t latency)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open("/dev/cpu_dma_latency", O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
err_msg("Error opening /dev/cpu_dma_latency\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = write(fd, &latency, 4);
|
||||||
|
if (retval < 1) {
|
||||||
|
err_msg("Error setting /dev/cpu_dma_latency\n");
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_msg("Set /dev/cpu_dma_latency to %d\n", latency);
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
|
@ -54,3 +54,4 @@ struct sched_attr {
|
||||||
|
|
||||||
int parse_prio(char *arg, struct sched_attr *sched_param);
|
int parse_prio(char *arg, struct sched_attr *sched_param);
|
||||||
int set_comm_sched_attr(const char *comm, struct sched_attr *attr);
|
int set_comm_sched_attr(const char *comm, struct sched_attr *attr);
|
||||||
|
int set_cpu_dma_latency(int32_t latency);
|
||||||
|
|
Loading…
Add table
Reference in a new issue