Skip to content

Commit 2f3172f

Browse files
crwood-rhrostedt
authored andcommitted
tools/rtla: Consolidate code between osnoise/timerlat and hist/top
Currently a lot of code is duplicated between the different rtla tools, making maintenance more difficult, and encouraging divergence such as features that are only implemented for certain tools even though they could be more broadly applicable. Merge the various main() functions into a common run_tool() with an ops struct for tool-specific details. Implement enough support for actions on osnoise to not need to keep the old params->trace_output path. Cc: John Kacur <[email protected]> Cc: Costa Shulyupin <[email protected]> Link: https://lore.kernel.org/[email protected] Reviewed-by: Tomas Glozar <[email protected]> Signed-off-by: Crystal Wood <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 263d7ea commit 2f3172f

File tree

12 files changed

+792
-1194
lines changed

12 files changed

+792
-1194
lines changed

tools/tracing/rtla/src/common.c

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,42 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#define _GNU_SOURCE
33

4+
#include <pthread.h>
5+
#include <signal.h>
6+
#include <stdlib.h>
47
#include <unistd.h>
58
#include "common.h"
69

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+
740
/*
841
* common_apply_config - apply common configs to the initialized tool
942
*/
@@ -61,3 +94,251 @@ common_apply_config(struct osnoise_tool *tool, struct common_params *params)
6194
return -1;
6295
}
6396

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+
actions_perform(&params->threshold_actions);
272+
273+
if (!params->threshold_actions.continue_flag)
274+
/* continue flag not set, break */
275+
return 0;
276+
277+
/* continue action reached, re-enable tracing */
278+
if (record)
279+
trace_instance_start(&record->trace);
280+
if (tool->aa)
281+
trace_instance_start(&tool->aa->trace);
282+
trace_instance_start(trace);
283+
}
284+
285+
/* is there still any user-threads ? */
286+
if (params->user_workload) {
287+
if (params->user.stopped_running) {
288+
debug_msg("timerlat user space threads stopped!\n");
289+
break;
290+
}
291+
}
292+
}
293+
294+
return 0;
295+
}
296+
297+
int hist_main_loop(struct osnoise_tool *tool)
298+
{
299+
struct common_params *params = tool->params;
300+
struct trace_instance *trace = &tool->trace;
301+
int retval = 0;
302+
303+
while (!stop_tracing) {
304+
sleep(params->sleep_time);
305+
306+
retval = tracefs_iterate_raw_events(trace->tep,
307+
trace->inst,
308+
NULL,
309+
0,
310+
collect_registered_events,
311+
trace);
312+
if (retval < 0) {
313+
err_msg("Error iterating on events\n");
314+
break;
315+
}
316+
317+
if (osnoise_trace_is_off(tool, tool->record)) {
318+
actions_perform(&params->threshold_actions);
319+
320+
if (!params->threshold_actions.continue_flag) {
321+
/* continue flag not set, break */
322+
break;
323+
324+
/* continue action reached, re-enable tracing */
325+
if (tool->record)
326+
trace_instance_start(&tool->record->trace);
327+
if (tool->aa)
328+
trace_instance_start(&tool->aa->trace);
329+
trace_instance_start(&tool->trace);
330+
}
331+
break;
332+
}
333+
334+
/* is there still any user-threads ? */
335+
if (params->user_workload) {
336+
if (params->user.stopped_running) {
337+
debug_msg("user-space threads stopped!\n");
338+
break;
339+
}
340+
}
341+
}
342+
343+
return retval;
344+
}

tools/tracing/rtla/src/common.h

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
22
#pragma once
33

4+
#include "actions.h"
5+
#include "timerlat_u.h"
46
#include "trace.h"
57
#include "utils.h"
68

@@ -51,16 +53,8 @@ struct osnoise_context {
5153
int opt_workload;
5254
};
5355

54-
/*
55-
* osnoise_tool - osnoise based tool definition.
56-
*/
57-
struct osnoise_tool {
58-
struct trace_instance trace;
59-
struct osnoise_context *context;
60-
void *data;
61-
void *params;
62-
time_t start_time;
63-
};
56+
extern struct trace_instance *trace_inst;
57+
extern int stop_tracing;
6458

6559
struct hist_params {
6660
char no_irq;
@@ -103,12 +97,58 @@ struct common_params {
10397
int output_divisor;
10498
int pretty_output;
10599
int quiet;
100+
int user_workload;
106101
int kernel_workload;
102+
int user_data;
103+
int aa_only;
104+
105+
struct actions threshold_actions;
106+
struct actions end_actions;
107+
struct timerlat_u_params user;
108+
};
109+
110+
struct tool_ops;
111+
112+
/*
113+
* osnoise_tool - osnoise based tool definition.
114+
*
115+
* Only the "trace" and "context" fields are used for
116+
* the additional trace instances (record and aa).
117+
*/
118+
struct osnoise_tool {
119+
struct tool_ops *ops;
120+
struct trace_instance trace;
121+
struct osnoise_context *context;
122+
void *data;
123+
struct common_params *params;
124+
time_t start_time;
125+
struct osnoise_tool *record;
126+
struct osnoise_tool *aa;
127+
};
128+
129+
struct tool_ops {
130+
const char *tracer;
131+
const char *comm_prefix;
132+
struct common_params *(*parse_args)(int argc, char *argv[]);
133+
struct osnoise_tool *(*init_tool)(struct common_params *params);
134+
int (*apply_config)(struct osnoise_tool *tool);
135+
int (*enable)(struct osnoise_tool *tool);
136+
int (*main)(struct osnoise_tool *tool);
137+
void (*print_stats)(struct osnoise_tool *tool);
138+
void (*analyze)(struct osnoise_tool *tool, bool stopped);
139+
void (*free)(struct osnoise_tool *tool);
107140
};
108141

109142
int osnoise_set_cpus(struct osnoise_context *context, char *cpus);
110143
void osnoise_restore_cpus(struct osnoise_context *context);
111144

112145
int osnoise_set_workload(struct osnoise_context *context, bool onoff);
113146

147+
void osnoise_destroy_tool(struct osnoise_tool *top);
148+
struct osnoise_tool *osnoise_init_tool(char *tool_name);
149+
struct osnoise_tool *osnoise_init_trace_tool(const char *tracer);
150+
bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record);
151+
114152
int common_apply_config(struct osnoise_tool *tool, struct common_params *params);
153+
int top_main_loop(struct osnoise_tool *tool);
154+
int hist_main_loop(struct osnoise_tool *tool);

0 commit comments

Comments
 (0)