11eceb2fcSDaniel Bristot de Oliveira // SPDX-License-Identifier: GPL-2.0
21eceb2fcSDaniel Bristot de Oliveira /*
31eceb2fcSDaniel Bristot de Oliveira * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
41eceb2fcSDaniel Bristot de Oliveira */
51eceb2fcSDaniel Bristot de Oliveira
6272ced25SDaniel Bristot de Oliveira #define _GNU_SOURCE
71eceb2fcSDaniel Bristot de Oliveira #include <getopt.h>
81eceb2fcSDaniel Bristot de Oliveira #include <stdlib.h>
91eceb2fcSDaniel Bristot de Oliveira #include <string.h>
101eceb2fcSDaniel Bristot de Oliveira #include <signal.h>
111eceb2fcSDaniel Bristot de Oliveira #include <unistd.h>
121eceb2fcSDaniel Bristot de Oliveira #include <stdio.h>
131eceb2fcSDaniel Bristot de Oliveira #include <time.h>
141eceb2fcSDaniel Bristot de Oliveira
151eceb2fcSDaniel Bristot de Oliveira #include "osnoise.h"
161eceb2fcSDaniel Bristot de Oliveira
171eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_cpu {
181eceb2fcSDaniel Bristot de Oliveira unsigned long long sum_runtime;
191eceb2fcSDaniel Bristot de Oliveira unsigned long long sum_noise;
201eceb2fcSDaniel Bristot de Oliveira unsigned long long max_noise;
211eceb2fcSDaniel Bristot de Oliveira unsigned long long max_sample;
221eceb2fcSDaniel Bristot de Oliveira
231eceb2fcSDaniel Bristot de Oliveira unsigned long long hw_count;
241eceb2fcSDaniel Bristot de Oliveira unsigned long long nmi_count;
251eceb2fcSDaniel Bristot de Oliveira unsigned long long irq_count;
261eceb2fcSDaniel Bristot de Oliveira unsigned long long softirq_count;
271eceb2fcSDaniel Bristot de Oliveira unsigned long long thread_count;
281eceb2fcSDaniel Bristot de Oliveira
291eceb2fcSDaniel Bristot de Oliveira int sum_cycles;
301eceb2fcSDaniel Bristot de Oliveira };
311eceb2fcSDaniel Bristot de Oliveira
321eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_data {
331eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_cpu *cpu_data;
341eceb2fcSDaniel Bristot de Oliveira int nr_cpus;
351eceb2fcSDaniel Bristot de Oliveira };
361eceb2fcSDaniel Bristot de Oliveira
371eceb2fcSDaniel Bristot de Oliveira /*
381eceb2fcSDaniel Bristot de Oliveira * osnoise_free_top - free runtime data
391eceb2fcSDaniel Bristot de Oliveira */
401eceb2fcSDaniel Bristot de Oliveira static void
osnoise_free_top(struct osnoise_top_data * data)411eceb2fcSDaniel Bristot de Oliveira osnoise_free_top(struct osnoise_top_data *data)
421eceb2fcSDaniel Bristot de Oliveira {
431eceb2fcSDaniel Bristot de Oliveira free(data->cpu_data);
441eceb2fcSDaniel Bristot de Oliveira free(data);
451eceb2fcSDaniel Bristot de Oliveira }
461eceb2fcSDaniel Bristot de Oliveira
471eceb2fcSDaniel Bristot de Oliveira /*
481eceb2fcSDaniel Bristot de Oliveira * osnoise_alloc_histogram - alloc runtime data
491eceb2fcSDaniel Bristot de Oliveira */
osnoise_alloc_top(int nr_cpus)501eceb2fcSDaniel Bristot de Oliveira static struct osnoise_top_data *osnoise_alloc_top(int nr_cpus)
511eceb2fcSDaniel Bristot de Oliveira {
521eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_data *data;
531eceb2fcSDaniel Bristot de Oliveira
541eceb2fcSDaniel Bristot de Oliveira data = calloc(1, sizeof(*data));
551eceb2fcSDaniel Bristot de Oliveira if (!data)
561eceb2fcSDaniel Bristot de Oliveira return NULL;
571eceb2fcSDaniel Bristot de Oliveira
581eceb2fcSDaniel Bristot de Oliveira data->nr_cpus = nr_cpus;
591eceb2fcSDaniel Bristot de Oliveira
601eceb2fcSDaniel Bristot de Oliveira /* one set of histograms per CPU */
611eceb2fcSDaniel Bristot de Oliveira data->cpu_data = calloc(1, sizeof(*data->cpu_data) * nr_cpus);
621eceb2fcSDaniel Bristot de Oliveira if (!data->cpu_data)
631eceb2fcSDaniel Bristot de Oliveira goto cleanup;
641eceb2fcSDaniel Bristot de Oliveira
651eceb2fcSDaniel Bristot de Oliveira return data;
661eceb2fcSDaniel Bristot de Oliveira
671eceb2fcSDaniel Bristot de Oliveira cleanup:
681eceb2fcSDaniel Bristot de Oliveira osnoise_free_top(data);
691eceb2fcSDaniel Bristot de Oliveira return NULL;
701eceb2fcSDaniel Bristot de Oliveira }
711eceb2fcSDaniel Bristot de Oliveira
721eceb2fcSDaniel Bristot de Oliveira /*
731eceb2fcSDaniel Bristot de Oliveira * osnoise_top_handler - this is the handler for osnoise tracer events
741eceb2fcSDaniel Bristot de Oliveira */
751eceb2fcSDaniel Bristot de Oliveira static int
osnoise_top_handler(struct trace_seq * s,struct tep_record * record,struct tep_event * event,void * context)761eceb2fcSDaniel Bristot de Oliveira osnoise_top_handler(struct trace_seq *s, struct tep_record *record,
771eceb2fcSDaniel Bristot de Oliveira struct tep_event *event, void *context)
781eceb2fcSDaniel Bristot de Oliveira {
791eceb2fcSDaniel Bristot de Oliveira struct trace_instance *trace = context;
801eceb2fcSDaniel Bristot de Oliveira struct osnoise_tool *tool;
811eceb2fcSDaniel Bristot de Oliveira unsigned long long val;
821eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_cpu *cpu_data;
831eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_data *data;
841eceb2fcSDaniel Bristot de Oliveira int cpu = record->cpu;
851eceb2fcSDaniel Bristot de Oliveira
861eceb2fcSDaniel Bristot de Oliveira tool = container_of(trace, struct osnoise_tool, trace);
871eceb2fcSDaniel Bristot de Oliveira
881eceb2fcSDaniel Bristot de Oliveira data = tool->data;
891eceb2fcSDaniel Bristot de Oliveira cpu_data = &data->cpu_data[cpu];
901eceb2fcSDaniel Bristot de Oliveira
911eceb2fcSDaniel Bristot de Oliveira cpu_data->sum_cycles++;
921eceb2fcSDaniel Bristot de Oliveira
931eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "runtime", record, &val, 1);
941eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->sum_runtime, &val);
951eceb2fcSDaniel Bristot de Oliveira
961eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "noise", record, &val, 1);
971eceb2fcSDaniel Bristot de Oliveira update_max(&cpu_data->max_noise, &val);
981eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->sum_noise, &val);
991eceb2fcSDaniel Bristot de Oliveira
1001eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "max_sample", record, &val, 1);
1011eceb2fcSDaniel Bristot de Oliveira update_max(&cpu_data->max_sample, &val);
1021eceb2fcSDaniel Bristot de Oliveira
1031eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "hw_count", record, &val, 1);
1041eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->hw_count, &val);
1051eceb2fcSDaniel Bristot de Oliveira
1061eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "nmi_count", record, &val, 1);
1071eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->nmi_count, &val);
1081eceb2fcSDaniel Bristot de Oliveira
1091eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "irq_count", record, &val, 1);
1101eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->irq_count, &val);
1111eceb2fcSDaniel Bristot de Oliveira
1121eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "softirq_count", record, &val, 1);
1131eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->softirq_count, &val);
1141eceb2fcSDaniel Bristot de Oliveira
1151eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "thread_count", record, &val, 1);
1161eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->thread_count, &val);
1171eceb2fcSDaniel Bristot de Oliveira
1181eceb2fcSDaniel Bristot de Oliveira return 0;
1191eceb2fcSDaniel Bristot de Oliveira }
1201eceb2fcSDaniel Bristot de Oliveira
1211eceb2fcSDaniel Bristot de Oliveira /*
1221eceb2fcSDaniel Bristot de Oliveira * osnoise_top_header - print the header of the tool output
1231eceb2fcSDaniel Bristot de Oliveira */
osnoise_top_header(struct osnoise_tool * top)1241eceb2fcSDaniel Bristot de Oliveira static void osnoise_top_header(struct osnoise_tool *top)
1251eceb2fcSDaniel Bristot de Oliveira {
126025b2179STomas Glozar struct osnoise_params *params = top->params;
1271eceb2fcSDaniel Bristot de Oliveira struct trace_seq *s = top->trace.seq;
1281eceb2fcSDaniel Bristot de Oliveira char duration[26];
1291eceb2fcSDaniel Bristot de Oliveira
1301eceb2fcSDaniel Bristot de Oliveira get_duration(top->start_time, duration, sizeof(duration));
1311eceb2fcSDaniel Bristot de Oliveira
13259237b0cSLuis Claudio R. Goncalves if (params->pretty_output)
1331eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\033[2;37;40m");
13459237b0cSLuis Claudio R. Goncalves
1351f428356SDaniel Bristot de Oliveira trace_seq_printf(s, " ");
1361f428356SDaniel Bristot de Oliveira
1371f428356SDaniel Bristot de Oliveira if (params->mode == MODE_OSNOISE) {
1381eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "Operating System Noise");
1391eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " ");
1401f428356SDaniel Bristot de Oliveira } else if (params->mode == MODE_HWNOISE) {
1411f428356SDaniel Bristot de Oliveira trace_seq_printf(s, "Hardware-related Noise");
1421f428356SDaniel Bristot de Oliveira }
1431f428356SDaniel Bristot de Oliveira
1441eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " ");
14559237b0cSLuis Claudio R. Goncalves
14659237b0cSLuis Claudio R. Goncalves if (params->pretty_output)
1471eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\033[0;0;0m");
1481eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\n");
1491eceb2fcSDaniel Bristot de Oliveira
1501eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "duration: %9s | time is in us\n", duration);
1511eceb2fcSDaniel Bristot de Oliveira
15259237b0cSLuis Claudio R. Goncalves if (params->pretty_output)
1531eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\033[2;30;47m");
15459237b0cSLuis Claudio R. Goncalves
1551eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "CPU Period Runtime ");
1561eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " Noise ");
1571eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " %% CPU Aval ");
1581eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " Max Noise Max Single ");
1591f428356SDaniel Bristot de Oliveira trace_seq_printf(s, " HW NMI");
1601f428356SDaniel Bristot de Oliveira
1611f428356SDaniel Bristot de Oliveira if (params->mode == MODE_HWNOISE)
1621f428356SDaniel Bristot de Oliveira goto eol;
1631f428356SDaniel Bristot de Oliveira
1641f428356SDaniel Bristot de Oliveira trace_seq_printf(s, " IRQ Softirq Thread");
1651f428356SDaniel Bristot de Oliveira
1661f428356SDaniel Bristot de Oliveira eol:
16759237b0cSLuis Claudio R. Goncalves if (params->pretty_output)
1681eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\033[0;0;0m");
1691eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\n");
1701eceb2fcSDaniel Bristot de Oliveira }
1711eceb2fcSDaniel Bristot de Oliveira
1721eceb2fcSDaniel Bristot de Oliveira /*
1731eceb2fcSDaniel Bristot de Oliveira * clear_terminal - clears the output terminal
1741eceb2fcSDaniel Bristot de Oliveira */
clear_terminal(struct trace_seq * seq)1751eceb2fcSDaniel Bristot de Oliveira static void clear_terminal(struct trace_seq *seq)
1761eceb2fcSDaniel Bristot de Oliveira {
1771eceb2fcSDaniel Bristot de Oliveira if (!config_debug)
1781eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(seq, "\033c");
1791eceb2fcSDaniel Bristot de Oliveira }
1801eceb2fcSDaniel Bristot de Oliveira
1811eceb2fcSDaniel Bristot de Oliveira /*
1821eceb2fcSDaniel Bristot de Oliveira * osnoise_top_print - prints the output of a given CPU
1831eceb2fcSDaniel Bristot de Oliveira */
osnoise_top_print(struct osnoise_tool * tool,int cpu)1841eceb2fcSDaniel Bristot de Oliveira static void osnoise_top_print(struct osnoise_tool *tool, int cpu)
1851eceb2fcSDaniel Bristot de Oliveira {
186025b2179STomas Glozar struct osnoise_params *params = tool->params;
1871eceb2fcSDaniel Bristot de Oliveira struct trace_seq *s = tool->trace.seq;
1881eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_cpu *cpu_data;
1891eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_data *data;
1901eceb2fcSDaniel Bristot de Oliveira int percentage;
1911eceb2fcSDaniel Bristot de Oliveira int decimal;
1921eceb2fcSDaniel Bristot de Oliveira
1931eceb2fcSDaniel Bristot de Oliveira data = tool->data;
1941eceb2fcSDaniel Bristot de Oliveira cpu_data = &data->cpu_data[cpu];
1951eceb2fcSDaniel Bristot de Oliveira
1961eceb2fcSDaniel Bristot de Oliveira if (!cpu_data->sum_runtime)
1971eceb2fcSDaniel Bristot de Oliveira return;
1981eceb2fcSDaniel Bristot de Oliveira
1991eceb2fcSDaniel Bristot de Oliveira percentage = ((cpu_data->sum_runtime - cpu_data->sum_noise) * 10000000)
2001eceb2fcSDaniel Bristot de Oliveira / cpu_data->sum_runtime;
2011eceb2fcSDaniel Bristot de Oliveira decimal = percentage % 100000;
2021eceb2fcSDaniel Bristot de Oliveira percentage = percentage / 100000;
2031eceb2fcSDaniel Bristot de Oliveira
2041eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%3d #%-6d %12llu ", cpu, cpu_data->sum_cycles, cpu_data->sum_runtime);
2051eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->sum_noise);
2061eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " %3d.%05d", percentage, decimal);
2071eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu %12llu", cpu_data->max_noise, cpu_data->max_sample);
2081eceb2fcSDaniel Bristot de Oliveira
2091eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->hw_count);
2101eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->nmi_count);
2111f428356SDaniel Bristot de Oliveira
2121f428356SDaniel Bristot de Oliveira if (params->mode == MODE_HWNOISE) {
2131f428356SDaniel Bristot de Oliveira trace_seq_printf(s, "\n");
2141f428356SDaniel Bristot de Oliveira return;
2151f428356SDaniel Bristot de Oliveira }
2161f428356SDaniel Bristot de Oliveira
2171eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->irq_count);
2181eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->softirq_count);
2191eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu\n", cpu_data->thread_count);
2201eceb2fcSDaniel Bristot de Oliveira }
2211eceb2fcSDaniel Bristot de Oliveira
2221eceb2fcSDaniel Bristot de Oliveira /*
2231eceb2fcSDaniel Bristot de Oliveira * osnoise_print_stats - print data for all cpus
2241eceb2fcSDaniel Bristot de Oliveira */
2251eceb2fcSDaniel Bristot de Oliveira static void
osnoise_print_stats(struct osnoise_params * params,struct osnoise_tool * top)226025b2179STomas Glozar osnoise_print_stats(struct osnoise_params *params, struct osnoise_tool *top)
2271eceb2fcSDaniel Bristot de Oliveira {
2281eceb2fcSDaniel Bristot de Oliveira struct trace_instance *trace = &top->trace;
2291eceb2fcSDaniel Bristot de Oliveira static int nr_cpus = -1;
2301eceb2fcSDaniel Bristot de Oliveira int i;
2311eceb2fcSDaniel Bristot de Oliveira
2321eceb2fcSDaniel Bristot de Oliveira if (nr_cpus == -1)
2331eceb2fcSDaniel Bristot de Oliveira nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
2341eceb2fcSDaniel Bristot de Oliveira
2351eceb2fcSDaniel Bristot de Oliveira if (!params->quiet)
2361eceb2fcSDaniel Bristot de Oliveira clear_terminal(trace->seq);
2371eceb2fcSDaniel Bristot de Oliveira
2381eceb2fcSDaniel Bristot de Oliveira osnoise_top_header(top);
2391eceb2fcSDaniel Bristot de Oliveira
2401eceb2fcSDaniel Bristot de Oliveira for (i = 0; i < nr_cpus; i++) {
241894c29c7SDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
2421eceb2fcSDaniel Bristot de Oliveira continue;
2431eceb2fcSDaniel Bristot de Oliveira osnoise_top_print(top, i);
2441eceb2fcSDaniel Bristot de Oliveira }
2451eceb2fcSDaniel Bristot de Oliveira
2461eceb2fcSDaniel Bristot de Oliveira trace_seq_do_printf(trace->seq);
2471eceb2fcSDaniel Bristot de Oliveira trace_seq_reset(trace->seq);
248cf186201STomas Glozar osnoise_report_missed_events(top);
2491eceb2fcSDaniel Bristot de Oliveira }
2501eceb2fcSDaniel Bristot de Oliveira
2511eceb2fcSDaniel Bristot de Oliveira /*
2521eceb2fcSDaniel Bristot de Oliveira * osnoise_top_usage - prints osnoise top usage message
2531eceb2fcSDaniel Bristot de Oliveira */
osnoise_top_usage(struct osnoise_params * params,char * usage)254025b2179STomas Glozar static void osnoise_top_usage(struct osnoise_params *params, char *usage)
2551eceb2fcSDaniel Bristot de Oliveira {
2561eceb2fcSDaniel Bristot de Oliveira int i;
2571eceb2fcSDaniel Bristot de Oliveira
2581eceb2fcSDaniel Bristot de Oliveira static const char * const msg[] = {
2591f428356SDaniel Bristot de Oliveira " [-h] [-q] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\",
260842fc5b8SJohn Kacur " [-T us] [-t[file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\",
261cdbf7196SDaniel Bristot de Oliveira " [-c cpu-list] [-H cpu-list] [-P priority] [-C[=cgroup_name]] [--warm-up s]",
2621eceb2fcSDaniel Bristot de Oliveira "",
2631eceb2fcSDaniel Bristot de Oliveira " -h/--help: print this menu",
2642b622eddSDaniel Bristot de Oliveira " -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit",
2651eceb2fcSDaniel Bristot de Oliveira " -p/--period us: osnoise period in us",
2661eceb2fcSDaniel Bristot de Oliveira " -r/--runtime us: osnoise runtime in us",
2671eceb2fcSDaniel Bristot de Oliveira " -s/--stop us: stop trace if a single sample is higher than the argument in us",
2681eceb2fcSDaniel Bristot de Oliveira " -S/--stop-total us: stop trace if the total sample is higher than the argument in us",
269d635316aSDaniel Bristot de Oliveira " -T/--threshold us: the minimum delta to be considered a noise",
2701eceb2fcSDaniel Bristot de Oliveira " -c/--cpus cpu-list: list of cpus to run osnoise threads",
271272ced25SDaniel Bristot de Oliveira " -H/--house-keeping cpus: run rtla control threads only on the given cpus",
272a957cbc0SDaniel Bristot de Oliveira " -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited",
2731eceb2fcSDaniel Bristot de Oliveira " -d/--duration time[s|m|h|d]: duration of the session",
2741eceb2fcSDaniel Bristot de Oliveira " -D/--debug: print debug info",
275842fc5b8SJohn Kacur " -t/--trace[file]: save the stopped trace to [file|osnoise_trace.txt]",
27651d64c3aSDaniel Bristot de Oliveira " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed",
27744f3a37dSDaniel Bristot de Oliveira " --filter <filter>: enable a trace event filter to the previous -e event",
2781a754893SDaniel Bristot de Oliveira " --trigger <trigger>: enable a trace event trigger to the previous -e event",
2791eceb2fcSDaniel Bristot de Oliveira " -q/--quiet print only a summary at the end",
2801eceb2fcSDaniel Bristot de Oliveira " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters",
2811eceb2fcSDaniel Bristot de Oliveira " o:prio - use SCHED_OTHER with prio",
2821eceb2fcSDaniel Bristot de Oliveira " r:prio - use SCHED_RR with prio",
2831eceb2fcSDaniel Bristot de Oliveira " f:prio - use SCHED_FIFO with prio",
2841eceb2fcSDaniel Bristot de Oliveira " d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period",
2851eceb2fcSDaniel Bristot de Oliveira " in nanoseconds",
286cdbf7196SDaniel Bristot de Oliveira " --warm-up s: let the workload run for s seconds before collecting data",
287e9a4062eSDaniel Bristot de Oliveira " --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
2881eceb2fcSDaniel Bristot de Oliveira NULL,
2891eceb2fcSDaniel Bristot de Oliveira };
2901eceb2fcSDaniel Bristot de Oliveira
2911eceb2fcSDaniel Bristot de Oliveira if (usage)
2921eceb2fcSDaniel Bristot de Oliveira fprintf(stderr, "%s\n", usage);
2931eceb2fcSDaniel Bristot de Oliveira
2941f428356SDaniel Bristot de Oliveira if (params->mode == MODE_OSNOISE) {
2951f428356SDaniel Bristot de Oliveira fprintf(stderr,
2961f428356SDaniel Bristot de Oliveira "rtla osnoise top: a per-cpu summary of the OS noise (version %s)\n",
2971eceb2fcSDaniel Bristot de Oliveira VERSION);
2981eceb2fcSDaniel Bristot de Oliveira
2991f428356SDaniel Bristot de Oliveira fprintf(stderr, " usage: rtla osnoise [top]");
3001f428356SDaniel Bristot de Oliveira }
3011f428356SDaniel Bristot de Oliveira
3021f428356SDaniel Bristot de Oliveira if (params->mode == MODE_HWNOISE) {
3031f428356SDaniel Bristot de Oliveira fprintf(stderr,
3041f428356SDaniel Bristot de Oliveira "rtla hwnoise: a summary of hardware-related noise (version %s)\n",
3051f428356SDaniel Bristot de Oliveira VERSION);
3061f428356SDaniel Bristot de Oliveira
3071f428356SDaniel Bristot de Oliveira fprintf(stderr, " usage: rtla hwnoise");
3081f428356SDaniel Bristot de Oliveira }
3091f428356SDaniel Bristot de Oliveira
3101eceb2fcSDaniel Bristot de Oliveira for (i = 0; msg[i]; i++)
3111eceb2fcSDaniel Bristot de Oliveira fprintf(stderr, "%s\n", msg[i]);
312b5f31936SJohn Kacur
313b5f31936SJohn Kacur if (usage)
314b5f31936SJohn Kacur exit(EXIT_FAILURE);
315b5f31936SJohn Kacur
316b5f31936SJohn Kacur exit(EXIT_SUCCESS);
3171eceb2fcSDaniel Bristot de Oliveira }
3181eceb2fcSDaniel Bristot de Oliveira
3191eceb2fcSDaniel Bristot de Oliveira /*
3201eceb2fcSDaniel Bristot de Oliveira * osnoise_top_parse_args - allocs, parse and fill the cmd line parameters
3211eceb2fcSDaniel Bristot de Oliveira */
osnoise_top_parse_args(int argc,char ** argv)322025b2179STomas Glozar struct osnoise_params *osnoise_top_parse_args(int argc, char **argv)
3231eceb2fcSDaniel Bristot de Oliveira {
324025b2179STomas Glozar struct osnoise_params *params;
32551d64c3aSDaniel Bristot de Oliveira struct trace_events *tevent;
3261eceb2fcSDaniel Bristot de Oliveira int retval;
3271eceb2fcSDaniel Bristot de Oliveira int c;
3281eceb2fcSDaniel Bristot de Oliveira
3291eceb2fcSDaniel Bristot de Oliveira params = calloc(1, sizeof(*params));
3301eceb2fcSDaniel Bristot de Oliveira if (!params)
3311eceb2fcSDaniel Bristot de Oliveira exit(1);
3321eceb2fcSDaniel Bristot de Oliveira
3337bc4d308SDaniel Bristot de Oliveira if (strcmp(argv[0], "hwnoise") == 0) {
3341f428356SDaniel Bristot de Oliveira params->mode = MODE_HWNOISE;
3357bc4d308SDaniel Bristot de Oliveira /*
3367bc4d308SDaniel Bristot de Oliveira * Reduce CPU usage for 75% to avoid killing the system.
3377bc4d308SDaniel Bristot de Oliveira */
3387bc4d308SDaniel Bristot de Oliveira params->runtime = 750000;
3397bc4d308SDaniel Bristot de Oliveira params->period = 1000000;
3407bc4d308SDaniel Bristot de Oliveira }
3411f428356SDaniel Bristot de Oliveira
3421eceb2fcSDaniel Bristot de Oliveira while (1) {
3431eceb2fcSDaniel Bristot de Oliveira static struct option long_options[] = {
3442b622eddSDaniel Bristot de Oliveira {"auto", required_argument, 0, 'a'},
3451eceb2fcSDaniel Bristot de Oliveira {"cpus", required_argument, 0, 'c'},
346a957cbc0SDaniel Bristot de Oliveira {"cgroup", optional_argument, 0, 'C'},
3471eceb2fcSDaniel Bristot de Oliveira {"debug", no_argument, 0, 'D'},
3481eceb2fcSDaniel Bristot de Oliveira {"duration", required_argument, 0, 'd'},
34951d64c3aSDaniel Bristot de Oliveira {"event", required_argument, 0, 'e'},
350272ced25SDaniel Bristot de Oliveira {"house-keeping", required_argument, 0, 'H'},
3511eceb2fcSDaniel Bristot de Oliveira {"help", no_argument, 0, 'h'},
3521eceb2fcSDaniel Bristot de Oliveira {"period", required_argument, 0, 'p'},
3531eceb2fcSDaniel Bristot de Oliveira {"priority", required_argument, 0, 'P'},
3541eceb2fcSDaniel Bristot de Oliveira {"quiet", no_argument, 0, 'q'},
3551eceb2fcSDaniel Bristot de Oliveira {"runtime", required_argument, 0, 'r'},
3561eceb2fcSDaniel Bristot de Oliveira {"stop", required_argument, 0, 's'},
3571eceb2fcSDaniel Bristot de Oliveira {"stop-total", required_argument, 0, 'S'},
358d635316aSDaniel Bristot de Oliveira {"threshold", required_argument, 0, 'T'},
3591eceb2fcSDaniel Bristot de Oliveira {"trace", optional_argument, 0, 't'},
3601a754893SDaniel Bristot de Oliveira {"trigger", required_argument, 0, '0'},
36144f3a37dSDaniel Bristot de Oliveira {"filter", required_argument, 0, '1'},
362cdbf7196SDaniel Bristot de Oliveira {"warm-up", required_argument, 0, '2'},
363e9a4062eSDaniel Bristot de Oliveira {"trace-buffer-size", required_argument, 0, '3'},
3641eceb2fcSDaniel Bristot de Oliveira {0, 0, 0, 0}
3651eceb2fcSDaniel Bristot de Oliveira };
3661eceb2fcSDaniel Bristot de Oliveira
3671eceb2fcSDaniel Bristot de Oliveira /* getopt_long stores the option index here. */
3681eceb2fcSDaniel Bristot de Oliveira int option_index = 0;
3691eceb2fcSDaniel Bristot de Oliveira
370e9a4062eSDaniel Bristot de Oliveira c = getopt_long(argc, argv, "a:c:C::d:De:hH:p:P:qr:s:S:t::T:0:1:2:3:",
3711eceb2fcSDaniel Bristot de Oliveira long_options, &option_index);
3721eceb2fcSDaniel Bristot de Oliveira
3731eceb2fcSDaniel Bristot de Oliveira /* Detect the end of the options. */
3741eceb2fcSDaniel Bristot de Oliveira if (c == -1)
3751eceb2fcSDaniel Bristot de Oliveira break;
3761eceb2fcSDaniel Bristot de Oliveira
3771eceb2fcSDaniel Bristot de Oliveira switch (c) {
3782b622eddSDaniel Bristot de Oliveira case 'a':
3792b622eddSDaniel Bristot de Oliveira /* set sample stop to auto_thresh */
3802b622eddSDaniel Bristot de Oliveira params->stop_us = get_llong_from_str(optarg);
3812b622eddSDaniel Bristot de Oliveira
3822b622eddSDaniel Bristot de Oliveira /* set sample threshold to 1 */
3832b622eddSDaniel Bristot de Oliveira params->threshold = 1;
3842b622eddSDaniel Bristot de Oliveira
3852b622eddSDaniel Bristot de Oliveira /* set trace */
3862b622eddSDaniel Bristot de Oliveira params->trace_output = "osnoise_trace.txt";
3872b622eddSDaniel Bristot de Oliveira
3882b622eddSDaniel Bristot de Oliveira break;
3891eceb2fcSDaniel Bristot de Oliveira case 'c':
390894c29c7SDaniel Bristot de Oliveira retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
3911eceb2fcSDaniel Bristot de Oliveira if (retval)
3921f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "\nInvalid -c cpu list\n");
3931eceb2fcSDaniel Bristot de Oliveira params->cpus = optarg;
3941eceb2fcSDaniel Bristot de Oliveira break;
395a957cbc0SDaniel Bristot de Oliveira case 'C':
396a957cbc0SDaniel Bristot de Oliveira params->cgroup = 1;
397a957cbc0SDaniel Bristot de Oliveira if (!optarg) {
398a957cbc0SDaniel Bristot de Oliveira /* will inherit this cgroup */
399a957cbc0SDaniel Bristot de Oliveira params->cgroup_name = NULL;
400a957cbc0SDaniel Bristot de Oliveira } else if (*optarg == '=') {
401a957cbc0SDaniel Bristot de Oliveira /* skip the = */
402a957cbc0SDaniel Bristot de Oliveira params->cgroup_name = ++optarg;
403a957cbc0SDaniel Bristot de Oliveira }
404a957cbc0SDaniel Bristot de Oliveira break;
4051eceb2fcSDaniel Bristot de Oliveira case 'D':
4061eceb2fcSDaniel Bristot de Oliveira config_debug = 1;
4071eceb2fcSDaniel Bristot de Oliveira break;
4081eceb2fcSDaniel Bristot de Oliveira case 'd':
4091eceb2fcSDaniel Bristot de Oliveira params->duration = parse_seconds_duration(optarg);
4101eceb2fcSDaniel Bristot de Oliveira if (!params->duration)
4113d7b8ea7SEder Zulian osnoise_top_usage(params, "Invalid -d duration\n");
4121eceb2fcSDaniel Bristot de Oliveira break;
41351d64c3aSDaniel Bristot de Oliveira case 'e':
41451d64c3aSDaniel Bristot de Oliveira tevent = trace_event_alloc(optarg);
41551d64c3aSDaniel Bristot de Oliveira if (!tevent) {
41651d64c3aSDaniel Bristot de Oliveira err_msg("Error alloc trace event");
41751d64c3aSDaniel Bristot de Oliveira exit(EXIT_FAILURE);
41851d64c3aSDaniel Bristot de Oliveira }
41951d64c3aSDaniel Bristot de Oliveira
42051d64c3aSDaniel Bristot de Oliveira if (params->events)
42151d64c3aSDaniel Bristot de Oliveira tevent->next = params->events;
42251d64c3aSDaniel Bristot de Oliveira params->events = tevent;
42351d64c3aSDaniel Bristot de Oliveira
42451d64c3aSDaniel Bristot de Oliveira break;
4251eceb2fcSDaniel Bristot de Oliveira case 'h':
4261eceb2fcSDaniel Bristot de Oliveira case '?':
4271f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, NULL);
4281eceb2fcSDaniel Bristot de Oliveira break;
429272ced25SDaniel Bristot de Oliveira case 'H':
430272ced25SDaniel Bristot de Oliveira params->hk_cpus = 1;
431272ced25SDaniel Bristot de Oliveira retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
432272ced25SDaniel Bristot de Oliveira if (retval) {
433272ced25SDaniel Bristot de Oliveira err_msg("Error parsing house keeping CPUs\n");
434272ced25SDaniel Bristot de Oliveira exit(EXIT_FAILURE);
435272ced25SDaniel Bristot de Oliveira }
436272ced25SDaniel Bristot de Oliveira break;
4371eceb2fcSDaniel Bristot de Oliveira case 'p':
4381eceb2fcSDaniel Bristot de Oliveira params->period = get_llong_from_str(optarg);
4391eceb2fcSDaniel Bristot de Oliveira if (params->period > 10000000)
4401f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "Period longer than 10 s\n");
4411eceb2fcSDaniel Bristot de Oliveira break;
4421eceb2fcSDaniel Bristot de Oliveira case 'P':
4431eceb2fcSDaniel Bristot de Oliveira retval = parse_prio(optarg, ¶ms->sched_param);
4441eceb2fcSDaniel Bristot de Oliveira if (retval == -1)
4451f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "Invalid -P priority");
4461eceb2fcSDaniel Bristot de Oliveira params->set_sched = 1;
4471eceb2fcSDaniel Bristot de Oliveira break;
4481eceb2fcSDaniel Bristot de Oliveira case 'q':
4491eceb2fcSDaniel Bristot de Oliveira params->quiet = 1;
4501eceb2fcSDaniel Bristot de Oliveira break;
4511eceb2fcSDaniel Bristot de Oliveira case 'r':
4521eceb2fcSDaniel Bristot de Oliveira params->runtime = get_llong_from_str(optarg);
4531eceb2fcSDaniel Bristot de Oliveira if (params->runtime < 100)
4541f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "Runtime shorter than 100 us\n");
4551eceb2fcSDaniel Bristot de Oliveira break;
4561eceb2fcSDaniel Bristot de Oliveira case 's':
4571eceb2fcSDaniel Bristot de Oliveira params->stop_us = get_llong_from_str(optarg);
4581eceb2fcSDaniel Bristot de Oliveira break;
4591eceb2fcSDaniel Bristot de Oliveira case 'S':
4601eceb2fcSDaniel Bristot de Oliveira params->stop_total_us = get_llong_from_str(optarg);
4611eceb2fcSDaniel Bristot de Oliveira break;
4621eceb2fcSDaniel Bristot de Oliveira case 't':
463842fc5b8SJohn Kacur if (optarg) {
464842fc5b8SJohn Kacur if (optarg[0] == '=')
4651eceb2fcSDaniel Bristot de Oliveira params->trace_output = &optarg[1];
4661eceb2fcSDaniel Bristot de Oliveira else
467842fc5b8SJohn Kacur params->trace_output = &optarg[0];
468842fc5b8SJohn Kacur } else if (optind < argc && argv[optind][0] != '-')
469842fc5b8SJohn Kacur params->trace_output = argv[optind];
470842fc5b8SJohn Kacur else
4711eceb2fcSDaniel Bristot de Oliveira params->trace_output = "osnoise_trace.txt";
4721eceb2fcSDaniel Bristot de Oliveira break;
473d635316aSDaniel Bristot de Oliveira case 'T':
474d635316aSDaniel Bristot de Oliveira params->threshold = get_llong_from_str(optarg);
475d635316aSDaniel Bristot de Oliveira break;
4761a754893SDaniel Bristot de Oliveira case '0': /* trigger */
4771a754893SDaniel Bristot de Oliveira if (params->events) {
4781a754893SDaniel Bristot de Oliveira retval = trace_event_add_trigger(params->events, optarg);
4791a754893SDaniel Bristot de Oliveira if (retval) {
4801a754893SDaniel Bristot de Oliveira err_msg("Error adding trigger %s\n", optarg);
4811a754893SDaniel Bristot de Oliveira exit(EXIT_FAILURE);
4821a754893SDaniel Bristot de Oliveira }
4831a754893SDaniel Bristot de Oliveira } else {
4841f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "--trigger requires a previous -e\n");
4851a754893SDaniel Bristot de Oliveira }
4861a754893SDaniel Bristot de Oliveira break;
48744f3a37dSDaniel Bristot de Oliveira case '1': /* filter */
48844f3a37dSDaniel Bristot de Oliveira if (params->events) {
48944f3a37dSDaniel Bristot de Oliveira retval = trace_event_add_filter(params->events, optarg);
49044f3a37dSDaniel Bristot de Oliveira if (retval) {
49144f3a37dSDaniel Bristot de Oliveira err_msg("Error adding filter %s\n", optarg);
49244f3a37dSDaniel Bristot de Oliveira exit(EXIT_FAILURE);
49344f3a37dSDaniel Bristot de Oliveira }
49444f3a37dSDaniel Bristot de Oliveira } else {
4951f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "--filter requires a previous -e\n");
49644f3a37dSDaniel Bristot de Oliveira }
49744f3a37dSDaniel Bristot de Oliveira break;
498cdbf7196SDaniel Bristot de Oliveira case '2':
499cdbf7196SDaniel Bristot de Oliveira params->warmup = get_llong_from_str(optarg);
500cdbf7196SDaniel Bristot de Oliveira break;
501e9a4062eSDaniel Bristot de Oliveira case '3':
502e9a4062eSDaniel Bristot de Oliveira params->buffer_size = get_llong_from_str(optarg);
503e9a4062eSDaniel Bristot de Oliveira break;
5041eceb2fcSDaniel Bristot de Oliveira default:
5051f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "Invalid option");
5061eceb2fcSDaniel Bristot de Oliveira }
5071eceb2fcSDaniel Bristot de Oliveira }
5081eceb2fcSDaniel Bristot de Oliveira
5091eceb2fcSDaniel Bristot de Oliveira if (geteuid()) {
5101eceb2fcSDaniel Bristot de Oliveira err_msg("osnoise needs root permission\n");
5111eceb2fcSDaniel Bristot de Oliveira exit(EXIT_FAILURE);
5121eceb2fcSDaniel Bristot de Oliveira }
5131eceb2fcSDaniel Bristot de Oliveira
5141eceb2fcSDaniel Bristot de Oliveira return params;
5151eceb2fcSDaniel Bristot de Oliveira }
5161eceb2fcSDaniel Bristot de Oliveira
5171eceb2fcSDaniel Bristot de Oliveira /*
5181eceb2fcSDaniel Bristot de Oliveira * osnoise_top_apply_config - apply the top configs to the initialized tool
5191eceb2fcSDaniel Bristot de Oliveira */
5201eceb2fcSDaniel Bristot de Oliveira static int
osnoise_top_apply_config(struct osnoise_tool * tool,struct osnoise_params * params)521025b2179STomas Glozar osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_params *params)
5221eceb2fcSDaniel Bristot de Oliveira {
5231eceb2fcSDaniel Bristot de Oliveira int retval;
5241eceb2fcSDaniel Bristot de Oliveira
52520d6b075STomas Glozar retval = osnoise_apply_config(tool, params);
52620d6b075STomas Glozar if (retval)
5271eceb2fcSDaniel Bristot de Oliveira goto out_err;
528d635316aSDaniel Bristot de Oliveira
5291f428356SDaniel Bristot de Oliveira if (params->mode == MODE_HWNOISE) {
5301f428356SDaniel Bristot de Oliveira retval = osnoise_set_irq_disable(tool->context, 1);
5311f428356SDaniel Bristot de Oliveira if (retval) {
5321f428356SDaniel Bristot de Oliveira err_msg("Failed to set OSNOISE_IRQ_DISABLE option\n");
5331f428356SDaniel Bristot de Oliveira goto out_err;
5341f428356SDaniel Bristot de Oliveira }
5351f428356SDaniel Bristot de Oliveira }
5361f428356SDaniel Bristot de Oliveira
5373a546a67SEder Zulian if (isatty(STDOUT_FILENO) && !params->quiet)
53859237b0cSLuis Claudio R. Goncalves params->pretty_output = 1;
53959237b0cSLuis Claudio R. Goncalves
5401eceb2fcSDaniel Bristot de Oliveira return 0;
5411eceb2fcSDaniel Bristot de Oliveira
5421eceb2fcSDaniel Bristot de Oliveira out_err:
5431eceb2fcSDaniel Bristot de Oliveira return -1;
5441eceb2fcSDaniel Bristot de Oliveira }
5451eceb2fcSDaniel Bristot de Oliveira
5461eceb2fcSDaniel Bristot de Oliveira /*
5471eceb2fcSDaniel Bristot de Oliveira * osnoise_init_top - initialize a osnoise top tool with parameters
5481eceb2fcSDaniel Bristot de Oliveira */
osnoise_init_top(struct osnoise_params * params)549025b2179STomas Glozar struct osnoise_tool *osnoise_init_top(struct osnoise_params *params)
5501eceb2fcSDaniel Bristot de Oliveira {
5511eceb2fcSDaniel Bristot de Oliveira struct osnoise_tool *tool;
5521eceb2fcSDaniel Bristot de Oliveira int nr_cpus;
5531eceb2fcSDaniel Bristot de Oliveira
5541eceb2fcSDaniel Bristot de Oliveira nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
5551eceb2fcSDaniel Bristot de Oliveira
5561eceb2fcSDaniel Bristot de Oliveira tool = osnoise_init_tool("osnoise_top");
5571eceb2fcSDaniel Bristot de Oliveira if (!tool)
5581eceb2fcSDaniel Bristot de Oliveira return NULL;
5591eceb2fcSDaniel Bristot de Oliveira
5601eceb2fcSDaniel Bristot de Oliveira tool->data = osnoise_alloc_top(nr_cpus);
56190574d2aSDan Carpenter if (!tool->data) {
56290574d2aSDan Carpenter osnoise_destroy_tool(tool);
56390574d2aSDan Carpenter return NULL;
56490574d2aSDan Carpenter }
5651eceb2fcSDaniel Bristot de Oliveira
5661eceb2fcSDaniel Bristot de Oliveira tool->params = params;
5671eceb2fcSDaniel Bristot de Oliveira
5681eceb2fcSDaniel Bristot de Oliveira tep_register_event_handler(tool->trace.tep, -1, "ftrace", "osnoise",
5691eceb2fcSDaniel Bristot de Oliveira osnoise_top_handler, NULL);
5701eceb2fcSDaniel Bristot de Oliveira
5711eceb2fcSDaniel Bristot de Oliveira return tool;
5721eceb2fcSDaniel Bristot de Oliveira }
5731eceb2fcSDaniel Bristot de Oliveira
5741eceb2fcSDaniel Bristot de Oliveira static int stop_tracing;
stop_top(int sig)5751eceb2fcSDaniel Bristot de Oliveira static void stop_top(int sig)
5761eceb2fcSDaniel Bristot de Oliveira {
5771eceb2fcSDaniel Bristot de Oliveira stop_tracing = 1;
5781eceb2fcSDaniel Bristot de Oliveira }
5791eceb2fcSDaniel Bristot de Oliveira
5801eceb2fcSDaniel Bristot de Oliveira /*
5811eceb2fcSDaniel Bristot de Oliveira * osnoise_top_set_signals - handles the signal to stop the tool
5821eceb2fcSDaniel Bristot de Oliveira */
osnoise_top_set_signals(struct osnoise_params * params)583025b2179STomas Glozar static void osnoise_top_set_signals(struct osnoise_params *params)
5841eceb2fcSDaniel Bristot de Oliveira {
5851eceb2fcSDaniel Bristot de Oliveira signal(SIGINT, stop_top);
5861eceb2fcSDaniel Bristot de Oliveira if (params->duration) {
5871eceb2fcSDaniel Bristot de Oliveira signal(SIGALRM, stop_top);
5881eceb2fcSDaniel Bristot de Oliveira alarm(params->duration);
5891eceb2fcSDaniel Bristot de Oliveira }
5901eceb2fcSDaniel Bristot de Oliveira }
5911eceb2fcSDaniel Bristot de Oliveira
osnoise_top_main(int argc,char ** argv)5921eceb2fcSDaniel Bristot de Oliveira int osnoise_top_main(int argc, char **argv)
5931eceb2fcSDaniel Bristot de Oliveira {
594025b2179STomas Glozar struct osnoise_params *params;
5954bbf59a9SDaniel Bristot de Oliveira struct osnoise_tool *record = NULL;
5964bbf59a9SDaniel Bristot de Oliveira struct osnoise_tool *tool = NULL;
597*18682166SCosta Shulyupin enum result return_value = ERROR;
5981eceb2fcSDaniel Bristot de Oliveira struct trace_instance *trace;
5991eceb2fcSDaniel Bristot de Oliveira int retval;
6001eceb2fcSDaniel Bristot de Oliveira
6011eceb2fcSDaniel Bristot de Oliveira params = osnoise_top_parse_args(argc, argv);
6021eceb2fcSDaniel Bristot de Oliveira if (!params)
6031eceb2fcSDaniel Bristot de Oliveira exit(1);
6041eceb2fcSDaniel Bristot de Oliveira
6051eceb2fcSDaniel Bristot de Oliveira tool = osnoise_init_top(params);
6061eceb2fcSDaniel Bristot de Oliveira if (!tool) {
6071eceb2fcSDaniel Bristot de Oliveira err_msg("Could not init osnoise top\n");
6081eceb2fcSDaniel Bristot de Oliveira goto out_exit;
6091eceb2fcSDaniel Bristot de Oliveira }
6101eceb2fcSDaniel Bristot de Oliveira
6111eceb2fcSDaniel Bristot de Oliveira retval = osnoise_top_apply_config(tool, params);
6121eceb2fcSDaniel Bristot de Oliveira if (retval) {
6131eceb2fcSDaniel Bristot de Oliveira err_msg("Could not apply config\n");
6142a6b52edSWan Jiabing goto out_free;
6151eceb2fcSDaniel Bristot de Oliveira }
6161eceb2fcSDaniel Bristot de Oliveira
6171eceb2fcSDaniel Bristot de Oliveira trace = &tool->trace;
6181eceb2fcSDaniel Bristot de Oliveira
6191eceb2fcSDaniel Bristot de Oliveira retval = enable_osnoise(trace);
6201eceb2fcSDaniel Bristot de Oliveira if (retval) {
6211eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to enable osnoise tracer\n");
6222a6b52edSWan Jiabing goto out_free;
6231eceb2fcSDaniel Bristot de Oliveira }
6241eceb2fcSDaniel Bristot de Oliveira
6251eceb2fcSDaniel Bristot de Oliveira if (params->set_sched) {
6261eceb2fcSDaniel Bristot de Oliveira retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param);
6271eceb2fcSDaniel Bristot de Oliveira if (retval) {
6281eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to set sched parameters\n");
6292a6b52edSWan Jiabing goto out_free;
6301eceb2fcSDaniel Bristot de Oliveira }
6311eceb2fcSDaniel Bristot de Oliveira }
6321eceb2fcSDaniel Bristot de Oliveira
633a957cbc0SDaniel Bristot de Oliveira if (params->cgroup) {
634a957cbc0SDaniel Bristot de Oliveira retval = set_comm_cgroup("osnoise/", params->cgroup_name);
635a957cbc0SDaniel Bristot de Oliveira if (!retval) {
636a957cbc0SDaniel Bristot de Oliveira err_msg("Failed to move threads to cgroup\n");
637a957cbc0SDaniel Bristot de Oliveira goto out_free;
638a957cbc0SDaniel Bristot de Oliveira }
639a957cbc0SDaniel Bristot de Oliveira }
640a957cbc0SDaniel Bristot de Oliveira
6411eceb2fcSDaniel Bristot de Oliveira if (params->trace_output) {
6421eceb2fcSDaniel Bristot de Oliveira record = osnoise_init_trace_tool("osnoise");
6431eceb2fcSDaniel Bristot de Oliveira if (!record) {
6441eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to enable the trace instance\n");
6452a6b52edSWan Jiabing goto out_free;
6461eceb2fcSDaniel Bristot de Oliveira }
64751d64c3aSDaniel Bristot de Oliveira
64851d64c3aSDaniel Bristot de Oliveira if (params->events) {
64951d64c3aSDaniel Bristot de Oliveira retval = trace_events_enable(&record->trace, params->events);
65051d64c3aSDaniel Bristot de Oliveira if (retval)
65151d64c3aSDaniel Bristot de Oliveira goto out_top;
65251d64c3aSDaniel Bristot de Oliveira }
653e9a4062eSDaniel Bristot de Oliveira
654e9a4062eSDaniel Bristot de Oliveira if (params->buffer_size > 0) {
655e9a4062eSDaniel Bristot de Oliveira retval = trace_set_buffer_size(&record->trace, params->buffer_size);
656e9a4062eSDaniel Bristot de Oliveira if (retval)
657e9a4062eSDaniel Bristot de Oliveira goto out_top;
658e9a4062eSDaniel Bristot de Oliveira }
6591eceb2fcSDaniel Bristot de Oliveira }
6601eceb2fcSDaniel Bristot de Oliveira
66157cf76ecSDaniel Bristot de Oliveira /*
66257cf76ecSDaniel Bristot de Oliveira * Start the tracer here, after having set all instances.
66357cf76ecSDaniel Bristot de Oliveira *
66457cf76ecSDaniel Bristot de Oliveira * Let the trace instance start first for the case of hitting a stop
66557cf76ecSDaniel Bristot de Oliveira * tracing while enabling other instances. The trace instance is the
66657cf76ecSDaniel Bristot de Oliveira * one with most valuable information.
66757cf76ecSDaniel Bristot de Oliveira */
66857cf76ecSDaniel Bristot de Oliveira if (params->trace_output)
66957cf76ecSDaniel Bristot de Oliveira trace_instance_start(&record->trace);
67057cf76ecSDaniel Bristot de Oliveira trace_instance_start(trace);
67157cf76ecSDaniel Bristot de Oliveira
672cdbf7196SDaniel Bristot de Oliveira if (params->warmup > 0) {
673cdbf7196SDaniel Bristot de Oliveira debug_msg("Warming up for %d seconds\n", params->warmup);
674cdbf7196SDaniel Bristot de Oliveira sleep(params->warmup);
675cdbf7196SDaniel Bristot de Oliveira if (stop_tracing)
676cdbf7196SDaniel Bristot de Oliveira goto out_top;
677cdbf7196SDaniel Bristot de Oliveira
678cdbf7196SDaniel Bristot de Oliveira /*
679cdbf7196SDaniel Bristot de Oliveira * Clean up the buffer. The osnoise workload do not run
680cdbf7196SDaniel Bristot de Oliveira * with tracing off to avoid creating a performance penalty
681cdbf7196SDaniel Bristot de Oliveira * when not needed.
682cdbf7196SDaniel Bristot de Oliveira */
683cdbf7196SDaniel Bristot de Oliveira retval = tracefs_instance_file_write(trace->inst, "trace", "");
684cdbf7196SDaniel Bristot de Oliveira if (retval < 0) {
685cdbf7196SDaniel Bristot de Oliveira debug_msg("Error cleaning up the buffer");
686cdbf7196SDaniel Bristot de Oliveira goto out_top;
687cdbf7196SDaniel Bristot de Oliveira }
688cdbf7196SDaniel Bristot de Oliveira
689cdbf7196SDaniel Bristot de Oliveira }
690cdbf7196SDaniel Bristot de Oliveira
6911eceb2fcSDaniel Bristot de Oliveira tool->start_time = time(NULL);
6921eceb2fcSDaniel Bristot de Oliveira osnoise_top_set_signals(params);
6931eceb2fcSDaniel Bristot de Oliveira
69475016ca3SDaniel Bristot de Oliveira while (!stop_tracing) {
6951eceb2fcSDaniel Bristot de Oliveira sleep(params->sleep_time);
6961eceb2fcSDaniel Bristot de Oliveira
6971eceb2fcSDaniel Bristot de Oliveira retval = tracefs_iterate_raw_events(trace->tep,
6981eceb2fcSDaniel Bristot de Oliveira trace->inst,
6991eceb2fcSDaniel Bristot de Oliveira NULL,
7001eceb2fcSDaniel Bristot de Oliveira 0,
7011eceb2fcSDaniel Bristot de Oliveira collect_registered_events,
7021eceb2fcSDaniel Bristot de Oliveira trace);
7031eceb2fcSDaniel Bristot de Oliveira if (retval < 0) {
7041eceb2fcSDaniel Bristot de Oliveira err_msg("Error iterating on events\n");
7051eceb2fcSDaniel Bristot de Oliveira goto out_top;
7061eceb2fcSDaniel Bristot de Oliveira }
7071eceb2fcSDaniel Bristot de Oliveira
7081eceb2fcSDaniel Bristot de Oliveira if (!params->quiet)
7091eceb2fcSDaniel Bristot de Oliveira osnoise_print_stats(params, tool);
7101eceb2fcSDaniel Bristot de Oliveira
711b91cfd9fSCosta Shulyupin if (osnoise_trace_is_off(tool, record))
7121eceb2fcSDaniel Bristot de Oliveira break;
7131eceb2fcSDaniel Bristot de Oliveira
71475016ca3SDaniel Bristot de Oliveira }
7151eceb2fcSDaniel Bristot de Oliveira
7161eceb2fcSDaniel Bristot de Oliveira osnoise_print_stats(params, tool);
7171eceb2fcSDaniel Bristot de Oliveira
718*18682166SCosta Shulyupin return_value = PASSED;
7191eceb2fcSDaniel Bristot de Oliveira
720b91cfd9fSCosta Shulyupin if (osnoise_trace_is_off(tool, record)) {
7211eceb2fcSDaniel Bristot de Oliveira printf("osnoise hit stop tracing\n");
722c57c58a6STomas Glozar save_trace_to_file(record ? record->trace.inst : NULL,
723c57c58a6STomas Glozar params->trace_output);
724*18682166SCosta Shulyupin return_value = FAILED;
7251eceb2fcSDaniel Bristot de Oliveira }
7261eceb2fcSDaniel Bristot de Oliveira
7271eceb2fcSDaniel Bristot de Oliveira out_top:
72851d64c3aSDaniel Bristot de Oliveira trace_events_destroy(&record->trace, params->events);
72951d64c3aSDaniel Bristot de Oliveira params->events = NULL;
7302a6b52edSWan Jiabing out_free:
7311eceb2fcSDaniel Bristot de Oliveira osnoise_free_top(tool->data);
7321eceb2fcSDaniel Bristot de Oliveira osnoise_destroy_tool(record);
7334bbf59a9SDaniel Bristot de Oliveira osnoise_destroy_tool(tool);
734316f7101SDaniel Bristot de Oliveira free(params);
7351eceb2fcSDaniel Bristot de Oliveira out_exit:
7361eceb2fcSDaniel Bristot de Oliveira exit(return_value);
7371eceb2fcSDaniel Bristot de Oliveira }
738