Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/tracing/rtla/src/timerlat.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <[email protected]>
4
*/
5
#define _GNU_SOURCE
6
#include <sys/types.h>
7
#include <sys/stat.h>
8
#include <pthread.h>
9
#include <stdlib.h>
10
#include <string.h>
11
#include <unistd.h>
12
#include <errno.h>
13
#include <fcntl.h>
14
#include <stdio.h>
15
#include <sched.h>
16
17
#include "timerlat.h"
18
19
#define DEFAULT_TIMERLAT_PERIOD 1000 /* 1ms */
20
21
/*
22
* timerlat_apply_config - apply common configs to the initialized tool
23
*/
24
int
25
timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
26
{
27
int retval, i;
28
29
if (!params->sleep_time)
30
params->sleep_time = 1;
31
32
retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all");
33
if (retval) {
34
err_msg("Failed to apply CPUs config\n");
35
goto out_err;
36
}
37
38
if (!params->cpus) {
39
for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++)
40
CPU_SET(i, &params->monitored_cpus);
41
}
42
43
if (params->mode != TRACING_MODE_BPF) {
44
/*
45
* In tracefs and mixed mode, timerlat tracer handles stopping
46
* on threshold
47
*/
48
retval = osnoise_set_stop_us(tool->context, params->stop_us);
49
if (retval) {
50
err_msg("Failed to set stop us\n");
51
goto out_err;
52
}
53
54
retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us);
55
if (retval) {
56
err_msg("Failed to set stop total us\n");
57
goto out_err;
58
}
59
}
60
61
62
retval = osnoise_set_timerlat_period_us(tool->context,
63
params->timerlat_period_us ?
64
params->timerlat_period_us :
65
DEFAULT_TIMERLAT_PERIOD);
66
if (retval) {
67
err_msg("Failed to set timerlat period\n");
68
goto out_err;
69
}
70
71
72
retval = osnoise_set_print_stack(tool->context, params->print_stack);
73
if (retval) {
74
err_msg("Failed to set print stack\n");
75
goto out_err;
76
}
77
78
if (params->hk_cpus) {
79
retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set),
80
&params->hk_cpu_set);
81
if (retval == -1) {
82
err_msg("Failed to set rtla to the house keeping CPUs\n");
83
goto out_err;
84
}
85
} else if (params->cpus) {
86
/*
87
* Even if the user do not set a house-keeping CPU, try to
88
* move rtla to a CPU set different to the one where the user
89
* set the workload to run.
90
*
91
* No need to check results as this is an automatic attempt.
92
*/
93
auto_house_keeping(&params->monitored_cpus);
94
}
95
96
/*
97
* If the user did not specify a type of thread, try user-threads first.
98
* Fall back to kernel threads otherwise.
99
*/
100
if (!params->kernel_workload && !params->user_data) {
101
retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd");
102
if (retval) {
103
debug_msg("User-space interface detected, setting user-threads\n");
104
params->user_workload = 1;
105
params->user_data = 1;
106
} else {
107
debug_msg("User-space interface not detected, setting kernel-threads\n");
108
params->kernel_workload = 1;
109
}
110
}
111
112
/*
113
* Set workload according to type of thread if the kernel supports it.
114
* On kernels without support, user threads will have already failed
115
* on missing timerlat_fd, and kernel threads do not need it.
116
*/
117
retval = osnoise_set_workload(tool->context, params->kernel_workload);
118
if (retval < -1) {
119
err_msg("Failed to set OSNOISE_WORKLOAD option\n");
120
goto out_err;
121
}
122
123
return 0;
124
125
out_err:
126
return -1;
127
}
128
129
static void timerlat_usage(int err)
130
{
131
int i;
132
133
static const char * const msg[] = {
134
"",
135
"timerlat version " VERSION,
136
"",
137
" usage: [rtla] timerlat [MODE] ...",
138
"",
139
" modes:",
140
" top - prints the summary from timerlat tracer",
141
" hist - prints a histogram of timer latencies",
142
"",
143
"if no MODE is given, the top mode is called, passing the arguments",
144
NULL,
145
};
146
147
for (i = 0; msg[i]; i++)
148
fprintf(stderr, "%s\n", msg[i]);
149
exit(err);
150
}
151
152
int timerlat_main(int argc, char *argv[])
153
{
154
if (argc == 0)
155
goto usage;
156
157
/*
158
* if timerlat was called without any argument, run the
159
* default cmdline.
160
*/
161
if (argc == 1) {
162
timerlat_top_main(argc, argv);
163
exit(0);
164
}
165
166
if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
167
timerlat_usage(0);
168
} else if (strncmp(argv[1], "-", 1) == 0) {
169
/* the user skipped the tool, call the default one */
170
timerlat_top_main(argc, argv);
171
exit(0);
172
} else if (strcmp(argv[1], "top") == 0) {
173
timerlat_top_main(argc-1, &argv[1]);
174
exit(0);
175
} else if (strcmp(argv[1], "hist") == 0) {
176
timerlat_hist_main(argc-1, &argv[1]);
177
exit(0);
178
}
179
180
usage:
181
timerlat_usage(1);
182
exit(1);
183
}
184
185