diff options
Diffstat (limited to 'tools/tracing/rtla/src/common.c')
| -rw-r--r-- | tools/tracing/rtla/src/common.c | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/tools/tracing/rtla/src/common.c b/tools/tracing/rtla/src/common.c index 32a6faffc714..2e6e3dac1897 100644 --- a/tools/tracing/rtla/src/common.c +++ b/tools/tracing/rtla/src/common.c @@ -1,9 +1,42 @@ // SPDX-License-Identifier: GPL-2.0 #define _GNU_SOURCE +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> #include <unistd.h> #include "common.h" +struct trace_instance *trace_inst; +int stop_tracing; + +static void stop_trace(int sig) +{ + if (stop_tracing) { + /* + * Stop requested twice in a row; abort event processing and + * exit immediately + */ + tracefs_iterate_stop(trace_inst->inst); + return; + } + stop_tracing = 1; + if (trace_inst) + trace_instance_stop(trace_inst); +} + +/* + * set_signals - handles the signal to stop the tool + */ +static void set_signals(struct common_params *params) +{ + signal(SIGINT, stop_trace); + if (params->duration) { + signal(SIGALRM, stop_trace); + alarm(params->duration); + } +} + /* * common_apply_config - apply common configs to the initialized tool */ @@ -61,3 +94,251 @@ out_err: return -1; } + +int run_tool(struct tool_ops *ops, int argc, char *argv[]) +{ + struct common_params *params; + enum result return_value = ERROR; + struct osnoise_tool *tool; + bool stopped; + int retval; + + params = ops->parse_args(argc, argv); + if (!params) + exit(1); + + tool = ops->init_tool(params); + if (!tool) { + err_msg("Could not init osnoise tool\n"); + goto out_exit; + } + tool->ops = ops; + tool->params = params; + + /* + * Save trace instance into global variable so that SIGINT can stop + * the timerlat tracer. + * Otherwise, rtla could loop indefinitely when overloaded. + */ + trace_inst = &tool->trace; + + retval = ops->apply_config(tool); + if (retval) { + err_msg("Could not apply config\n"); + goto out_free; + } + + retval = enable_tracer_by_name(trace_inst->inst, ops->tracer); + if (retval) { + err_msg("Failed to enable %s tracer\n", ops->tracer); + goto out_free; + } + + if (params->set_sched) { + retval = set_comm_sched_attr(ops->comm_prefix, ¶ms->sched_param); + if (retval) { + err_msg("Failed to set sched parameters\n"); + goto out_free; + } + } + + if (params->cgroup && !params->user_data) { + retval = set_comm_cgroup(ops->comm_prefix, params->cgroup_name); + if (!retval) { + err_msg("Failed to move threads to cgroup\n"); + goto out_free; + } + } + + + if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] || + params->end_actions.present[ACTION_TRACE_OUTPUT]) { + tool->record = osnoise_init_trace_tool(ops->tracer); + if (!tool->record) { + err_msg("Failed to enable the trace instance\n"); + goto out_free; + } + params->threshold_actions.trace_output_inst = tool->record->trace.inst; + params->end_actions.trace_output_inst = tool->record->trace.inst; + + if (params->events) { + retval = trace_events_enable(&tool->record->trace, params->events); + if (retval) + goto out_trace; + } + + if (params->buffer_size > 0) { + retval = trace_set_buffer_size(&tool->record->trace, params->buffer_size); + if (retval) + goto out_trace; + } + } + + if (params->user_workload) { + pthread_t user_thread; + + /* rtla asked to stop */ + params->user.should_run = 1; + /* all threads left */ + params->user.stopped_running = 0; + + params->user.set = ¶ms->monitored_cpus; + if (params->set_sched) + params->user.sched_param = ¶ms->sched_param; + else + params->user.sched_param = NULL; + + params->user.cgroup_name = params->cgroup_name; + + retval = pthread_create(&user_thread, NULL, timerlat_u_dispatcher, ¶ms->user); + if (retval) + err_msg("Error creating timerlat user-space threads\n"); + } + + retval = ops->enable(tool); + if (retval) + goto out_trace; + + tool->start_time = time(NULL); + set_signals(params); + + retval = ops->main(tool); + if (retval) + goto out_trace; + + if (params->user_workload && !params->user.stopped_running) { + params->user.should_run = 0; + sleep(1); + } + + ops->print_stats(tool); + + actions_perform(¶ms->end_actions); + + return_value = PASSED; + + stopped = osnoise_trace_is_off(tool, tool->record) && !stop_tracing; + if (stopped) { + printf("%s hit stop tracing\n", ops->tracer); + return_value = FAILED; + } + + if (ops->analyze) + ops->analyze(tool, stopped); + +out_trace: + trace_events_destroy(&tool->record->trace, params->events); + params->events = NULL; +out_free: + ops->free(tool); + osnoise_destroy_tool(tool->record); + osnoise_destroy_tool(tool); + actions_destroy(¶ms->threshold_actions); + actions_destroy(¶ms->end_actions); + free(params); +out_exit: + exit(return_value); +} + +int top_main_loop(struct osnoise_tool *tool) +{ + struct common_params *params = tool->params; + struct trace_instance *trace = &tool->trace; + struct osnoise_tool *record = tool->record; + int retval; + + while (!stop_tracing) { + sleep(params->sleep_time); + + if (params->aa_only && !osnoise_trace_is_off(tool, record)) + continue; + + retval = tracefs_iterate_raw_events(trace->tep, + trace->inst, + NULL, + 0, + collect_registered_events, + trace); + if (retval < 0) { + err_msg("Error iterating on events\n"); + return retval; + } + + if (!params->quiet) + tool->ops->print_stats(tool); + + if (osnoise_trace_is_off(tool, record)) { + actions_perform(¶ms->threshold_actions); + + if (!params->threshold_actions.continue_flag) + /* continue flag not set, break */ + return 0; + + /* continue action reached, re-enable tracing */ + if (record) + trace_instance_start(&record->trace); + if (tool->aa) + trace_instance_start(&tool->aa->trace); + trace_instance_start(trace); + } + + /* is there still any user-threads ? */ + if (params->user_workload) { + if (params->user.stopped_running) { + debug_msg("timerlat user space threads stopped!\n"); + break; + } + } + } + + return 0; +} + +int hist_main_loop(struct osnoise_tool *tool) +{ + struct common_params *params = tool->params; + struct trace_instance *trace = &tool->trace; + int retval = 0; + + while (!stop_tracing) { + sleep(params->sleep_time); + + retval = tracefs_iterate_raw_events(trace->tep, + trace->inst, + NULL, + 0, + collect_registered_events, + trace); + if (retval < 0) { + err_msg("Error iterating on events\n"); + break; + } + + if (osnoise_trace_is_off(tool, tool->record)) { + actions_perform(¶ms->threshold_actions); + + if (!params->threshold_actions.continue_flag) { + /* continue flag not set, break */ + break; + + /* continue action reached, re-enable tracing */ + if (tool->record) + trace_instance_start(&tool->record->trace); + if (tool->aa) + trace_instance_start(&tool->aa->trace); + trace_instance_start(&tool->trace); + } + break; + } + + /* is there still any user-threads ? */ + if (params->user_workload) { + if (params->user.stopped_running) { + debug_msg("user-space threads stopped!\n"); + break; + } + } + } + + return retval; +} |