File Index
Files and directories
Sign in
FILE

common.c

File preview with syntax highlighting.

linux-6.19.14/tools/tracing/rtla/src/common.c C
  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
 10struct trace_instance *trace_inst;
 11int stop_tracing;
 12
 13static 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 */
 31static 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 */
 43int
 44common_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
 93out_err:
 94	return -1;
 95}
 96
 97
 98int 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
229out_trace:
230	trace_events_destroy(&tool->record->trace, params->events);
231	params->events = NULL;
232out_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);
239out_exit:
240	exit(return_value);
241}
242
243int 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
301int 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}
~/ Read-only file preview.