xref: /linux/tools/tracing/rtla/src/osnoise_top.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
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, &params->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, &params->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, &params->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, &params->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/", &params->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