data = calloc(1, sizeof(*data)); if (!data) return NULL;
data->nr_cpus = nr_cpus;
/* one set of histograms per CPU */
data->cpu_data = calloc(1, sizeof(*data->cpu_data) * nr_cpus); if (!data->cpu_data) goto cleanup;
/* set the min to max */ for (cpu = 0; cpu < nr_cpus; cpu++) {
data->cpu_data[cpu].min_irq = ~0;
data->cpu_data[cpu].min_thread = ~0;
data->cpu_data[cpu].min_user = ~0;
}
if (nr_cpus == -1)
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
if (!params->quiet)
clear_terminal(trace->seq);
timerlat_top_reset_sum(&summary);
timerlat_top_header(params, top);
for (i = 0; i < nr_cpus; i++) { if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus)) continue;
timerlat_top_print(top, i);
timerlat_top_update_sum(top, i, &summary);
}
/* *timerlat_top_usage-printstimerlattopusagemessage
*/ staticvoid timerlat_top_usage(char *usage)
{ int i;
staticconstchar *const msg[] = { "", " usage: rtla timerlat [top] [-h] [-q] [-a us] [-d s] [-D] [-n] [-p us] [-i us] [-T us] [-s us] \\", " [[-t[file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] [-H cpu-list]\\", " [-P priority] [--dma-latency us] [--aa-only us] [-C[=cgroup_name]] [-u|-k] [--warm-up s] [--deepest-idle-state n]", "", " -h/--help: print this menu", " -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit", " --aa-only us: stop if <us> latency is hit, only printing the auto analysis (reduces CPU usage)", " -p/--period us: timerlat period in us", " -i/--irq us: stop trace if the irq latency is higher than the argument in us", " -T/--thread us: stop trace if the thread latency is higher than the argument in us", " -s/--stack us: save the stack trace at the IRQ if a thread latency is higher than the argument in us", " -c/--cpus cpus: run the tracer only on the given cpus", " -H/--house-keeping cpus: run rtla control threads only on the given cpus", " -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited", " -d/--duration time[s|m|h|d]: duration of the session", " -D/--debug: print debug info", " --dump-tasks: prints the task running on all CPUs if stop conditions are met (depends on !--no-aa)", " -t/--trace[file]: save the stopped trace to [file|timerlat_trace.txt]", " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed", " --filter <command>: enable a trace event filter to the previous -e event", " --trigger <command>: enable a trace event trigger to the previous -e event", " -n/--nano: display data in nanoseconds", " --no-aa: disable auto-analysis, reducing rtla timerlat cpu usage", " -q/--quiet print only a summary at the end", " --dma-latency us: set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency", " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters", " o:prio - use SCHED_OTHER with prio", " r:prio - use SCHED_RR with prio", " f:prio - use SCHED_FIFO with prio", " d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period", " in nanoseconds", " -u/--user-threads: use rtla user-space threads instead of kernel-space timerlat threads", " -k/--kernel-threads: use timerlat kernel-space threads instead of rtla user-space threads", " -U/--user-load: enable timerlat for user-defined user-space workload", " --warm-up s: let the workload run for s seconds before collecting data", " --trace-buffer-size kB: set the per-cpu trace buffer size in kB", " --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency", " --on-threshold <action>: define action to be executed at latency threshold, multiple are allowed", " --on-end: define action to be executed at measurement end, multiple are allowed",
NULL,
};
if (usage)
fprintf(stderr, "%s\n", usage);
fprintf(stderr, "rtla timerlat top: a per-cpu summary of the timer latency (version %s)\n",
VERSION);
for (i = 0; msg[i]; i++)
fprintf(stderr, "%s\n", msg[i]);
while (!stop_tracing) {
sleep(params->sleep_time);
if (params->aa_only && !osnoise_trace_is_off(top, 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)
timerlat_print_stats(params, top);
if (osnoise_trace_is_off(top, 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 (record)
trace_instance_start(&record->trace); if (!params->no_aa)
trace_instance_start(&aa->trace);
trace_instance_start(trace);
}
/* is there still any user-threads ? */ if (params->user_workload) { if (params_u->stopped_running) {
debug_msg("timerlat user space threads stopped!\n"); break;
}
}
}
if (!params->quiet)
timerlat_print_stats(params, top);
if (wait_retval == 1) { /* Stopping requested by tracer */
actions_perform(¶ms->threshold_actions);
if (!params->threshold_actions.continue_flag) /* continue flag not set, break */ break;
/* continue action reached, re-enable tracing */ if (record)
trace_instance_start(&record->trace); if (!params->no_aa)
trace_instance_start(&aa->trace);
timerlat_bpf_restart_tracing();
}
/* is there still any user-threads ? */ if (params->user_workload) { if (params_u->stopped_running) {
debug_msg("timerlat user space threads stopped!\n"); break;
}
}
}
return0;
}
int timerlat_top_main(int argc, char *argv[])
{ struct timerlat_params *params; struct osnoise_tool *record = NULL; struct timerlat_u_params params_u; enum result return_value = ERROR; struct osnoise_tool *top = NULL; struct osnoise_tool *aa = NULL; struct trace_instance *trace; int dma_latency_fd = -1;
pthread_t timerlat_u; char *max_lat; int retval; int nr_cpus, i;
params = timerlat_top_parse_args(argc, argv); if (!params) exit(1);
top = timerlat_init_top(params); if (!top) {
err_msg("Could not init osnoise top\n"); goto out_exit;
}
retval = timerlat_top_apply_config(top, params); if (retval) {
err_msg("Could not apply config\n"); goto out_free;
}
retval = enable_timerlat(trace); if (retval) {
err_msg("Failed to enable timerlat tracer\n"); goto out_free;
}
if (params->set_sched) {
retval = set_comm_sched_attr("timerlat/", ¶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("timerlat/", params->cgroup_name); if (!retval) {
err_msg("Failed to move threads to cgroup\n"); goto out_free;
}
}
if (params->dma_latency >= 0) {
dma_latency_fd = set_cpu_dma_latency(params->dma_latency); if (dma_latency_fd < 0) {
err_msg("Could not set /dev/cpu_dma_latency.\n"); goto out_free;
}
}
if (params->deepest_idle_state >= -1) { if (!have_libcpupower_support()) {
err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n"); goto out_free;
}
nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
for (i = 0; i < nr_cpus; i++) { if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus)) continue; if (save_cpu_idle_disable_state(i) < 0) {
err_msg("Could not save cpu idle state.\n"); goto out_free;
} if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
err_msg("Could not set deepest cpu idle state.\n"); goto out_free;
}
}
}
if (params->threshold_actions.present[ACTION_TRACE_OUTPUT] ||
params->end_actions.present[ACTION_TRACE_OUTPUT]) {
record = osnoise_init_trace_tool("timerlat"); if (!record) {
err_msg("Failed to enable the trace instance\n"); goto out_free;
}
params->threshold_actions.trace_output_inst = record->trace.inst;
params->end_actions.trace_output_inst = record->trace.inst;
if (params->events) {
retval = trace_events_enable(&record->trace, params->events); if (retval) goto out_top;
}
if (params->buffer_size > 0) {
retval = trace_set_buffer_size(&record->trace, params->buffer_size); if (retval) goto out_top;
}
}
if (!params->no_aa) {
aa = osnoise_init_tool("timerlat_aa"); if (!aa) goto out_top;
retval = timerlat_aa_init(aa, params->dump_tasks); if (retval) {
err_msg("Failed to enable the auto analysis instance\n"); goto out_top;
}
/* if it is re-using the main instance, there is no need to start it */ if (aa != top) {
retval = enable_timerlat(&aa->trace); if (retval) {
err_msg("Failed to enable timerlat tracer\n"); goto out_top;
}
}
}
if (params->user_workload) { /* rtla asked to stop */
params_u.should_run = 1; /* all threads left */
params_u.stopped_running = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.