Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/tracing/rtla/src/common.c
49130 views
1
// SPDX-License-Identifier: GPL-2.0
2
#define _GNU_SOURCE
3
4
#include <pthread.h>
5
#include <signal.h>
6
#include <stdlib.h>
7
#include <unistd.h>
8
#include "common.h"
9
10
struct trace_instance *trace_inst;
11
int stop_tracing;
12
13
static void stop_trace(int sig)
14
{
15
if (stop_tracing) {
16
/*
17
* Stop requested twice in a row; abort event processing and
18
* exit immediately
19
*/
20
tracefs_iterate_stop(trace_inst->inst);
21
return;
22
}
23
stop_tracing = 1;
24
if (trace_inst)
25
trace_instance_stop(trace_inst);
26
}
27
28
/*
29
* set_signals - handles the signal to stop the tool
30
*/
31
static void set_signals(struct common_params *params)
32
{
33
signal(SIGINT, stop_trace);
34
if (params->duration) {
35
signal(SIGALRM, stop_trace);
36
alarm(params->duration);
37
}
38
}
39
40
/*
41
* common_apply_config - apply common configs to the initialized tool
42
*/
43
int
44
common_apply_config(struct osnoise_tool *tool, struct common_params *params)
45
{
46
int retval, i;
47
48
if (!params->sleep_time)
49
params->sleep_time = 1;
50
51
retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all");
52
if (retval) {
53
err_msg("Failed to apply CPUs config\n");
54
goto out_err;
55
}
56
57
if (!params->cpus) {
58
for (i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++)
59
CPU_SET(i, &params->monitored_cpus);
60
}
61
62
if (params->hk_cpus) {
63
retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set),
64
&params->hk_cpu_set);
65
if (retval == -1) {
66
err_msg("Failed to set rtla to the house keeping CPUs\n");
67
goto out_err;
68
}
69
} else if (params->cpus) {
70
/*
71
* Even if the user do not set a house-keeping CPU, try to
72
* move rtla to a CPU set different to the one where the user
73
* set the workload to run.
74
*
75
* No need to check results as this is an automatic attempt.
76
*/
77
auto_house_keeping(&params->monitored_cpus);
78
}
79
80
/*
81
* Set workload according to type of thread if the kernel supports it.
82
* On kernels without support, user threads will have already failed
83
* on missing fd, and kernel threads do not need it.
84
*/
85
retval = osnoise_set_workload(tool->context, params->kernel_workload);
86
if (retval < -1) {
87
err_msg("Failed to set OSNOISE_WORKLOAD option\n");
88
goto out_err;
89
}
90
91
return 0;
92
93
out_err:
94
return -1;
95
}
96
97
98
int run_tool(struct tool_ops *ops, int argc, char *argv[])
99
{
100
struct common_params *params;
101
enum result return_value = ERROR;
102
struct osnoise_tool *tool;
103
bool stopped;
104
int retval;
105
106
params = ops->parse_args(argc, argv);
107
if (!params)
108
exit(1);
109
110
tool = ops->init_tool(params);
111
if (!tool) {
112
err_msg("Could not init osnoise tool\n");
113
goto out_exit;
114
}
115
tool->ops = ops;
116
tool->params = params;
117
118
/*
119
* Save trace instance into global variable so that SIGINT can stop
120
* the timerlat tracer.
121
* Otherwise, rtla could loop indefinitely when overloaded.
122
*/
123
trace_inst = &tool->trace;
124
125
retval = ops->apply_config(tool);
126
if (retval) {
127
err_msg("Could not apply config\n");
128
goto out_free;
129
}
130
131
retval = enable_tracer_by_name(trace_inst->inst, ops->tracer);
132
if (retval) {
133
err_msg("Failed to enable %s tracer\n", ops->tracer);
134
goto out_free;
135
}
136
137
if (params->set_sched) {
138
retval = set_comm_sched_attr(ops->comm_prefix, &params->sched_param);
139
if (retval) {
140
err_msg("Failed to set sched parameters\n");
141
goto out_free;
142
}
143
}
144
145
if (params->cgroup && !params->user_data) {
146
retval = set_comm_cgroup(ops->comm_prefix, params->cgroup_name);
147
if (!retval) {
148
err_msg("Failed to move threads to cgroup\n");
149
goto out_free;
150
}
151
}
152
153
154
if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
155
params->end_actions.present[ACTION_TRACE_OUTPUT]) {
156
tool->record = osnoise_init_trace_tool(ops->tracer);
157
if (!tool->record) {
158
err_msg("Failed to enable the trace instance\n");
159
goto out_free;
160
}
161
params->threshold_actions.trace_output_inst = tool->record->trace.inst;
162
params->end_actions.trace_output_inst = tool->record->trace.inst;
163
164
if (params->events) {
165
retval = trace_events_enable(&tool->record->trace, params->events);
166
if (retval)
167
goto out_trace;
168
}
169
170
if (params->buffer_size > 0) {
171
retval = trace_set_buffer_size(&tool->record->trace, params->buffer_size);
172
if (retval)
173
goto out_trace;
174
}
175
}
176
177
if (params->user_workload) {
178
pthread_t user_thread;
179
180
/* rtla asked to stop */
181
params->user.should_run = 1;
182
/* all threads left */
183
params->user.stopped_running = 0;
184
185
params->user.set = &params->monitored_cpus;
186
if (params->set_sched)
187
params->user.sched_param = &params->sched_param;
188
else
189
params->user.sched_param = NULL;
190
191
params->user.cgroup_name = params->cgroup_name;
192
193
retval = pthread_create(&user_thread, NULL, timerlat_u_dispatcher, &params->user);
194
if (retval)
195
err_msg("Error creating timerlat user-space threads\n");
196
}
197
198
retval = ops->enable(tool);
199
if (retval)
200
goto out_trace;
201
202
tool->start_time = time(NULL);
203
set_signals(params);
204
205
retval = ops->main(tool);
206
if (retval)
207
goto out_trace;
208
209
if (params->user_workload && !params->user.stopped_running) {
210
params->user.should_run = 0;
211
sleep(1);
212
}
213
214
ops->print_stats(tool);
215
216
actions_perform(&params->end_actions);
217
218
return_value = PASSED;
219
220
stopped = osnoise_trace_is_off(tool, tool->record) && !stop_tracing;
221
if (stopped) {
222
printf("%s hit stop tracing\n", ops->tracer);
223
return_value = FAILED;
224
}
225
226
if (ops->analyze)
227
ops->analyze(tool, stopped);
228
229
out_trace:
230
trace_events_destroy(&tool->record->trace, params->events);
231
params->events = NULL;
232
out_free:
233
ops->free(tool);
234
osnoise_destroy_tool(tool->record);
235
osnoise_destroy_tool(tool);
236
actions_destroy(&params->threshold_actions);
237
actions_destroy(&params->end_actions);
238
free(params);
239
out_exit:
240
exit(return_value);
241
}
242
243
int top_main_loop(struct osnoise_tool *tool)
244
{
245
struct common_params *params = tool->params;
246
struct trace_instance *trace = &tool->trace;
247
struct osnoise_tool *record = tool->record;
248
int retval;
249
250
while (!stop_tracing) {
251
sleep(params->sleep_time);
252
253
if (params->aa_only && !osnoise_trace_is_off(tool, record))
254
continue;
255
256
retval = tracefs_iterate_raw_events(trace->tep,
257
trace->inst,
258
NULL,
259
0,
260
collect_registered_events,
261
trace);
262
if (retval < 0) {
263
err_msg("Error iterating on events\n");
264
return retval;
265
}
266
267
if (!params->quiet)
268
tool->ops->print_stats(tool);
269
270
if (osnoise_trace_is_off(tool, record)) {
271
if (stop_tracing)
272
/* stop tracing requested, do not perform actions */
273
return 0;
274
275
actions_perform(&params->threshold_actions);
276
277
if (!params->threshold_actions.continue_flag)
278
/* continue flag not set, break */
279
return 0;
280
281
/* continue action reached, re-enable tracing */
282
if (record)
283
trace_instance_start(&record->trace);
284
if (tool->aa)
285
trace_instance_start(&tool->aa->trace);
286
trace_instance_start(trace);
287
}
288
289
/* is there still any user-threads ? */
290
if (params->user_workload) {
291
if (params->user.stopped_running) {
292
debug_msg("timerlat user space threads stopped!\n");
293
break;
294
}
295
}
296
}
297
298
return 0;
299
}
300
301
int hist_main_loop(struct osnoise_tool *tool)
302
{
303
struct common_params *params = tool->params;
304
struct trace_instance *trace = &tool->trace;
305
int retval = 0;
306
307
while (!stop_tracing) {
308
sleep(params->sleep_time);
309
310
retval = tracefs_iterate_raw_events(trace->tep,
311
trace->inst,
312
NULL,
313
0,
314
collect_registered_events,
315
trace);
316
if (retval < 0) {
317
err_msg("Error iterating on events\n");
318
break;
319
}
320
321
if (osnoise_trace_is_off(tool, tool->record)) {
322
if (stop_tracing)
323
/* stop tracing requested, do not perform actions */
324
break;
325
326
actions_perform(&params->threshold_actions);
327
328
if (!params->threshold_actions.continue_flag)
329
/* continue flag not set, break */
330
break;
331
332
/* continue action reached, re-enable tracing */
333
if (tool->record)
334
trace_instance_start(&tool->record->trace);
335
if (tool->aa)
336
trace_instance_start(&tool->aa->trace);
337
trace_instance_start(&tool->trace);
338
}
339
340
/* is there still any user-threads ? */
341
if (params->user_workload) {
342
if (params->user.stopped_running) {
343
debug_msg("user-space threads stopped!\n");
344
break;
345
}
346
}
347
}
348
349
return retval;
350
}
351
352