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> 14272ced25SDaniel Bristot de Oliveira #include <sched.h> 151eceb2fcSDaniel Bristot de Oliveira 161eceb2fcSDaniel Bristot de Oliveira #include "osnoise.h" 171eceb2fcSDaniel Bristot de Oliveira #include "utils.h" 181eceb2fcSDaniel Bristot de Oliveira 191f428356SDaniel Bristot de Oliveira enum osnoise_mode { 201f428356SDaniel Bristot de Oliveira MODE_OSNOISE = 0, 211f428356SDaniel Bristot de Oliveira MODE_HWNOISE 221f428356SDaniel Bristot de Oliveira }; 231f428356SDaniel Bristot de Oliveira 241eceb2fcSDaniel Bristot de Oliveira /* 251eceb2fcSDaniel Bristot de Oliveira * osnoise top parameters 261eceb2fcSDaniel Bristot de Oliveira */ 271eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_params { 281eceb2fcSDaniel Bristot de Oliveira char *cpus; 29894c29c7SDaniel Bristot de Oliveira cpu_set_t monitored_cpus; 301eceb2fcSDaniel Bristot de Oliveira char *trace_output; 31a957cbc0SDaniel Bristot de Oliveira char *cgroup_name; 321eceb2fcSDaniel Bristot de Oliveira unsigned long long runtime; 331eceb2fcSDaniel Bristot de Oliveira unsigned long long period; 34d635316aSDaniel Bristot de Oliveira long long threshold; 351eceb2fcSDaniel Bristot de Oliveira long long stop_us; 361eceb2fcSDaniel Bristot de Oliveira long long stop_total_us; 371eceb2fcSDaniel Bristot de Oliveira int sleep_time; 381eceb2fcSDaniel Bristot de Oliveira int duration; 391eceb2fcSDaniel Bristot de Oliveira int quiet; 401eceb2fcSDaniel Bristot de Oliveira int set_sched; 41a957cbc0SDaniel Bristot de Oliveira int cgroup; 42272ced25SDaniel Bristot de Oliveira int hk_cpus; 43cdbf7196SDaniel Bristot de Oliveira int warmup; 44e9a4062eSDaniel Bristot de Oliveira int buffer_size; 45272ced25SDaniel Bristot de Oliveira cpu_set_t hk_cpu_set; 461eceb2fcSDaniel Bristot de Oliveira struct sched_attr sched_param; 4751d64c3aSDaniel Bristot de Oliveira struct trace_events *events; 481f428356SDaniel Bristot de Oliveira enum osnoise_mode mode; 491eceb2fcSDaniel Bristot de Oliveira }; 501eceb2fcSDaniel Bristot de Oliveira 511eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_cpu { 521eceb2fcSDaniel Bristot de Oliveira unsigned long long sum_runtime; 531eceb2fcSDaniel Bristot de Oliveira unsigned long long sum_noise; 541eceb2fcSDaniel Bristot de Oliveira unsigned long long max_noise; 551eceb2fcSDaniel Bristot de Oliveira unsigned long long max_sample; 561eceb2fcSDaniel Bristot de Oliveira 571eceb2fcSDaniel Bristot de Oliveira unsigned long long hw_count; 581eceb2fcSDaniel Bristot de Oliveira unsigned long long nmi_count; 591eceb2fcSDaniel Bristot de Oliveira unsigned long long irq_count; 601eceb2fcSDaniel Bristot de Oliveira unsigned long long softirq_count; 611eceb2fcSDaniel Bristot de Oliveira unsigned long long thread_count; 621eceb2fcSDaniel Bristot de Oliveira 631eceb2fcSDaniel Bristot de Oliveira int sum_cycles; 641eceb2fcSDaniel Bristot de Oliveira }; 651eceb2fcSDaniel Bristot de Oliveira 661eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_data { 671eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_cpu *cpu_data; 681eceb2fcSDaniel Bristot de Oliveira int nr_cpus; 691eceb2fcSDaniel Bristot de Oliveira }; 701eceb2fcSDaniel Bristot de Oliveira 711eceb2fcSDaniel Bristot de Oliveira /* 721eceb2fcSDaniel Bristot de Oliveira * osnoise_free_top - free runtime data 731eceb2fcSDaniel Bristot de Oliveira */ 741eceb2fcSDaniel Bristot de Oliveira static void 751eceb2fcSDaniel Bristot de Oliveira osnoise_free_top(struct osnoise_top_data *data) 761eceb2fcSDaniel Bristot de Oliveira { 771eceb2fcSDaniel Bristot de Oliveira free(data->cpu_data); 781eceb2fcSDaniel Bristot de Oliveira free(data); 791eceb2fcSDaniel Bristot de Oliveira } 801eceb2fcSDaniel Bristot de Oliveira 811eceb2fcSDaniel Bristot de Oliveira /* 821eceb2fcSDaniel Bristot de Oliveira * osnoise_alloc_histogram - alloc runtime data 831eceb2fcSDaniel Bristot de Oliveira */ 841eceb2fcSDaniel Bristot de Oliveira static struct osnoise_top_data *osnoise_alloc_top(int nr_cpus) 851eceb2fcSDaniel Bristot de Oliveira { 861eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_data *data; 871eceb2fcSDaniel Bristot de Oliveira 881eceb2fcSDaniel Bristot de Oliveira data = calloc(1, sizeof(*data)); 891eceb2fcSDaniel Bristot de Oliveira if (!data) 901eceb2fcSDaniel Bristot de Oliveira return NULL; 911eceb2fcSDaniel Bristot de Oliveira 921eceb2fcSDaniel Bristot de Oliveira data->nr_cpus = nr_cpus; 931eceb2fcSDaniel Bristot de Oliveira 941eceb2fcSDaniel Bristot de Oliveira /* one set of histograms per CPU */ 951eceb2fcSDaniel Bristot de Oliveira data->cpu_data = calloc(1, sizeof(*data->cpu_data) * nr_cpus); 961eceb2fcSDaniel Bristot de Oliveira if (!data->cpu_data) 971eceb2fcSDaniel Bristot de Oliveira goto cleanup; 981eceb2fcSDaniel Bristot de Oliveira 991eceb2fcSDaniel Bristot de Oliveira return data; 1001eceb2fcSDaniel Bristot de Oliveira 1011eceb2fcSDaniel Bristot de Oliveira cleanup: 1021eceb2fcSDaniel Bristot de Oliveira osnoise_free_top(data); 1031eceb2fcSDaniel Bristot de Oliveira return NULL; 1041eceb2fcSDaniel Bristot de Oliveira } 1051eceb2fcSDaniel Bristot de Oliveira 1061eceb2fcSDaniel Bristot de Oliveira /* 1071eceb2fcSDaniel Bristot de Oliveira * osnoise_top_handler - this is the handler for osnoise tracer events 1081eceb2fcSDaniel Bristot de Oliveira */ 1091eceb2fcSDaniel Bristot de Oliveira static int 1101eceb2fcSDaniel Bristot de Oliveira osnoise_top_handler(struct trace_seq *s, struct tep_record *record, 1111eceb2fcSDaniel Bristot de Oliveira struct tep_event *event, void *context) 1121eceb2fcSDaniel Bristot de Oliveira { 1131eceb2fcSDaniel Bristot de Oliveira struct trace_instance *trace = context; 1141eceb2fcSDaniel Bristot de Oliveira struct osnoise_tool *tool; 1151eceb2fcSDaniel Bristot de Oliveira unsigned long long val; 1161eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_cpu *cpu_data; 1171eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_data *data; 1181eceb2fcSDaniel Bristot de Oliveira int cpu = record->cpu; 1191eceb2fcSDaniel Bristot de Oliveira 1201eceb2fcSDaniel Bristot de Oliveira tool = container_of(trace, struct osnoise_tool, trace); 1211eceb2fcSDaniel Bristot de Oliveira 1221eceb2fcSDaniel Bristot de Oliveira data = tool->data; 1231eceb2fcSDaniel Bristot de Oliveira cpu_data = &data->cpu_data[cpu]; 1241eceb2fcSDaniel Bristot de Oliveira 1251eceb2fcSDaniel Bristot de Oliveira cpu_data->sum_cycles++; 1261eceb2fcSDaniel Bristot de Oliveira 1271eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "runtime", record, &val, 1); 1281eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->sum_runtime, &val); 1291eceb2fcSDaniel Bristot de Oliveira 1301eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "noise", record, &val, 1); 1311eceb2fcSDaniel Bristot de Oliveira update_max(&cpu_data->max_noise, &val); 1321eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->sum_noise, &val); 1331eceb2fcSDaniel Bristot de Oliveira 1341eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "max_sample", record, &val, 1); 1351eceb2fcSDaniel Bristot de Oliveira update_max(&cpu_data->max_sample, &val); 1361eceb2fcSDaniel Bristot de Oliveira 1371eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "hw_count", record, &val, 1); 1381eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->hw_count, &val); 1391eceb2fcSDaniel Bristot de Oliveira 1401eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "nmi_count", record, &val, 1); 1411eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->nmi_count, &val); 1421eceb2fcSDaniel Bristot de Oliveira 1431eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "irq_count", record, &val, 1); 1441eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->irq_count, &val); 1451eceb2fcSDaniel Bristot de Oliveira 1461eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "softirq_count", record, &val, 1); 1471eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->softirq_count, &val); 1481eceb2fcSDaniel Bristot de Oliveira 1491eceb2fcSDaniel Bristot de Oliveira tep_get_field_val(s, event, "thread_count", record, &val, 1); 1501eceb2fcSDaniel Bristot de Oliveira update_sum(&cpu_data->thread_count, &val); 1511eceb2fcSDaniel Bristot de Oliveira 1521eceb2fcSDaniel Bristot de Oliveira return 0; 1531eceb2fcSDaniel Bristot de Oliveira } 1541eceb2fcSDaniel Bristot de Oliveira 1551eceb2fcSDaniel Bristot de Oliveira /* 1561eceb2fcSDaniel Bristot de Oliveira * osnoise_top_header - print the header of the tool output 1571eceb2fcSDaniel Bristot de Oliveira */ 1581eceb2fcSDaniel Bristot de Oliveira static void osnoise_top_header(struct osnoise_tool *top) 1591eceb2fcSDaniel Bristot de Oliveira { 1601f428356SDaniel Bristot de Oliveira struct osnoise_top_params *params = top->params; 1611eceb2fcSDaniel Bristot de Oliveira struct trace_seq *s = top->trace.seq; 1621eceb2fcSDaniel Bristot de Oliveira char duration[26]; 1631eceb2fcSDaniel Bristot de Oliveira 1641eceb2fcSDaniel Bristot de Oliveira get_duration(top->start_time, duration, sizeof(duration)); 1651eceb2fcSDaniel Bristot de Oliveira 1661eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\033[2;37;40m"); 1671f428356SDaniel Bristot de Oliveira trace_seq_printf(s, " "); 1681f428356SDaniel Bristot de Oliveira 1691f428356SDaniel Bristot de Oliveira if (params->mode == MODE_OSNOISE) { 1701eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "Operating System Noise"); 1711eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " "); 1721f428356SDaniel Bristot de Oliveira } else if (params->mode == MODE_HWNOISE) { 1731f428356SDaniel Bristot de Oliveira trace_seq_printf(s, "Hardware-related Noise"); 1741f428356SDaniel Bristot de Oliveira } 1751f428356SDaniel Bristot de Oliveira 1761eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " "); 1771eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\033[0;0;0m"); 1781eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\n"); 1791eceb2fcSDaniel Bristot de Oliveira 1801eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "duration: %9s | time is in us\n", duration); 1811eceb2fcSDaniel Bristot de Oliveira 1821eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\033[2;30;47m"); 1831eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "CPU Period Runtime "); 1841eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " Noise "); 1851eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " %% CPU Aval "); 1861eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " Max Noise Max Single "); 1871f428356SDaniel Bristot de Oliveira trace_seq_printf(s, " HW NMI"); 1881f428356SDaniel Bristot de Oliveira 1891f428356SDaniel Bristot de Oliveira if (params->mode == MODE_HWNOISE) 1901f428356SDaniel Bristot de Oliveira goto eol; 1911f428356SDaniel Bristot de Oliveira 1921f428356SDaniel Bristot de Oliveira trace_seq_printf(s, " IRQ Softirq Thread"); 1931f428356SDaniel Bristot de Oliveira 1941f428356SDaniel Bristot de Oliveira eol: 1951eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\033[0;0;0m"); 1961eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "\n"); 1971eceb2fcSDaniel Bristot de Oliveira } 1981eceb2fcSDaniel Bristot de Oliveira 1991eceb2fcSDaniel Bristot de Oliveira /* 2001eceb2fcSDaniel Bristot de Oliveira * clear_terminal - clears the output terminal 2011eceb2fcSDaniel Bristot de Oliveira */ 2021eceb2fcSDaniel Bristot de Oliveira static void clear_terminal(struct trace_seq *seq) 2031eceb2fcSDaniel Bristot de Oliveira { 2041eceb2fcSDaniel Bristot de Oliveira if (!config_debug) 2051eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(seq, "\033c"); 2061eceb2fcSDaniel Bristot de Oliveira } 2071eceb2fcSDaniel Bristot de Oliveira 2081eceb2fcSDaniel Bristot de Oliveira /* 2091eceb2fcSDaniel Bristot de Oliveira * osnoise_top_print - prints the output of a given CPU 2101eceb2fcSDaniel Bristot de Oliveira */ 2111eceb2fcSDaniel Bristot de Oliveira static void osnoise_top_print(struct osnoise_tool *tool, int cpu) 2121eceb2fcSDaniel Bristot de Oliveira { 2131f428356SDaniel Bristot de Oliveira struct osnoise_top_params *params = tool->params; 2141eceb2fcSDaniel Bristot de Oliveira struct trace_seq *s = tool->trace.seq; 2151eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_cpu *cpu_data; 2161eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_data *data; 2171eceb2fcSDaniel Bristot de Oliveira int percentage; 2181eceb2fcSDaniel Bristot de Oliveira int decimal; 2191eceb2fcSDaniel Bristot de Oliveira 2201eceb2fcSDaniel Bristot de Oliveira data = tool->data; 2211eceb2fcSDaniel Bristot de Oliveira cpu_data = &data->cpu_data[cpu]; 2221eceb2fcSDaniel Bristot de Oliveira 2231eceb2fcSDaniel Bristot de Oliveira if (!cpu_data->sum_runtime) 2241eceb2fcSDaniel Bristot de Oliveira return; 2251eceb2fcSDaniel Bristot de Oliveira 2261eceb2fcSDaniel Bristot de Oliveira percentage = ((cpu_data->sum_runtime - cpu_data->sum_noise) * 10000000) 2271eceb2fcSDaniel Bristot de Oliveira / cpu_data->sum_runtime; 2281eceb2fcSDaniel Bristot de Oliveira decimal = percentage % 100000; 2291eceb2fcSDaniel Bristot de Oliveira percentage = percentage / 100000; 2301eceb2fcSDaniel Bristot de Oliveira 2311eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%3d #%-6d %12llu ", cpu, cpu_data->sum_cycles, cpu_data->sum_runtime); 2321eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->sum_noise); 2331eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, " %3d.%05d", percentage, decimal); 2341eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu %12llu", cpu_data->max_noise, cpu_data->max_sample); 2351eceb2fcSDaniel Bristot de Oliveira 2361eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->hw_count); 2371eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->nmi_count); 2381f428356SDaniel Bristot de Oliveira 2391f428356SDaniel Bristot de Oliveira if (params->mode == MODE_HWNOISE) { 2401f428356SDaniel Bristot de Oliveira trace_seq_printf(s, "\n"); 2411f428356SDaniel Bristot de Oliveira return; 2421f428356SDaniel Bristot de Oliveira } 2431f428356SDaniel Bristot de Oliveira 2441eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->irq_count); 2451eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu ", cpu_data->softirq_count); 2461eceb2fcSDaniel Bristot de Oliveira trace_seq_printf(s, "%12llu\n", cpu_data->thread_count); 2471eceb2fcSDaniel Bristot de Oliveira } 2481eceb2fcSDaniel Bristot de Oliveira 2491eceb2fcSDaniel Bristot de Oliveira /* 2501eceb2fcSDaniel Bristot de Oliveira * osnoise_print_stats - print data for all cpus 2511eceb2fcSDaniel Bristot de Oliveira */ 2521eceb2fcSDaniel Bristot de Oliveira static void 2531eceb2fcSDaniel Bristot de Oliveira osnoise_print_stats(struct osnoise_top_params *params, struct osnoise_tool *top) 2541eceb2fcSDaniel Bristot de Oliveira { 2551eceb2fcSDaniel Bristot de Oliveira struct trace_instance *trace = &top->trace; 2561eceb2fcSDaniel Bristot de Oliveira static int nr_cpus = -1; 2571eceb2fcSDaniel Bristot de Oliveira int i; 2581eceb2fcSDaniel Bristot de Oliveira 2591eceb2fcSDaniel Bristot de Oliveira if (nr_cpus == -1) 2601eceb2fcSDaniel Bristot de Oliveira nr_cpus = sysconf(_SC_NPROCESSORS_CONF); 2611eceb2fcSDaniel Bristot de Oliveira 2621eceb2fcSDaniel Bristot de Oliveira if (!params->quiet) 2631eceb2fcSDaniel Bristot de Oliveira clear_terminal(trace->seq); 2641eceb2fcSDaniel Bristot de Oliveira 2651eceb2fcSDaniel Bristot de Oliveira osnoise_top_header(top); 2661eceb2fcSDaniel Bristot de Oliveira 2671eceb2fcSDaniel Bristot de Oliveira for (i = 0; i < nr_cpus; i++) { 268894c29c7SDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus)) 2691eceb2fcSDaniel Bristot de Oliveira continue; 2701eceb2fcSDaniel Bristot de Oliveira osnoise_top_print(top, i); 2711eceb2fcSDaniel Bristot de Oliveira } 2721eceb2fcSDaniel Bristot de Oliveira 2731eceb2fcSDaniel Bristot de Oliveira trace_seq_do_printf(trace->seq); 2741eceb2fcSDaniel Bristot de Oliveira trace_seq_reset(trace->seq); 2751eceb2fcSDaniel Bristot de Oliveira } 2761eceb2fcSDaniel Bristot de Oliveira 2771eceb2fcSDaniel Bristot de Oliveira /* 2781eceb2fcSDaniel Bristot de Oliveira * osnoise_top_usage - prints osnoise top usage message 2791eceb2fcSDaniel Bristot de Oliveira */ 2801f428356SDaniel Bristot de Oliveira static void osnoise_top_usage(struct osnoise_top_params *params, char *usage) 2811eceb2fcSDaniel Bristot de Oliveira { 2821eceb2fcSDaniel Bristot de Oliveira int i; 2831eceb2fcSDaniel Bristot de Oliveira 2841eceb2fcSDaniel Bristot de Oliveira static const char * const msg[] = { 2851f428356SDaniel Bristot de Oliveira " [-h] [-q] [-D] [-d s] [-a us] [-p us] [-r us] [-s us] [-S us] \\", 286842fc5b8SJohn Kacur " [-T us] [-t[file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] \\", 287cdbf7196SDaniel Bristot de Oliveira " [-c cpu-list] [-H cpu-list] [-P priority] [-C[=cgroup_name]] [--warm-up s]", 2881eceb2fcSDaniel Bristot de Oliveira "", 2891eceb2fcSDaniel Bristot de Oliveira " -h/--help: print this menu", 2902b622eddSDaniel Bristot de Oliveira " -a/--auto: set automatic trace mode, stopping the session if argument in us sample is hit", 2911eceb2fcSDaniel Bristot de Oliveira " -p/--period us: osnoise period in us", 2921eceb2fcSDaniel Bristot de Oliveira " -r/--runtime us: osnoise runtime in us", 2931eceb2fcSDaniel Bristot de Oliveira " -s/--stop us: stop trace if a single sample is higher than the argument in us", 2941eceb2fcSDaniel Bristot de Oliveira " -S/--stop-total us: stop trace if the total sample is higher than the argument in us", 295d635316aSDaniel Bristot de Oliveira " -T/--threshold us: the minimum delta to be considered a noise", 2961eceb2fcSDaniel Bristot de Oliveira " -c/--cpus cpu-list: list of cpus to run osnoise threads", 297272ced25SDaniel Bristot de Oliveira " -H/--house-keeping cpus: run rtla control threads only on the given cpus", 298a957cbc0SDaniel Bristot de Oliveira " -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited", 2991eceb2fcSDaniel Bristot de Oliveira " -d/--duration time[s|m|h|d]: duration of the session", 3001eceb2fcSDaniel Bristot de Oliveira " -D/--debug: print debug info", 301842fc5b8SJohn Kacur " -t/--trace[file]: save the stopped trace to [file|osnoise_trace.txt]", 30251d64c3aSDaniel Bristot de Oliveira " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed", 30344f3a37dSDaniel Bristot de Oliveira " --filter <filter>: enable a trace event filter to the previous -e event", 3041a754893SDaniel Bristot de Oliveira " --trigger <trigger>: enable a trace event trigger to the previous -e event", 3051eceb2fcSDaniel Bristot de Oliveira " -q/--quiet print only a summary at the end", 3061eceb2fcSDaniel Bristot de Oliveira " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters", 3071eceb2fcSDaniel Bristot de Oliveira " o:prio - use SCHED_OTHER with prio", 3081eceb2fcSDaniel Bristot de Oliveira " r:prio - use SCHED_RR with prio", 3091eceb2fcSDaniel Bristot de Oliveira " f:prio - use SCHED_FIFO with prio", 3101eceb2fcSDaniel Bristot de Oliveira " d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period", 3111eceb2fcSDaniel Bristot de Oliveira " in nanoseconds", 312cdbf7196SDaniel Bristot de Oliveira " --warm-up s: let the workload run for s seconds before collecting data", 313e9a4062eSDaniel Bristot de Oliveira " --trace-buffer-size kB: set the per-cpu trace buffer size in kB", 3141eceb2fcSDaniel Bristot de Oliveira NULL, 3151eceb2fcSDaniel Bristot de Oliveira }; 3161eceb2fcSDaniel Bristot de Oliveira 3171eceb2fcSDaniel Bristot de Oliveira if (usage) 3181eceb2fcSDaniel Bristot de Oliveira fprintf(stderr, "%s\n", usage); 3191eceb2fcSDaniel Bristot de Oliveira 3201f428356SDaniel Bristot de Oliveira if (params->mode == MODE_OSNOISE) { 3211f428356SDaniel Bristot de Oliveira fprintf(stderr, 3221f428356SDaniel Bristot de Oliveira "rtla osnoise top: a per-cpu summary of the OS noise (version %s)\n", 3231eceb2fcSDaniel Bristot de Oliveira VERSION); 3241eceb2fcSDaniel Bristot de Oliveira 3251f428356SDaniel Bristot de Oliveira fprintf(stderr, " usage: rtla osnoise [top]"); 3261f428356SDaniel Bristot de Oliveira } 3271f428356SDaniel Bristot de Oliveira 3281f428356SDaniel Bristot de Oliveira if (params->mode == MODE_HWNOISE) { 3291f428356SDaniel Bristot de Oliveira fprintf(stderr, 3301f428356SDaniel Bristot de Oliveira "rtla hwnoise: a summary of hardware-related noise (version %s)\n", 3311f428356SDaniel Bristot de Oliveira VERSION); 3321f428356SDaniel Bristot de Oliveira 3331f428356SDaniel Bristot de Oliveira fprintf(stderr, " usage: rtla hwnoise"); 3341f428356SDaniel Bristot de Oliveira } 3351f428356SDaniel Bristot de Oliveira 3361eceb2fcSDaniel Bristot de Oliveira for (i = 0; msg[i]; i++) 3371eceb2fcSDaniel Bristot de Oliveira fprintf(stderr, "%s\n", msg[i]); 338b5f31936SJohn Kacur 339b5f31936SJohn Kacur if (usage) 340b5f31936SJohn Kacur exit(EXIT_FAILURE); 341b5f31936SJohn Kacur 342b5f31936SJohn Kacur exit(EXIT_SUCCESS); 3431eceb2fcSDaniel Bristot de Oliveira } 3441eceb2fcSDaniel Bristot de Oliveira 3451eceb2fcSDaniel Bristot de Oliveira /* 3461eceb2fcSDaniel Bristot de Oliveira * osnoise_top_parse_args - allocs, parse and fill the cmd line parameters 3471eceb2fcSDaniel Bristot de Oliveira */ 3481eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_params *osnoise_top_parse_args(int argc, char **argv) 3491eceb2fcSDaniel Bristot de Oliveira { 3501eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_params *params; 35151d64c3aSDaniel Bristot de Oliveira struct trace_events *tevent; 3521eceb2fcSDaniel Bristot de Oliveira int retval; 3531eceb2fcSDaniel Bristot de Oliveira int c; 3541eceb2fcSDaniel Bristot de Oliveira 3551eceb2fcSDaniel Bristot de Oliveira params = calloc(1, sizeof(*params)); 3561eceb2fcSDaniel Bristot de Oliveira if (!params) 3571eceb2fcSDaniel Bristot de Oliveira exit(1); 3581eceb2fcSDaniel Bristot de Oliveira 3597bc4d308SDaniel Bristot de Oliveira if (strcmp(argv[0], "hwnoise") == 0) { 3601f428356SDaniel Bristot de Oliveira params->mode = MODE_HWNOISE; 3617bc4d308SDaniel Bristot de Oliveira /* 3627bc4d308SDaniel Bristot de Oliveira * Reduce CPU usage for 75% to avoid killing the system. 3637bc4d308SDaniel Bristot de Oliveira */ 3647bc4d308SDaniel Bristot de Oliveira params->runtime = 750000; 3657bc4d308SDaniel Bristot de Oliveira params->period = 1000000; 3667bc4d308SDaniel Bristot de Oliveira } 3671f428356SDaniel Bristot de Oliveira 3681eceb2fcSDaniel Bristot de Oliveira while (1) { 3691eceb2fcSDaniel Bristot de Oliveira static struct option long_options[] = { 3702b622eddSDaniel Bristot de Oliveira {"auto", required_argument, 0, 'a'}, 3711eceb2fcSDaniel Bristot de Oliveira {"cpus", required_argument, 0, 'c'}, 372a957cbc0SDaniel Bristot de Oliveira {"cgroup", optional_argument, 0, 'C'}, 3731eceb2fcSDaniel Bristot de Oliveira {"debug", no_argument, 0, 'D'}, 3741eceb2fcSDaniel Bristot de Oliveira {"duration", required_argument, 0, 'd'}, 37551d64c3aSDaniel Bristot de Oliveira {"event", required_argument, 0, 'e'}, 376272ced25SDaniel Bristot de Oliveira {"house-keeping", required_argument, 0, 'H'}, 3771eceb2fcSDaniel Bristot de Oliveira {"help", no_argument, 0, 'h'}, 3781eceb2fcSDaniel Bristot de Oliveira {"period", required_argument, 0, 'p'}, 3791eceb2fcSDaniel Bristot de Oliveira {"priority", required_argument, 0, 'P'}, 3801eceb2fcSDaniel Bristot de Oliveira {"quiet", no_argument, 0, 'q'}, 3811eceb2fcSDaniel Bristot de Oliveira {"runtime", required_argument, 0, 'r'}, 3821eceb2fcSDaniel Bristot de Oliveira {"stop", required_argument, 0, 's'}, 3831eceb2fcSDaniel Bristot de Oliveira {"stop-total", required_argument, 0, 'S'}, 384d635316aSDaniel Bristot de Oliveira {"threshold", required_argument, 0, 'T'}, 3851eceb2fcSDaniel Bristot de Oliveira {"trace", optional_argument, 0, 't'}, 3861a754893SDaniel Bristot de Oliveira {"trigger", required_argument, 0, '0'}, 38744f3a37dSDaniel Bristot de Oliveira {"filter", required_argument, 0, '1'}, 388cdbf7196SDaniel Bristot de Oliveira {"warm-up", required_argument, 0, '2'}, 389e9a4062eSDaniel Bristot de Oliveira {"trace-buffer-size", required_argument, 0, '3'}, 3901eceb2fcSDaniel Bristot de Oliveira {0, 0, 0, 0} 3911eceb2fcSDaniel Bristot de Oliveira }; 3921eceb2fcSDaniel Bristot de Oliveira 3931eceb2fcSDaniel Bristot de Oliveira /* getopt_long stores the option index here. */ 3941eceb2fcSDaniel Bristot de Oliveira int option_index = 0; 3951eceb2fcSDaniel Bristot de Oliveira 396e9a4062eSDaniel 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:", 3971eceb2fcSDaniel Bristot de Oliveira long_options, &option_index); 3981eceb2fcSDaniel Bristot de Oliveira 3991eceb2fcSDaniel Bristot de Oliveira /* Detect the end of the options. */ 4001eceb2fcSDaniel Bristot de Oliveira if (c == -1) 4011eceb2fcSDaniel Bristot de Oliveira break; 4021eceb2fcSDaniel Bristot de Oliveira 4031eceb2fcSDaniel Bristot de Oliveira switch (c) { 4042b622eddSDaniel Bristot de Oliveira case 'a': 4052b622eddSDaniel Bristot de Oliveira /* set sample stop to auto_thresh */ 4062b622eddSDaniel Bristot de Oliveira params->stop_us = get_llong_from_str(optarg); 4072b622eddSDaniel Bristot de Oliveira 4082b622eddSDaniel Bristot de Oliveira /* set sample threshold to 1 */ 4092b622eddSDaniel Bristot de Oliveira params->threshold = 1; 4102b622eddSDaniel Bristot de Oliveira 4112b622eddSDaniel Bristot de Oliveira /* set trace */ 4122b622eddSDaniel Bristot de Oliveira params->trace_output = "osnoise_trace.txt"; 4132b622eddSDaniel Bristot de Oliveira 4142b622eddSDaniel Bristot de Oliveira break; 4151eceb2fcSDaniel Bristot de Oliveira case 'c': 416894c29c7SDaniel Bristot de Oliveira retval = parse_cpu_set(optarg, ¶ms->monitored_cpus); 4171eceb2fcSDaniel Bristot de Oliveira if (retval) 4181f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "\nInvalid -c cpu list\n"); 4191eceb2fcSDaniel Bristot de Oliveira params->cpus = optarg; 4201eceb2fcSDaniel Bristot de Oliveira break; 421a957cbc0SDaniel Bristot de Oliveira case 'C': 422a957cbc0SDaniel Bristot de Oliveira params->cgroup = 1; 423a957cbc0SDaniel Bristot de Oliveira if (!optarg) { 424a957cbc0SDaniel Bristot de Oliveira /* will inherit this cgroup */ 425a957cbc0SDaniel Bristot de Oliveira params->cgroup_name = NULL; 426a957cbc0SDaniel Bristot de Oliveira } else if (*optarg == '=') { 427a957cbc0SDaniel Bristot de Oliveira /* skip the = */ 428a957cbc0SDaniel Bristot de Oliveira params->cgroup_name = ++optarg; 429a957cbc0SDaniel Bristot de Oliveira } 430a957cbc0SDaniel Bristot de Oliveira break; 4311eceb2fcSDaniel Bristot de Oliveira case 'D': 4321eceb2fcSDaniel Bristot de Oliveira config_debug = 1; 4331eceb2fcSDaniel Bristot de Oliveira break; 4341eceb2fcSDaniel Bristot de Oliveira case 'd': 4351eceb2fcSDaniel Bristot de Oliveira params->duration = parse_seconds_duration(optarg); 4361eceb2fcSDaniel Bristot de Oliveira if (!params->duration) 4371f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "Invalid -D duration\n"); 4381eceb2fcSDaniel Bristot de Oliveira break; 43951d64c3aSDaniel Bristot de Oliveira case 'e': 44051d64c3aSDaniel Bristot de Oliveira tevent = trace_event_alloc(optarg); 44151d64c3aSDaniel Bristot de Oliveira if (!tevent) { 44251d64c3aSDaniel Bristot de Oliveira err_msg("Error alloc trace event"); 44351d64c3aSDaniel Bristot de Oliveira exit(EXIT_FAILURE); 44451d64c3aSDaniel Bristot de Oliveira } 44551d64c3aSDaniel Bristot de Oliveira 44651d64c3aSDaniel Bristot de Oliveira if (params->events) 44751d64c3aSDaniel Bristot de Oliveira tevent->next = params->events; 44851d64c3aSDaniel Bristot de Oliveira params->events = tevent; 44951d64c3aSDaniel Bristot de Oliveira 45051d64c3aSDaniel Bristot de Oliveira break; 4511eceb2fcSDaniel Bristot de Oliveira case 'h': 4521eceb2fcSDaniel Bristot de Oliveira case '?': 4531f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, NULL); 4541eceb2fcSDaniel Bristot de Oliveira break; 455272ced25SDaniel Bristot de Oliveira case 'H': 456272ced25SDaniel Bristot de Oliveira params->hk_cpus = 1; 457272ced25SDaniel Bristot de Oliveira retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set); 458272ced25SDaniel Bristot de Oliveira if (retval) { 459272ced25SDaniel Bristot de Oliveira err_msg("Error parsing house keeping CPUs\n"); 460272ced25SDaniel Bristot de Oliveira exit(EXIT_FAILURE); 461272ced25SDaniel Bristot de Oliveira } 462272ced25SDaniel Bristot de Oliveira break; 4631eceb2fcSDaniel Bristot de Oliveira case 'p': 4641eceb2fcSDaniel Bristot de Oliveira params->period = get_llong_from_str(optarg); 4651eceb2fcSDaniel Bristot de Oliveira if (params->period > 10000000) 4661f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "Period longer than 10 s\n"); 4671eceb2fcSDaniel Bristot de Oliveira break; 4681eceb2fcSDaniel Bristot de Oliveira case 'P': 4691eceb2fcSDaniel Bristot de Oliveira retval = parse_prio(optarg, ¶ms->sched_param); 4701eceb2fcSDaniel Bristot de Oliveira if (retval == -1) 4711f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "Invalid -P priority"); 4721eceb2fcSDaniel Bristot de Oliveira params->set_sched = 1; 4731eceb2fcSDaniel Bristot de Oliveira break; 4741eceb2fcSDaniel Bristot de Oliveira case 'q': 4751eceb2fcSDaniel Bristot de Oliveira params->quiet = 1; 4761eceb2fcSDaniel Bristot de Oliveira break; 4771eceb2fcSDaniel Bristot de Oliveira case 'r': 4781eceb2fcSDaniel Bristot de Oliveira params->runtime = get_llong_from_str(optarg); 4791eceb2fcSDaniel Bristot de Oliveira if (params->runtime < 100) 4801f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "Runtime shorter than 100 us\n"); 4811eceb2fcSDaniel Bristot de Oliveira break; 4821eceb2fcSDaniel Bristot de Oliveira case 's': 4831eceb2fcSDaniel Bristot de Oliveira params->stop_us = get_llong_from_str(optarg); 4841eceb2fcSDaniel Bristot de Oliveira break; 4851eceb2fcSDaniel Bristot de Oliveira case 'S': 4861eceb2fcSDaniel Bristot de Oliveira params->stop_total_us = get_llong_from_str(optarg); 4871eceb2fcSDaniel Bristot de Oliveira break; 4881eceb2fcSDaniel Bristot de Oliveira case 't': 489842fc5b8SJohn Kacur if (optarg) { 490842fc5b8SJohn Kacur if (optarg[0] == '=') 4911eceb2fcSDaniel Bristot de Oliveira params->trace_output = &optarg[1]; 4921eceb2fcSDaniel Bristot de Oliveira else 493842fc5b8SJohn Kacur params->trace_output = &optarg[0]; 494842fc5b8SJohn Kacur } else if (optind < argc && argv[optind][0] != '-') 495842fc5b8SJohn Kacur params->trace_output = argv[optind]; 496842fc5b8SJohn Kacur else 4971eceb2fcSDaniel Bristot de Oliveira params->trace_output = "osnoise_trace.txt"; 4981eceb2fcSDaniel Bristot de Oliveira break; 499d635316aSDaniel Bristot de Oliveira case 'T': 500d635316aSDaniel Bristot de Oliveira params->threshold = get_llong_from_str(optarg); 501d635316aSDaniel Bristot de Oliveira break; 5021a754893SDaniel Bristot de Oliveira case '0': /* trigger */ 5031a754893SDaniel Bristot de Oliveira if (params->events) { 5041a754893SDaniel Bristot de Oliveira retval = trace_event_add_trigger(params->events, optarg); 5051a754893SDaniel Bristot de Oliveira if (retval) { 5061a754893SDaniel Bristot de Oliveira err_msg("Error adding trigger %s\n", optarg); 5071a754893SDaniel Bristot de Oliveira exit(EXIT_FAILURE); 5081a754893SDaniel Bristot de Oliveira } 5091a754893SDaniel Bristot de Oliveira } else { 5101f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "--trigger requires a previous -e\n"); 5111a754893SDaniel Bristot de Oliveira } 5121a754893SDaniel Bristot de Oliveira break; 51344f3a37dSDaniel Bristot de Oliveira case '1': /* filter */ 51444f3a37dSDaniel Bristot de Oliveira if (params->events) { 51544f3a37dSDaniel Bristot de Oliveira retval = trace_event_add_filter(params->events, optarg); 51644f3a37dSDaniel Bristot de Oliveira if (retval) { 51744f3a37dSDaniel Bristot de Oliveira err_msg("Error adding filter %s\n", optarg); 51844f3a37dSDaniel Bristot de Oliveira exit(EXIT_FAILURE); 51944f3a37dSDaniel Bristot de Oliveira } 52044f3a37dSDaniel Bristot de Oliveira } else { 5211f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "--filter requires a previous -e\n"); 52244f3a37dSDaniel Bristot de Oliveira } 52344f3a37dSDaniel Bristot de Oliveira break; 524cdbf7196SDaniel Bristot de Oliveira case '2': 525cdbf7196SDaniel Bristot de Oliveira params->warmup = get_llong_from_str(optarg); 526cdbf7196SDaniel Bristot de Oliveira break; 527e9a4062eSDaniel Bristot de Oliveira case '3': 528e9a4062eSDaniel Bristot de Oliveira params->buffer_size = get_llong_from_str(optarg); 529e9a4062eSDaniel Bristot de Oliveira break; 5301eceb2fcSDaniel Bristot de Oliveira default: 5311f428356SDaniel Bristot de Oliveira osnoise_top_usage(params, "Invalid option"); 5321eceb2fcSDaniel Bristot de Oliveira } 5331eceb2fcSDaniel Bristot de Oliveira } 5341eceb2fcSDaniel Bristot de Oliveira 5351eceb2fcSDaniel Bristot de Oliveira if (geteuid()) { 5361eceb2fcSDaniel Bristot de Oliveira err_msg("osnoise needs root permission\n"); 5371eceb2fcSDaniel Bristot de Oliveira exit(EXIT_FAILURE); 5381eceb2fcSDaniel Bristot de Oliveira } 5391eceb2fcSDaniel Bristot de Oliveira 5401eceb2fcSDaniel Bristot de Oliveira return params; 5411eceb2fcSDaniel Bristot de Oliveira } 5421eceb2fcSDaniel Bristot de Oliveira 5431eceb2fcSDaniel Bristot de Oliveira /* 5441eceb2fcSDaniel Bristot de Oliveira * osnoise_top_apply_config - apply the top configs to the initialized tool 5451eceb2fcSDaniel Bristot de Oliveira */ 5461eceb2fcSDaniel Bristot de Oliveira static int 5471eceb2fcSDaniel Bristot de Oliveira osnoise_top_apply_config(struct osnoise_tool *tool, struct osnoise_top_params *params) 5481eceb2fcSDaniel Bristot de Oliveira { 5491eceb2fcSDaniel Bristot de Oliveira int retval; 5501eceb2fcSDaniel Bristot de Oliveira 5511eceb2fcSDaniel Bristot de Oliveira if (!params->sleep_time) 5521eceb2fcSDaniel Bristot de Oliveira params->sleep_time = 1; 5531eceb2fcSDaniel Bristot de Oliveira 5541eceb2fcSDaniel Bristot de Oliveira if (params->cpus) { 5551eceb2fcSDaniel Bristot de Oliveira retval = osnoise_set_cpus(tool->context, params->cpus); 5561eceb2fcSDaniel Bristot de Oliveira if (retval) { 5571eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to apply CPUs config\n"); 5581eceb2fcSDaniel Bristot de Oliveira goto out_err; 5591eceb2fcSDaniel Bristot de Oliveira } 5601eceb2fcSDaniel Bristot de Oliveira } 5611eceb2fcSDaniel Bristot de Oliveira 5621eceb2fcSDaniel Bristot de Oliveira if (params->runtime || params->period) { 5631eceb2fcSDaniel Bristot de Oliveira retval = osnoise_set_runtime_period(tool->context, 5641eceb2fcSDaniel Bristot de Oliveira params->runtime, 5651eceb2fcSDaniel Bristot de Oliveira params->period); 5661eceb2fcSDaniel Bristot de Oliveira if (retval) { 5671eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to set runtime and/or period\n"); 5681eceb2fcSDaniel Bristot de Oliveira goto out_err; 5691eceb2fcSDaniel Bristot de Oliveira } 5701eceb2fcSDaniel Bristot de Oliveira } 5711eceb2fcSDaniel Bristot de Oliveira 5721eceb2fcSDaniel Bristot de Oliveira if (params->stop_us) { 5731eceb2fcSDaniel Bristot de Oliveira retval = osnoise_set_stop_us(tool->context, params->stop_us); 5741eceb2fcSDaniel Bristot de Oliveira if (retval) { 5751eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to set stop us\n"); 5761eceb2fcSDaniel Bristot de Oliveira goto out_err; 5771eceb2fcSDaniel Bristot de Oliveira } 5781eceb2fcSDaniel Bristot de Oliveira } 5791eceb2fcSDaniel Bristot de Oliveira 5801eceb2fcSDaniel Bristot de Oliveira if (params->stop_total_us) { 5811eceb2fcSDaniel Bristot de Oliveira retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); 5821eceb2fcSDaniel Bristot de Oliveira if (retval) { 5831eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to set stop total us\n"); 5841eceb2fcSDaniel Bristot de Oliveira goto out_err; 5851eceb2fcSDaniel Bristot de Oliveira } 5861eceb2fcSDaniel Bristot de Oliveira } 5871eceb2fcSDaniel Bristot de Oliveira 588d635316aSDaniel Bristot de Oliveira if (params->threshold) { 589d635316aSDaniel Bristot de Oliveira retval = osnoise_set_tracing_thresh(tool->context, params->threshold); 590d635316aSDaniel Bristot de Oliveira if (retval) { 591d635316aSDaniel Bristot de Oliveira err_msg("Failed to set tracing_thresh\n"); 592d635316aSDaniel Bristot de Oliveira goto out_err; 593d635316aSDaniel Bristot de Oliveira } 594d635316aSDaniel Bristot de Oliveira } 595d635316aSDaniel Bristot de Oliveira 5961f428356SDaniel Bristot de Oliveira if (params->mode == MODE_HWNOISE) { 5971f428356SDaniel Bristot de Oliveira retval = osnoise_set_irq_disable(tool->context, 1); 5981f428356SDaniel Bristot de Oliveira if (retval) { 5991f428356SDaniel Bristot de Oliveira err_msg("Failed to set OSNOISE_IRQ_DISABLE option\n"); 6001f428356SDaniel Bristot de Oliveira goto out_err; 6011f428356SDaniel Bristot de Oliveira } 6021f428356SDaniel Bristot de Oliveira } 6031f428356SDaniel Bristot de Oliveira 604272ced25SDaniel Bristot de Oliveira if (params->hk_cpus) { 605272ced25SDaniel Bristot de Oliveira retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), 606272ced25SDaniel Bristot de Oliveira ¶ms->hk_cpu_set); 607272ced25SDaniel Bristot de Oliveira if (retval == -1) { 608272ced25SDaniel Bristot de Oliveira err_msg("Failed to set rtla to the house keeping CPUs\n"); 609272ced25SDaniel Bristot de Oliveira goto out_err; 610272ced25SDaniel Bristot de Oliveira } 611c58a3f8cSDaniel Bristot de Oliveira } else if (params->cpus) { 612c58a3f8cSDaniel Bristot de Oliveira /* 613c58a3f8cSDaniel Bristot de Oliveira * Even if the user do not set a house-keeping CPU, try to 614c58a3f8cSDaniel Bristot de Oliveira * move rtla to a CPU set different to the one where the user 615c58a3f8cSDaniel Bristot de Oliveira * set the workload to run. 616c58a3f8cSDaniel Bristot de Oliveira * 617c58a3f8cSDaniel Bristot de Oliveira * No need to check results as this is an automatic attempt. 618c58a3f8cSDaniel Bristot de Oliveira */ 619c58a3f8cSDaniel Bristot de Oliveira auto_house_keeping(¶ms->monitored_cpus); 620272ced25SDaniel Bristot de Oliveira } 621272ced25SDaniel Bristot de Oliveira 6221eceb2fcSDaniel Bristot de Oliveira return 0; 6231eceb2fcSDaniel Bristot de Oliveira 6241eceb2fcSDaniel Bristot de Oliveira out_err: 6251eceb2fcSDaniel Bristot de Oliveira return -1; 6261eceb2fcSDaniel Bristot de Oliveira } 6271eceb2fcSDaniel Bristot de Oliveira 6281eceb2fcSDaniel Bristot de Oliveira /* 6291eceb2fcSDaniel Bristot de Oliveira * osnoise_init_top - initialize a osnoise top tool with parameters 6301eceb2fcSDaniel Bristot de Oliveira */ 6311eceb2fcSDaniel Bristot de Oliveira struct osnoise_tool *osnoise_init_top(struct osnoise_top_params *params) 6321eceb2fcSDaniel Bristot de Oliveira { 6331eceb2fcSDaniel Bristot de Oliveira struct osnoise_tool *tool; 6341eceb2fcSDaniel Bristot de Oliveira int nr_cpus; 6351eceb2fcSDaniel Bristot de Oliveira 6361eceb2fcSDaniel Bristot de Oliveira nr_cpus = sysconf(_SC_NPROCESSORS_CONF); 6371eceb2fcSDaniel Bristot de Oliveira 6381eceb2fcSDaniel Bristot de Oliveira tool = osnoise_init_tool("osnoise_top"); 6391eceb2fcSDaniel Bristot de Oliveira if (!tool) 6401eceb2fcSDaniel Bristot de Oliveira return NULL; 6411eceb2fcSDaniel Bristot de Oliveira 6421eceb2fcSDaniel Bristot de Oliveira tool->data = osnoise_alloc_top(nr_cpus); 6431eceb2fcSDaniel Bristot de Oliveira if (!tool->data) 6441eceb2fcSDaniel Bristot de Oliveira goto out_err; 6451eceb2fcSDaniel Bristot de Oliveira 6461eceb2fcSDaniel Bristot de Oliveira tool->params = params; 6471eceb2fcSDaniel Bristot de Oliveira 6481eceb2fcSDaniel Bristot de Oliveira tep_register_event_handler(tool->trace.tep, -1, "ftrace", "osnoise", 6491eceb2fcSDaniel Bristot de Oliveira osnoise_top_handler, NULL); 6501eceb2fcSDaniel Bristot de Oliveira 6511eceb2fcSDaniel Bristot de Oliveira return tool; 6521eceb2fcSDaniel Bristot de Oliveira 6531eceb2fcSDaniel Bristot de Oliveira out_err: 6541eceb2fcSDaniel Bristot de Oliveira osnoise_free_top(tool->data); 6551eceb2fcSDaniel Bristot de Oliveira osnoise_destroy_tool(tool); 6561eceb2fcSDaniel Bristot de Oliveira return NULL; 6571eceb2fcSDaniel Bristot de Oliveira } 6581eceb2fcSDaniel Bristot de Oliveira 6591eceb2fcSDaniel Bristot de Oliveira static int stop_tracing; 6601eceb2fcSDaniel Bristot de Oliveira static void stop_top(int sig) 6611eceb2fcSDaniel Bristot de Oliveira { 6621eceb2fcSDaniel Bristot de Oliveira stop_tracing = 1; 6631eceb2fcSDaniel Bristot de Oliveira } 6641eceb2fcSDaniel Bristot de Oliveira 6651eceb2fcSDaniel Bristot de Oliveira /* 6661eceb2fcSDaniel Bristot de Oliveira * osnoise_top_set_signals - handles the signal to stop the tool 6671eceb2fcSDaniel Bristot de Oliveira */ 6681eceb2fcSDaniel Bristot de Oliveira static void osnoise_top_set_signals(struct osnoise_top_params *params) 6691eceb2fcSDaniel Bristot de Oliveira { 6701eceb2fcSDaniel Bristot de Oliveira signal(SIGINT, stop_top); 6711eceb2fcSDaniel Bristot de Oliveira if (params->duration) { 6721eceb2fcSDaniel Bristot de Oliveira signal(SIGALRM, stop_top); 6731eceb2fcSDaniel Bristot de Oliveira alarm(params->duration); 6741eceb2fcSDaniel Bristot de Oliveira } 6751eceb2fcSDaniel Bristot de Oliveira } 6761eceb2fcSDaniel Bristot de Oliveira 6771eceb2fcSDaniel Bristot de Oliveira int osnoise_top_main(int argc, char **argv) 6781eceb2fcSDaniel Bristot de Oliveira { 6791eceb2fcSDaniel Bristot de Oliveira struct osnoise_top_params *params; 6804bbf59a9SDaniel Bristot de Oliveira struct osnoise_tool *record = NULL; 6814bbf59a9SDaniel Bristot de Oliveira struct osnoise_tool *tool = NULL; 6821eceb2fcSDaniel Bristot de Oliveira struct trace_instance *trace; 6831eceb2fcSDaniel Bristot de Oliveira int return_value = 1; 6841eceb2fcSDaniel Bristot de Oliveira int retval; 6851eceb2fcSDaniel Bristot de Oliveira 6861eceb2fcSDaniel Bristot de Oliveira params = osnoise_top_parse_args(argc, argv); 6871eceb2fcSDaniel Bristot de Oliveira if (!params) 6881eceb2fcSDaniel Bristot de Oliveira exit(1); 6891eceb2fcSDaniel Bristot de Oliveira 6901eceb2fcSDaniel Bristot de Oliveira tool = osnoise_init_top(params); 6911eceb2fcSDaniel Bristot de Oliveira if (!tool) { 6921eceb2fcSDaniel Bristot de Oliveira err_msg("Could not init osnoise top\n"); 6931eceb2fcSDaniel Bristot de Oliveira goto out_exit; 6941eceb2fcSDaniel Bristot de Oliveira } 6951eceb2fcSDaniel Bristot de Oliveira 6961eceb2fcSDaniel Bristot de Oliveira retval = osnoise_top_apply_config(tool, params); 6971eceb2fcSDaniel Bristot de Oliveira if (retval) { 6981eceb2fcSDaniel Bristot de Oliveira err_msg("Could not apply config\n"); 6992a6b52edSWan Jiabing goto out_free; 7001eceb2fcSDaniel Bristot de Oliveira } 7011eceb2fcSDaniel Bristot de Oliveira 7021eceb2fcSDaniel Bristot de Oliveira trace = &tool->trace; 7031eceb2fcSDaniel Bristot de Oliveira 7041eceb2fcSDaniel Bristot de Oliveira retval = enable_osnoise(trace); 7051eceb2fcSDaniel Bristot de Oliveira if (retval) { 7061eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to enable osnoise tracer\n"); 7072a6b52edSWan Jiabing goto out_free; 7081eceb2fcSDaniel Bristot de Oliveira } 7091eceb2fcSDaniel Bristot de Oliveira 7101eceb2fcSDaniel Bristot de Oliveira if (params->set_sched) { 7111eceb2fcSDaniel Bristot de Oliveira retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param); 7121eceb2fcSDaniel Bristot de Oliveira if (retval) { 7131eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to set sched parameters\n"); 7142a6b52edSWan Jiabing goto out_free; 7151eceb2fcSDaniel Bristot de Oliveira } 7161eceb2fcSDaniel Bristot de Oliveira } 7171eceb2fcSDaniel Bristot de Oliveira 718a957cbc0SDaniel Bristot de Oliveira if (params->cgroup) { 719a957cbc0SDaniel Bristot de Oliveira retval = set_comm_cgroup("osnoise/", params->cgroup_name); 720a957cbc0SDaniel Bristot de Oliveira if (!retval) { 721a957cbc0SDaniel Bristot de Oliveira err_msg("Failed to move threads to cgroup\n"); 722a957cbc0SDaniel Bristot de Oliveira goto out_free; 723a957cbc0SDaniel Bristot de Oliveira } 724a957cbc0SDaniel Bristot de Oliveira } 725a957cbc0SDaniel Bristot de Oliveira 7261eceb2fcSDaniel Bristot de Oliveira if (params->trace_output) { 7271eceb2fcSDaniel Bristot de Oliveira record = osnoise_init_trace_tool("osnoise"); 7281eceb2fcSDaniel Bristot de Oliveira if (!record) { 7291eceb2fcSDaniel Bristot de Oliveira err_msg("Failed to enable the trace instance\n"); 7302a6b52edSWan Jiabing goto out_free; 7311eceb2fcSDaniel Bristot de Oliveira } 73251d64c3aSDaniel Bristot de Oliveira 73351d64c3aSDaniel Bristot de Oliveira if (params->events) { 73451d64c3aSDaniel Bristot de Oliveira retval = trace_events_enable(&record->trace, params->events); 73551d64c3aSDaniel Bristot de Oliveira if (retval) 73651d64c3aSDaniel Bristot de Oliveira goto out_top; 73751d64c3aSDaniel Bristot de Oliveira } 738e9a4062eSDaniel Bristot de Oliveira 739e9a4062eSDaniel Bristot de Oliveira if (params->buffer_size > 0) { 740e9a4062eSDaniel Bristot de Oliveira retval = trace_set_buffer_size(&record->trace, params->buffer_size); 741e9a4062eSDaniel Bristot de Oliveira if (retval) 742e9a4062eSDaniel Bristot de Oliveira goto out_top; 743e9a4062eSDaniel Bristot de Oliveira } 7441eceb2fcSDaniel Bristot de Oliveira } 7451eceb2fcSDaniel Bristot de Oliveira 74657cf76ecSDaniel Bristot de Oliveira /* 74757cf76ecSDaniel Bristot de Oliveira * Start the tracer here, after having set all instances. 74857cf76ecSDaniel Bristot de Oliveira * 74957cf76ecSDaniel Bristot de Oliveira * Let the trace instance start first for the case of hitting a stop 75057cf76ecSDaniel Bristot de Oliveira * tracing while enabling other instances. The trace instance is the 75157cf76ecSDaniel Bristot de Oliveira * one with most valuable information. 75257cf76ecSDaniel Bristot de Oliveira */ 75357cf76ecSDaniel Bristot de Oliveira if (params->trace_output) 75457cf76ecSDaniel Bristot de Oliveira trace_instance_start(&record->trace); 75557cf76ecSDaniel Bristot de Oliveira trace_instance_start(trace); 75657cf76ecSDaniel Bristot de Oliveira 757cdbf7196SDaniel Bristot de Oliveira if (params->warmup > 0) { 758cdbf7196SDaniel Bristot de Oliveira debug_msg("Warming up for %d seconds\n", params->warmup); 759cdbf7196SDaniel Bristot de Oliveira sleep(params->warmup); 760cdbf7196SDaniel Bristot de Oliveira if (stop_tracing) 761cdbf7196SDaniel Bristot de Oliveira goto out_top; 762cdbf7196SDaniel Bristot de Oliveira 763cdbf7196SDaniel Bristot de Oliveira /* 764cdbf7196SDaniel Bristot de Oliveira * Clean up the buffer. The osnoise workload do not run 765cdbf7196SDaniel Bristot de Oliveira * with tracing off to avoid creating a performance penalty 766cdbf7196SDaniel Bristot de Oliveira * when not needed. 767cdbf7196SDaniel Bristot de Oliveira */ 768cdbf7196SDaniel Bristot de Oliveira retval = tracefs_instance_file_write(trace->inst, "trace", ""); 769cdbf7196SDaniel Bristot de Oliveira if (retval < 0) { 770cdbf7196SDaniel Bristot de Oliveira debug_msg("Error cleaning up the buffer"); 771cdbf7196SDaniel Bristot de Oliveira goto out_top; 772cdbf7196SDaniel Bristot de Oliveira } 773cdbf7196SDaniel Bristot de Oliveira 774cdbf7196SDaniel Bristot de Oliveira } 775cdbf7196SDaniel Bristot de Oliveira 7761eceb2fcSDaniel Bristot de Oliveira tool->start_time = time(NULL); 7771eceb2fcSDaniel Bristot de Oliveira osnoise_top_set_signals(params); 7781eceb2fcSDaniel Bristot de Oliveira 77975016ca3SDaniel Bristot de Oliveira while (!stop_tracing) { 7801eceb2fcSDaniel Bristot de Oliveira sleep(params->sleep_time); 7811eceb2fcSDaniel Bristot de Oliveira 7821eceb2fcSDaniel Bristot de Oliveira retval = tracefs_iterate_raw_events(trace->tep, 7831eceb2fcSDaniel Bristot de Oliveira trace->inst, 7841eceb2fcSDaniel Bristot de Oliveira NULL, 7851eceb2fcSDaniel Bristot de Oliveira 0, 7861eceb2fcSDaniel Bristot de Oliveira collect_registered_events, 7871eceb2fcSDaniel Bristot de Oliveira trace); 7881eceb2fcSDaniel Bristot de Oliveira if (retval < 0) { 7891eceb2fcSDaniel Bristot de Oliveira err_msg("Error iterating on events\n"); 7901eceb2fcSDaniel Bristot de Oliveira goto out_top; 7911eceb2fcSDaniel Bristot de Oliveira } 7921eceb2fcSDaniel Bristot de Oliveira 7931eceb2fcSDaniel Bristot de Oliveira if (!params->quiet) 7941eceb2fcSDaniel Bristot de Oliveira osnoise_print_stats(params, tool); 7951eceb2fcSDaniel Bristot de Oliveira 79628d2160cSDaniel Bristot de Oliveira if (trace_is_off(&tool->trace, &record->trace)) 7971eceb2fcSDaniel Bristot de Oliveira break; 7981eceb2fcSDaniel Bristot de Oliveira 79975016ca3SDaniel Bristot de Oliveira } 8001eceb2fcSDaniel Bristot de Oliveira 8011eceb2fcSDaniel Bristot de Oliveira osnoise_print_stats(params, tool); 8021eceb2fcSDaniel Bristot de Oliveira 8031eceb2fcSDaniel Bristot de Oliveira return_value = 0; 8041eceb2fcSDaniel Bristot de Oliveira 80528d2160cSDaniel Bristot de Oliveira if (trace_is_off(&tool->trace, &record->trace)) { 8061eceb2fcSDaniel Bristot de Oliveira printf("osnoise hit stop tracing\n"); 8071eceb2fcSDaniel Bristot de Oliveira if (params->trace_output) { 8081eceb2fcSDaniel Bristot de Oliveira printf(" Saving trace to %s\n", params->trace_output); 8091eceb2fcSDaniel Bristot de Oliveira save_trace_to_file(record->trace.inst, params->trace_output); 8101eceb2fcSDaniel Bristot de Oliveira } 8111eceb2fcSDaniel Bristot de Oliveira } 8121eceb2fcSDaniel Bristot de Oliveira 8131eceb2fcSDaniel Bristot de Oliveira out_top: 81451d64c3aSDaniel Bristot de Oliveira trace_events_destroy(&record->trace, params->events); 81551d64c3aSDaniel Bristot de Oliveira params->events = NULL; 8162a6b52edSWan Jiabing out_free: 8171eceb2fcSDaniel Bristot de Oliveira osnoise_free_top(tool->data); 8181eceb2fcSDaniel Bristot de Oliveira osnoise_destroy_tool(record); 8194bbf59a9SDaniel Bristot de Oliveira osnoise_destroy_tool(tool); 820316f7101SDaniel Bristot de Oliveira free(params); 8211eceb2fcSDaniel Bristot de Oliveira out_exit: 8221eceb2fcSDaniel Bristot de Oliveira exit(return_value); 8231eceb2fcSDaniel Bristot de Oliveira } 824