lkml.org 
[lkml]   [2021]   [Oct]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH V3 10/19] rtla/osnoise: Add the hist mode
    Date
    The rtla osnoise hist tool collects all osnoise:sample_threshold
    occurrence in a histogram, displaying the results in a user-friendly
    way. The tool also allows many configurations of the osnoise tracer
    and the collection of the tracer output.

    Here is one example of the rtla osnoise hist tool output:
    ---------- %< ----------
    [root@f34 ~]# rtla osnoise hist --bucket-size 10 --entries 100 -c 0-8 -d 1M -r 9000 -P F:1
    # RTLA osnoise histogram
    # Time unit is microseconds (us)
    # Duration: 0 00:01:00
    Index CPU-000 CPU-001 CPU-002 CPU-003 CPU-004 CPU-005 CPU-006 CPU-007 CPU-008
    0 430 434 352 455 440 463 467 436 484
    10 88 88 92 141 120 100 126 166 100
    20 19 7 12 22 8 8 13 13 16
    30 6 0 2 0 1 2 2 1 0
    50 0 0 0 0 0 0 1 0 0
    over: 0 0 0 0 0 0 0 0 0
    count: 543 529 458 618 569 573 609 616 600
    min: 0 0 0 0 0 0 0 0 0
    avg: 0 0 0 0 0 0 0 0 0
    max: 30 20 30 20 30 30 50 30 20
    ---------- >% ----------

    Running
    - rtla osnoise hist --help

    provides information about the available options.

    Cc: Steven Rostedt <rostedt@goodmis.org>
    Cc: Ingo Molnar <mingo@redhat.com>
    Cc: Tom Zanussi <zanussi@kernel.org>
    Cc: Masami Hiramatsu <mhiramat@kernel.org>
    Cc: Juri Lelli <juri.lelli@redhat.com>
    Cc: Clark Williams <williams@redhat.com>
    Cc: John Kacur <jkacur@redhat.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
    Cc: Daniel Bristot de Oliveira <bristot@kernel.org>
    Cc: linux-rt-users@vger.kernel.org
    Cc: linux-trace-devel@vger.kernel.org
    Cc: linux-kernel@vger.kernel.org
    Signed-off-by: Daniel Bristot de Oliveira <bristot@kernel.org>
    ---
    tools/tracing/rtla/src/osnoise.c | 6 +-
    tools/tracing/rtla/src/osnoise.h | 1 +
    tools/tracing/rtla/src/osnoise_hist.c | 783 ++++++++++++++++++++++++++
    3 files changed, 789 insertions(+), 1 deletion(-)
    create mode 100644 tools/tracing/rtla/src/osnoise_hist.c

    diff --git a/tools/tracing/rtla/src/osnoise.c b/tools/tracing/rtla/src/osnoise.c
    index b9866dfdda66..6c6358ebf66f 100644
    --- a/tools/tracing/rtla/src/osnoise.c
    +++ b/tools/tracing/rtla/src/osnoise.c
    @@ -790,7 +790,8 @@ static void osnoise_usage(void)
    " usage: [rtla] osnoise [MODE] ...",
    "",
    " modes:",
    - " top - prints the summary from osnoise tracer",
    + " top - prints the summary from osnoise tracer",
    + " hist - prints a histogram of osnoise samples",
    "",
    "if no MODE is given, the top mode is called, passing the arguments",
    NULL,
    @@ -825,6 +826,9 @@ int osnoise_main(int argc, char *argv[])
    } else if (strcmp(argv[1], "top") == 0) {
    osnoise_top_main(argc-1, &argv[1]);
    exit(0);
    + } else if (strcmp(argv[1], "hist") == 0) {
    + osnoise_hist_main(argc-1, &argv[1]);
    + exit(0);
    }

    usage:
    diff --git a/tools/tracing/rtla/src/osnoise.h b/tools/tracing/rtla/src/osnoise.h
    index 4882ee275ea0..dbaad7a162a2 100644
    --- a/tools/tracing/rtla/src/osnoise.h
    +++ b/tools/tracing/rtla/src/osnoise.h
    @@ -82,5 +82,6 @@ void osnoise_destroy_tool(struct osnoise_tool *top);
    struct osnoise_tool *osnoise_init_tool(char *tool_name);
    struct osnoise_tool *osnoise_init_trace_tool(char *tracer);

    +int osnoise_hist_main(int argc, char *argv[]);
    int osnoise_top_main(int argc, char **argv);
    int osnoise_main(int argc, char **argv);
    diff --git a/tools/tracing/rtla/src/osnoise_hist.c b/tools/tracing/rtla/src/osnoise_hist.c
    new file mode 100644
    index 000000000000..a31de319416f
    --- /dev/null
    +++ b/tools/tracing/rtla/src/osnoise_hist.c
    @@ -0,0 +1,783 @@
    +// SPDX-License-Identifier: GPL-2.0
    +/*
    + * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
    + */
    +
    +#include <getopt.h>
    +#include <stdlib.h>
    +#include <string.h>
    +#include <signal.h>
    +#include <unistd.h>
    +#include <errno.h>
    +#include <stdio.h>
    +#include <time.h>
    +
    +#include "utils.h"
    +#include "osnoise.h"
    +
    +struct osnoise_hist_params {
    + char *cpus;
    + char *monitored_cpus;
    + char *trace_output;
    + unsigned long long runtime;
    + unsigned long long period;
    + long long stop_us;
    + long long stop_total_us;
    + int sleep_time;
    + int duration;
    + int set_sched;
    + int output_divisor;
    + struct sched_attr sched_param;
    +
    + char no_header;
    + char no_summary;
    + char no_index;
    + char with_zeros;
    + int bucket_size;
    + int entries;
    +};
    +
    +struct osnoise_hist_cpu {
    + int *samples;
    + int *thread;
    +
    + int count;
    + int thread_count;
    +
    + unsigned long long min_sample;
    + unsigned long long sum_sample;
    + unsigned long long max_sample;
    +
    + unsigned long long min_thread;
    + unsigned long long sum_thread;
    + unsigned long long max_thread;
    +};
    +
    +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
    + */
    +static void
    +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);
    +
    + if (data->hist[cpu].thread)
    + free(data->hist[cpu].thread);
    + }
    +
    + /* one set of histograms per CPU */
    + if (data->hist)
    + free(data->hist);
    +
    + free(data);
    +}
    +
    +/*
    + * osnoise_alloc_histogram - alloc runtime data
    + */
    +static struct 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;
    +
    + data->entries = entries;
    + data->bucket_size = bucket_size;
    + data->nr_cpus = nr_cpus;
    +
    + /* one set of histograms per CPU */
    + data->hist = calloc(1, sizeof(*data->hist) * nr_cpus);
    + if (!data->hist)
    + goto cleanup;
    +
    + /* one histogram for IRQ and one for thread, per cpu */
    + for (cpu = 0; cpu < nr_cpus; cpu++) {
    + data->hist[cpu].samples = calloc(1, sizeof(*data->hist) * (entries + 1));
    + if (!data->hist[cpu].samples)
    + goto cleanup;
    + data->hist[cpu].thread = calloc(1, sizeof(*data->hist) * (entries + 1));
    + if (!data->hist[cpu].thread)
    + goto cleanup;
    + }
    +
    + /* set the min to max */
    + for (cpu = 0; cpu < nr_cpus; cpu++) {
    + data->hist[cpu].min_sample = ~0;
    + data->hist[cpu].min_thread = ~0;
    + }
    +
    + return data;
    +
    +cleanup:
    + osnoise_free_histogram(data);
    + return NULL;
    +}
    +
    +static void osnoise_hist_update_multiple(struct osnoise_tool *tool, int cpu,
    + unsigned long long duration, int count)
    +{
    + struct osnoise_hist_params *params = tool->params;
    + struct osnoise_hist_data *data = tool->data;
    + int entries = data->entries;
    + int bucket;
    + int *hist;
    +
    + if (params->output_divisor)
    + duration = duration / params->output_divisor;
    +
    + if (data->bucket_size)
    + bucket = duration / data->bucket_size;
    +
    + hist = data->hist[cpu].samples;
    + data->hist[cpu].count += count;
    + update_min(&data->hist[cpu].min_sample, &duration);
    + update_sum(&data->hist[cpu].sum_sample, &duration);
    + update_max(&data->hist[cpu].max_sample, &duration);
    +
    + if (bucket < entries)
    + hist[bucket] += count;
    + else
    + hist[entries] += count;
    +}
    +
    +/*
    + * osnoise_destroy_trace_hist - disable events used to collect histogram
    + */
    +static void osnoise_destroy_trace_hist(struct osnoise_tool *tool)
    +{
    + struct osnoise_hist_data *data = tool->data;
    +
    + tracefs_hist_pause(tool->trace.inst, data->trace_hist);
    + tracefs_hist_destroy(tool->trace.inst, data->trace_hist);
    +}
    +
    +/*
    + * osnoise_init_trace_hist - enable events used to collect histogram
    + */
    +static int osnoise_init_trace_hist(struct osnoise_tool *tool)
    +{
    + struct osnoise_hist_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);
    +
    + data->trace_hist = tracefs_hist_alloc(tool->trace.tep, "osnoise", "sample_threshold",
    + buff, TRACEFS_HIST_KEY_NORMAL);
    + if (!data->trace_hist)
    + return 1;
    +
    + retval = tracefs_hist_add_key(data->trace_hist, "cpu", 0);
    + if (retval)
    + goto out_err;
    +
    + retval = tracefs_hist_start(tool->trace.inst, data->trace_hist);
    + if (retval)
    + goto out_err;
    +
    + return 0;
    +
    +out_err:
    + osnoise_destroy_trace_hist(tool);
    + return 1;
    +}
    +
    +/*
    + * osnoise_read_trace_hist - parse histogram file and file osnoise histogram
    + */
    +static void osnoise_read_trace_hist(struct osnoise_tool *tool)
    +{
    + struct osnoise_hist_data *data = tool->data;
    + long cpu, counter, duration;
    + char *content, *position;
    +
    + tracefs_hist_pause(tool->trace.inst, data->trace_hist);
    +
    + 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_long_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_long_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_long_from_str(position);
    + if (counter == -1)
    + err_msg("error reading counter from histogram\n");
    +
    + osnoise_hist_update_multiple(tool, cpu, duration, counter);
    + }
    + free(content);
    +}
    +
    +/*
    + * osnoise_hist_header - print the header of the tracer to the output
    + */
    +static void osnoise_hist_header(struct osnoise_tool *tool)
    +{
    + struct osnoise_hist_params *params = tool->params;
    + struct osnoise_hist_data *data = tool->data;
    + struct trace_seq *s = tool->trace.seq;
    + char duration[26];
    + int cpu;
    +
    + if (params->no_header)
    + return;
    +
    + get_duration(tool->start_time, duration, sizeof(duration));
    + trace_seq_printf(s, "# RTLA osnoise histogram\n");
    + trace_seq_printf(s, "# Time unit is %s (%s)\n",
    + params->output_divisor == 1 ? "nanoseconds" : "microseconds",
    + params->output_divisor == 1 ? "ns" : "us");
    +
    + trace_seq_printf(s, "# Duration: %s\n", duration);
    +
    + if (!params->no_index)
    + trace_seq_printf(s, "Index");
    +
    + for (cpu = 0; cpu < data->nr_cpus; cpu++) {
    + if (params->cpus && !params->monitored_cpus[cpu])
    + continue;
    +
    + trace_seq_printf(s, " CPU-%03d", cpu);
    + }
    + trace_seq_printf(s, "\n");
    +
    + trace_seq_do_printf(s);
    + trace_seq_reset(s);
    +}
    +
    +/*
    + * osnoise_print_summary - print the summary of the hist data to the output
    + */
    +static void
    +osnoise_print_summary(struct osnoise_hist_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 && !params->monitored_cpus[cpu])
    + continue;
    +
    + trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].count);
    + }
    + trace_seq_printf(trace->seq, "\n");
    +
    + if (!params->no_index)
    + trace_seq_printf(trace->seq, "min: ");
    +
    + for (cpu = 0; cpu < data->nr_cpus; cpu++) {
    + if (params->cpus && !params->monitored_cpus[cpu])
    + continue;
    + trace_seq_printf(trace->seq, "%9llu ", data->hist[cpu].min_sample);
    +
    + }
    + trace_seq_printf(trace->seq, "\n");
    +
    + if (!params->no_index)
    + trace_seq_printf(trace->seq, "avg: ");
    +
    + for (cpu = 0; cpu < data->nr_cpus; cpu++) {
    + if (params->cpus && !params->monitored_cpus[cpu])
    + continue;
    +
    + if (data->hist[cpu].count)
    + trace_seq_printf(trace->seq, "%9llu ",
    + data->hist[cpu].sum_sample / data->hist[cpu].count);
    + else
    + trace_seq_printf(trace->seq, " - ");
    + }
    + trace_seq_printf(trace->seq, "\n");
    +
    + if (!params->no_index)
    + trace_seq_printf(trace->seq, "max: ");
    +
    + for (cpu = 0; cpu < data->nr_cpus; cpu++) {
    + if (params->cpus && !params->monitored_cpus[cpu])
    + continue;
    +
    + trace_seq_printf(trace->seq, "%9llu ", data->hist[cpu].max_sample);
    +
    + }
    + trace_seq_printf(trace->seq, "\n");
    + trace_seq_do_printf(trace->seq);
    + trace_seq_reset(trace->seq);
    +}
    +
    +/*
    + * osnoise_print_stats - print data for all CPUs
    + */
    +static void
    +osnoise_print_stats(struct osnoise_hist_params *params, struct osnoise_tool *tool)
    +{
    + struct osnoise_hist_data *data = tool->data;
    + struct trace_instance *trace = &tool->trace;
    + int bucket, cpu;
    + int total;
    +
    + osnoise_hist_header(tool);
    +
    + for (bucket = 0; bucket < data->entries; bucket++) {
    + total = 0;
    +
    + if (!params->no_index)
    + trace_seq_printf(trace->seq, "%-6d",
    + bucket * data->bucket_size);
    +
    + for (cpu = 0; cpu < data->nr_cpus; cpu++) {
    + if (params->cpus && !params->monitored_cpus[cpu])
    + continue;
    +
    + total += data->hist[cpu].samples[bucket];
    + trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].samples[bucket]);
    + }
    +
    + if (total == 0 && !params->with_zeros) {
    + trace_seq_reset(trace->seq);
    + continue;
    + }
    +
    + trace_seq_printf(trace->seq, "\n");
    + trace_seq_do_printf(trace->seq);
    + trace_seq_reset(trace->seq);
    + }
    +
    + if (!params->no_index)
    + trace_seq_printf(trace->seq, "over: ");
    +
    + for (cpu = 0; cpu < data->nr_cpus; cpu++) {
    + if (params->cpus && !params->monitored_cpus[cpu])
    + continue;
    +
    + trace_seq_printf(trace->seq, "%9d ",
    + data->hist[cpu].samples[data->entries]);
    + }
    + trace_seq_printf(trace->seq, "\n");
    + trace_seq_do_printf(trace->seq);
    + trace_seq_reset(trace->seq);
    +
    + osnoise_print_summary(params, trace, data);
    +}
    +
    +/*
    + * osnoise_hist_usage - prints osnoise hist usage message
    + */
    +static void osnoise_hist_usage(char *usage)
    +{
    + int i;
    +
    + static const char * const msg[] = {
    + "",
    + " usage: rtla osnoise hist [-h] [-p us] [-r us] [-s us] [-S us] [-T[=file]] \\",
    + " [-c cpu-list] [-P priority] [-b N] [-e N] [--no-header] [--no-summary] \\",
    + " [--no-index] [--with-zeros]",
    + "",
    + " -h/--help: print this menu",
    + " -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",
    + " -c/--cpus cpu-list: list of cpus to run osnoise threads",
    + " -d/--duration time[s|m|h|d]: duration of the session",
    + " -t/--trace[=file]: save the stopped trace to [file|osnoise_trace.txt]",
    + " -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",
    + 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]);
    + exit(1);
    +}
    +
    +/*
    + * osnoise_hist_parse_args - allocs, parse and fill the cmd line parameters
    + */
    +static struct osnoise_hist_params
    +*osnoise_hist_parse_args(int argc, char *argv[])
    +{
    + struct osnoise_hist_params *params;
    + 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;
    +
    + while (1) {
    + static struct option long_options[] = {
    + {"bucket-size", required_argument, 0, 'b'},
    + {"entries", required_argument, 0, 'e'},
    + {"cpus", required_argument, 0, 'c'},
    + {"debug", no_argument, 0, 'D'},
    + {"duration", required_argument, 0, 'd'},
    + {"help", no_argument, 0, 'h'},
    + {"period", required_argument, 0, 'p'},
    + {"priority", required_argument, 0, 'P'},
    + {"runtime", required_argument, 0, 'r'},
    + {"stop", required_argument, 0, 's'},
    + {"stop-total", required_argument, 0, 'S'},
    + {"trace", optional_argument, 0, 't'},
    + {"no-header", no_argument, 0, '0'},
    + {"no-summary", no_argument, 0, '1'},
    + {"no-index", no_argument, 0, '2'},
    + {"with-zeros", no_argument, 0, '3'},
    + {0, 0, 0, 0}
    + };
    +
    + /* getopt_long stores the option index here. */
    + int option_index = 0;
    +
    + c = getopt_long(argc, argv, "c:b:d:e:Dhp:P:r:s:S:t::0123",
    + long_options, &option_index);
    +
    + /* detect the end of the options. */
    + if (c == -1)
    + break;
    +
    + switch (c) {
    + case 'b':
    + params->bucket_size = get_long_from_str(optarg);
    + if ((params->bucket_size == 0) || (params->bucket_size >= 1000000))
    + osnoise_hist_usage("Bucket size needs to be > 0 and <= 1000000\n");
    + break;
    + case 'c':
    + retval = parse_cpu_list(optarg, &params->monitored_cpus);
    + if (retval)
    + osnoise_hist_usage("\nInvalid -c cpu list\n");
    + params->cpus = optarg;
    + debug_msg("-c for %s\n", params->cpus);
    + break;
    + case 'D':
    + config_debug = 1;
    + break;
    + case 'd':
    + params->duration = parse_seconds_duration(optarg);
    + if (!params->duration)
    + osnoise_hist_usage("Invalid -D duration\n");
    + break;
    + case 'e':
    + params->entries = get_long_from_str(optarg);
    + if ((params->entries < 10) || (params->entries > 9999999))
    + osnoise_hist_usage("Entries must be > 10 and < 9999999\n");
    + break;
    + case 'h':
    + case '?':
    + osnoise_hist_usage(NULL);
    + break;
    + case 'p':
    + params->period = get_long_from_str(optarg);
    + if (params->period > 10000000)
    + osnoise_hist_usage("Period longer than 10 s\n");
    + break;
    + case 'P':
    + retval = parse_prio(optarg, &params->sched_param);
    + if (retval == -1)
    + osnoise_hist_usage("Invalid -P priority");
    + params->set_sched = 1;
    + break;
    + case 'r':
    + params->runtime = get_long_from_str(optarg);
    + if (params->runtime < 100)
    + osnoise_hist_usage("Runtime shorter than 100 us\n");
    + break;
    + case 's':
    + params->stop_us = get_long_from_str(optarg);
    + break;
    + case 'S':
    + params->stop_total_us = get_long_from_str(optarg);
    + break;
    + case 't':
    + if (optarg)
    + /* skip = */
    + params->trace_output = &optarg[1];
    + else
    + params->trace_output = "osnoise_trace.txt";
    + break;
    + case '0': /* no header */
    + params->no_header = 1;
    + break;
    + case '1': /* no summary */
    + params->no_summary = 1;
    + break;
    + case '2': /* no index */
    + params->no_index = 1;
    + break;
    + case '3': /* with zeros */
    + params->with_zeros = 1;
    + break;
    + default:
    + osnoise_hist_usage("Invalid option");
    + }
    + }
    +
    + if (geteuid()) {
    + err_msg("rtla needs root permission\n");
    + exit(EXIT_FAILURE);
    + }
    +
    + if (params->no_index && !params->with_zeros)
    + osnoise_hist_usage("no-index set and with-zeros not set - it does not make sense");
    +
    + return params;
    +}
    +
    +/*
    + * osnoise_hist_apply_config - apply the hist configs to the initialized tool
    + */
    +static int
    +osnoise_hist_apply_config(struct osnoise_tool *tool, struct osnoise_hist_params *params)
    +{
    + int retval;
    +
    + if (!params->sleep_time)
    + params->sleep_time = 1;
    +
    + if (params->cpus) {
    + retval = osnoise_set_cpus(tool->context, params->cpus);
    + if (retval) {
    + err_msg("Failed to apply CPUs config\n");
    + goto out_err;
    + }
    + }
    +
    + if (params->runtime || params->period) {
    + retval = osnoise_set_runtime_period(tool->context,
    + params->runtime,
    + params->period);
    + if (retval) {
    + err_msg("Failed to set runtime and/or period\n");
    + goto out_err;
    + }
    + }
    +
    + if (params->stop_us)
    + osnoise_set_stop_us(tool->context, params->stop_us);
    +
    + if (params->stop_total_us)
    + osnoise_set_stop_total_us(tool->context, params->stop_total_us);
    +
    + return 0;
    +
    +out_err:
    + return -1;
    +}
    +
    +/*
    + * osnoise_init_hist - initialize a osnoise hist tool with parameters
    + */
    +static struct osnoise_tool
    +*osnoise_init_hist(struct osnoise_hist_params *params)
    +{
    + struct osnoise_tool *tool;
    + int nr_cpus;
    +
    + nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
    +
    + tool = osnoise_init_tool("osnoise_hist");
    + if (!tool)
    + return NULL;
    +
    + tool->data = osnoise_alloc_histogram(nr_cpus, params->entries, params->bucket_size);
    + if (!tool->data)
    + goto out_err;
    +
    + tool->params = params;
    +
    + return tool;
    +
    +out_err:
    + osnoise_destroy_tool(tool);
    + return NULL;
    +}
    +
    +static int stop_tracing;
    +static void stop_hist(int sig)
    +{
    + stop_tracing = 1;
    +}
    +
    +/*
    + * osnoise_hist_set_signals - handles the signal to stop the tool
    + */
    +static void
    +osnoise_hist_set_signals(struct osnoise_hist_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_hist_params *params;
    + struct trace_instance *trace;
    + struct osnoise_tool *record;
    + struct osnoise_tool *tool;
    + int return_value = 1;
    + 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_exit;
    + }
    +
    + 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/", &params->sched_param);
    + if (retval)
    + osnoise_hist_usage("Failed to set sched parameters\n");
    + }
    +
    + trace_instance_start(trace);
    +
    + if (params->trace_output) {
    + record = osnoise_init_trace_tool("osnoise");
    + if (!record) {
    + err_msg("Failed to enable the trace instance\n");
    + goto out_hist;
    + }
    + trace_instance_start(&record->trace);
    + }
    +
    + tool->start_time = time(NULL);
    + osnoise_hist_set_signals(params);
    +
    + 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");
    + goto out_hist;
    + }
    +
    + if (!tracefs_trace_is_on(trace->inst))
    + break;
    + };
    +
    + osnoise_read_trace_hist(tool);
    +
    + osnoise_print_stats(params, tool);
    +
    + return_value = 0;
    +
    + if (!tracefs_trace_is_on(trace->inst)) {
    + printf("rtla timelat hit stop tracing\n");
    + if (params->trace_output) {
    + printf(" Saving trace to %s\n", params->trace_output);
    + save_trace_to_file(record->trace.inst, params->trace_output);
    + }
    + }
    +
    +out_hist:
    + osnoise_free_histogram(tool->data);
    +out_destroy:
    + osnoise_destroy_tool(tool);
    + if (params->trace_output)
    + osnoise_destroy_tool(record);
    + free(params);
    +out_exit:
    + exit(return_value);
    +}
    --
    2.31.1
    \
     
     \ /
      Last update: 2021-10-18 18:50    [W:4.152 / U:0.248 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site