struct osnoise_hist_data { struct tracefs_hist *trace_hist; struct osnoise_hist_cpu *hist; int entries; int bucket_size; int nr_cpus;
};
/* * osnoise_free_histogram - free runtime data
*/ staticvoid
osnoise_free_histogram(struct osnoise_hist_data *data)
{ int cpu;
/* one histogram for IRQ and one for thread, per CPU */ for (cpu = 0; cpu < data->nr_cpus; cpu++) { if (data->hist[cpu].samples)
free(data->hist[cpu].samples);
}
/* one set of histograms per CPU */ if (data->hist)
free(data->hist);
free(data);
}
/* * osnoise_alloc_histogram - alloc runtime data
*/ staticstruct osnoise_hist_data
*osnoise_alloc_histogram(int nr_cpus, int entries, int bucket_size)
{ struct osnoise_hist_data *data; int cpu;
data = calloc(1, sizeof(*data)); if (!data) return NULL;
/* * osnoise_init_trace_hist - enable events used to collect histogram
*/ staticint osnoise_init_trace_hist(struct osnoise_tool *tool)
{ struct osnoise_params *params = tool->params; struct osnoise_hist_data *data = tool->data; int bucket_size; char buff[128]; int retval = 0;
/* * Set the size of the bucket.
*/
bucket_size = params->output_divisor * params->bucket_size;
snprintf(buff, sizeof(buff), "duration.buckets=%d", bucket_size);
content = tracefs_event_file_read(tool->trace.inst, "osnoise", "sample_threshold", "hist", NULL); if (!content) return;
position = content; while (true) {
position = strstr(position, "duration: ~"); if (!position) break;
position += strlen("duration: ~");
duration = get_llong_from_str(position); if (duration == -1)
err_msg("error reading duration from histogram\n");
position = strstr(position, "cpu:"); if (!position) break;
position += strlen("cpu: ");
cpu = get_llong_from_str(position); if (cpu == -1)
err_msg("error reading cpu from histogram\n");
position = strstr(position, "hitcount:"); if (!position) break;
position += strlen("hitcount: ");
counter = get_llong_from_str(position); if (counter == -1)
err_msg("error reading counter from histogram\n");
/* * osnoise_print_summary - print the summary of the hist data to the output
*/ staticvoid
osnoise_print_summary(struct osnoise_params *params, struct trace_instance *trace, struct osnoise_hist_data *data)
{ int cpu;
if (params->no_summary) return;
if (!params->no_index)
trace_seq_printf(trace->seq, "count:");
for (cpu = 0; cpu < data->nr_cpus; cpu++) { if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus)) continue;
/* * osnoise_hist_usage - prints osnoise hist usage message
*/ staticvoid osnoise_hist_usage(char *usage)
{ int i;
staticconstchar * const msg[] = { "", " usage: rtla osnoise hist [-h] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\", " [-T us] [-t[file]] [-e sys[:event]] [--filter ] [--trigger ] \\", " [-c cpu-list] [-H cpu-list] [-P priority] [-b N] [-E N] [--no-header] [--no-summary] \\", " [--no-index] [--with-zeros] [-C[=cgroup_name]] [--warm-up]", "", " -h/--help: print this menu", " -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit", " -p/--period us: osnoise period in us", " -r/--runtime us: osnoise runtime in us", " -s/--stop us: stop trace if a single sample is higher than the argument in us", " -S/--stop-total us: stop trace if the total sample is higher than the argument in us", " -T/--threshold us: the minimum delta to be considered a noise", " -c/--cpus cpu-list: list of cpus to run osnoise threads", " -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", " -t/--trace[file]: save the stopped trace to [file|osnoise_trace.txt]", " -e/--event : enable the in the trace instance, multiple -e are allowed", " --filter : enable a trace event filter to the previous -e event", " --trigger : enable a trace event trigger to the previous -e event", " -b/--bucket-size N: set the histogram bucket size (default 1)", " -E/--entries N: set the number of entries of the histogram (default 256)", " --no-header: do not print header", " --no-summary: do not print summary", " --no-index: do not print index", " --with-zeros: print zero only entries", " -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", " --warm-up: let the workload run for s seconds before collecting data", " --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
NULL,
};
if (usage)
fprintf(stderr, "%s\n", usage);
fprintf(stderr, "rtla osnoise hist: a per-cpu histogram of the OS noise (version %s)\n",
VERSION);
for (i = 0; msg[i]; i++)
fprintf(stderr, "%s\n", msg[i]);
if (usage) exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
}
/* * osnoise_hist_parse_args - allocs, parse and fill the cmd line parameters
*/ staticstruct osnoise_params
*osnoise_hist_parse_args(int argc, char *argv[])
{ struct osnoise_params *params; struct trace_events *tevent; int retval; int c;
params = calloc(1, sizeof(*params)); if (!params) exit(1);
/* display data in microseconds */
params->output_divisor = 1000;
params->bucket_size = 1;
params->entries = 256;
/* * osnoise_hist_set_signals - handles the signal to stop the tool
*/ staticvoid
osnoise_hist_set_signals(struct osnoise_params *params)
{
signal(SIGINT, stop_hist); if (params->duration) {
signal(SIGALRM, stop_hist);
alarm(params->duration);
}
}
int osnoise_hist_main(int argc, char *argv[])
{ struct osnoise_params *params; struct osnoise_tool *record = NULL; struct osnoise_tool *tool = NULL; enum result return_value = ERROR; struct trace_instance *trace; int retval;
params = osnoise_hist_parse_args(argc, argv); if (!params) exit(1);
tool = osnoise_init_hist(params); if (!tool) {
err_msg("Could not init osnoise hist\n"); goto out_exit;
}
retval = osnoise_hist_apply_config(tool, params); if (retval) {
err_msg("Could not apply config\n"); goto out_destroy;
}
trace = &tool->trace;
retval = enable_osnoise(trace); if (retval) {
err_msg("Failed to enable osnoise tracer\n"); goto out_destroy;
}
retval = osnoise_init_trace_hist(tool); if (retval) goto out_destroy;
if (params->set_sched) {
retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param); if (retval) {
err_msg("Failed to set sched parameters\n"); goto out_free;
}
}
if (params->cgroup) {
retval = set_comm_cgroup("timerlat/", params->cgroup_name); if (!retval) {
err_msg("Failed to move threads to cgroup\n"); goto out_free;
}
}
if (params->trace_output) {
record = osnoise_init_trace_tool("osnoise"); if (!record) {
err_msg("Failed to enable the trace instance\n"); goto out_free;
}
if (params->events) {
retval = trace_events_enable(&record->trace, params->events); if (retval) goto out_hist;
}
if (params->buffer_size > 0) {
retval = trace_set_buffer_size(&record->trace, params->buffer_size); if (retval) goto out_hist;
}
}
/* * Start the tracer here, after having set all instances. * * Let the trace instance start first for the case of hitting a stop * tracing while enabling other instances. The trace instance is the * one with most valuable information.
*/ if (params->trace_output)
trace_instance_start(&record->trace);
trace_instance_start(trace);
if (params->warmup > 0) {
debug_msg("Warming up for %d seconds\n", params->warmup);
sleep(params->warmup); if (stop_tracing) goto out_hist;
/* * Clean up the buffer. The osnoise workload do not run * with tracing off to avoid creating a performance penalty * when not needed.
*/
retval = tracefs_instance_file_write(trace->inst, "trace", ""); if (retval < 0) {
debug_msg("Error cleaning up the buffer"); goto out_hist;
}
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.