1*829a6c0bSDaniel Bristot de Oliveira // SPDX-License-Identifier: GPL-2.0 2*829a6c0bSDaniel Bristot de Oliveira /* 3*829a6c0bSDaniel Bristot de Oliveira * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> 4*829a6c0bSDaniel Bristot de Oliveira */ 5*829a6c0bSDaniel Bristot de Oliveira 6*829a6c0bSDaniel Bristot de Oliveira #include <getopt.h> 7*829a6c0bSDaniel Bristot de Oliveira #include <stdlib.h> 8*829a6c0bSDaniel Bristot de Oliveira #include <string.h> 9*829a6c0bSDaniel Bristot de Oliveira #include <signal.h> 10*829a6c0bSDaniel Bristot de Oliveira #include <unistd.h> 11*829a6c0bSDaniel Bristot de Oliveira #include <errno.h> 12*829a6c0bSDaniel Bristot de Oliveira #include <stdio.h> 13*829a6c0bSDaniel Bristot de Oliveira #include <time.h> 14*829a6c0bSDaniel Bristot de Oliveira 15*829a6c0bSDaniel Bristot de Oliveira #include "utils.h" 16*829a6c0bSDaniel Bristot de Oliveira #include "osnoise.h" 17*829a6c0bSDaniel Bristot de Oliveira 18*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_params { 19*829a6c0bSDaniel Bristot de Oliveira char *cpus; 20*829a6c0bSDaniel Bristot de Oliveira char *monitored_cpus; 21*829a6c0bSDaniel Bristot de Oliveira char *trace_output; 22*829a6c0bSDaniel Bristot de Oliveira unsigned long long runtime; 23*829a6c0bSDaniel Bristot de Oliveira unsigned long long period; 24*829a6c0bSDaniel Bristot de Oliveira long long stop_us; 25*829a6c0bSDaniel Bristot de Oliveira long long stop_total_us; 26*829a6c0bSDaniel Bristot de Oliveira int sleep_time; 27*829a6c0bSDaniel Bristot de Oliveira int duration; 28*829a6c0bSDaniel Bristot de Oliveira int set_sched; 29*829a6c0bSDaniel Bristot de Oliveira int output_divisor; 30*829a6c0bSDaniel Bristot de Oliveira struct sched_attr sched_param; 31*829a6c0bSDaniel Bristot de Oliveira 32*829a6c0bSDaniel Bristot de Oliveira char no_header; 33*829a6c0bSDaniel Bristot de Oliveira char no_summary; 34*829a6c0bSDaniel Bristot de Oliveira char no_index; 35*829a6c0bSDaniel Bristot de Oliveira char with_zeros; 36*829a6c0bSDaniel Bristot de Oliveira int bucket_size; 37*829a6c0bSDaniel Bristot de Oliveira int entries; 38*829a6c0bSDaniel Bristot de Oliveira }; 39*829a6c0bSDaniel Bristot de Oliveira 40*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_cpu { 41*829a6c0bSDaniel Bristot de Oliveira int *samples; 42*829a6c0bSDaniel Bristot de Oliveira int count; 43*829a6c0bSDaniel Bristot de Oliveira 44*829a6c0bSDaniel Bristot de Oliveira unsigned long long min_sample; 45*829a6c0bSDaniel Bristot de Oliveira unsigned long long sum_sample; 46*829a6c0bSDaniel Bristot de Oliveira unsigned long long max_sample; 47*829a6c0bSDaniel Bristot de Oliveira 48*829a6c0bSDaniel Bristot de Oliveira }; 49*829a6c0bSDaniel Bristot de Oliveira 50*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_data { 51*829a6c0bSDaniel Bristot de Oliveira struct tracefs_hist *trace_hist; 52*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_cpu *hist; 53*829a6c0bSDaniel Bristot de Oliveira int entries; 54*829a6c0bSDaniel Bristot de Oliveira int bucket_size; 55*829a6c0bSDaniel Bristot de Oliveira int nr_cpus; 56*829a6c0bSDaniel Bristot de Oliveira }; 57*829a6c0bSDaniel Bristot de Oliveira 58*829a6c0bSDaniel Bristot de Oliveira /* 59*829a6c0bSDaniel Bristot de Oliveira * osnoise_free_histogram - free runtime data 60*829a6c0bSDaniel Bristot de Oliveira */ 61*829a6c0bSDaniel Bristot de Oliveira static void 62*829a6c0bSDaniel Bristot de Oliveira osnoise_free_histogram(struct osnoise_hist_data *data) 63*829a6c0bSDaniel Bristot de Oliveira { 64*829a6c0bSDaniel Bristot de Oliveira int cpu; 65*829a6c0bSDaniel Bristot de Oliveira 66*829a6c0bSDaniel Bristot de Oliveira /* one histogram for IRQ and one for thread, per CPU */ 67*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) { 68*829a6c0bSDaniel Bristot de Oliveira if (data->hist[cpu].samples) 69*829a6c0bSDaniel Bristot de Oliveira free(data->hist[cpu].samples); 70*829a6c0bSDaniel Bristot de Oliveira } 71*829a6c0bSDaniel Bristot de Oliveira 72*829a6c0bSDaniel Bristot de Oliveira /* one set of histograms per CPU */ 73*829a6c0bSDaniel Bristot de Oliveira if (data->hist) 74*829a6c0bSDaniel Bristot de Oliveira free(data->hist); 75*829a6c0bSDaniel Bristot de Oliveira 76*829a6c0bSDaniel Bristot de Oliveira free(data); 77*829a6c0bSDaniel Bristot de Oliveira } 78*829a6c0bSDaniel Bristot de Oliveira 79*829a6c0bSDaniel Bristot de Oliveira /* 80*829a6c0bSDaniel Bristot de Oliveira * osnoise_alloc_histogram - alloc runtime data 81*829a6c0bSDaniel Bristot de Oliveira */ 82*829a6c0bSDaniel Bristot de Oliveira static struct osnoise_hist_data 83*829a6c0bSDaniel Bristot de Oliveira *osnoise_alloc_histogram(int nr_cpus, int entries, int bucket_size) 84*829a6c0bSDaniel Bristot de Oliveira { 85*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_data *data; 86*829a6c0bSDaniel Bristot de Oliveira int cpu; 87*829a6c0bSDaniel Bristot de Oliveira 88*829a6c0bSDaniel Bristot de Oliveira data = calloc(1, sizeof(*data)); 89*829a6c0bSDaniel Bristot de Oliveira if (!data) 90*829a6c0bSDaniel Bristot de Oliveira return NULL; 91*829a6c0bSDaniel Bristot de Oliveira 92*829a6c0bSDaniel Bristot de Oliveira data->entries = entries; 93*829a6c0bSDaniel Bristot de Oliveira data->bucket_size = bucket_size; 94*829a6c0bSDaniel Bristot de Oliveira data->nr_cpus = nr_cpus; 95*829a6c0bSDaniel Bristot de Oliveira 96*829a6c0bSDaniel Bristot de Oliveira data->hist = calloc(1, sizeof(*data->hist) * nr_cpus); 97*829a6c0bSDaniel Bristot de Oliveira if (!data->hist) 98*829a6c0bSDaniel Bristot de Oliveira goto cleanup; 99*829a6c0bSDaniel Bristot de Oliveira 100*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < nr_cpus; cpu++) { 101*829a6c0bSDaniel Bristot de Oliveira data->hist[cpu].samples = calloc(1, sizeof(*data->hist->samples) * (entries + 1)); 102*829a6c0bSDaniel Bristot de Oliveira if (!data->hist[cpu].samples) 103*829a6c0bSDaniel Bristot de Oliveira goto cleanup; 104*829a6c0bSDaniel Bristot de Oliveira } 105*829a6c0bSDaniel Bristot de Oliveira 106*829a6c0bSDaniel Bristot de Oliveira /* set the min to max */ 107*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < nr_cpus; cpu++) 108*829a6c0bSDaniel Bristot de Oliveira data->hist[cpu].min_sample = ~0; 109*829a6c0bSDaniel Bristot de Oliveira 110*829a6c0bSDaniel Bristot de Oliveira return data; 111*829a6c0bSDaniel Bristot de Oliveira 112*829a6c0bSDaniel Bristot de Oliveira cleanup: 113*829a6c0bSDaniel Bristot de Oliveira osnoise_free_histogram(data); 114*829a6c0bSDaniel Bristot de Oliveira return NULL; 115*829a6c0bSDaniel Bristot de Oliveira } 116*829a6c0bSDaniel Bristot de Oliveira 117*829a6c0bSDaniel Bristot de Oliveira static void osnoise_hist_update_multiple(struct osnoise_tool *tool, int cpu, 118*829a6c0bSDaniel Bristot de Oliveira unsigned long long duration, int count) 119*829a6c0bSDaniel Bristot de Oliveira { 120*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_params *params = tool->params; 121*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_data *data = tool->data; 122*829a6c0bSDaniel Bristot de Oliveira int entries = data->entries; 123*829a6c0bSDaniel Bristot de Oliveira int bucket; 124*829a6c0bSDaniel Bristot de Oliveira int *hist; 125*829a6c0bSDaniel Bristot de Oliveira 126*829a6c0bSDaniel Bristot de Oliveira if (params->output_divisor) 127*829a6c0bSDaniel Bristot de Oliveira duration = duration / params->output_divisor; 128*829a6c0bSDaniel Bristot de Oliveira 129*829a6c0bSDaniel Bristot de Oliveira if (data->bucket_size) 130*829a6c0bSDaniel Bristot de Oliveira bucket = duration / data->bucket_size; 131*829a6c0bSDaniel Bristot de Oliveira 132*829a6c0bSDaniel Bristot de Oliveira hist = data->hist[cpu].samples; 133*829a6c0bSDaniel Bristot de Oliveira data->hist[cpu].count += count; 134*829a6c0bSDaniel Bristot de Oliveira update_min(&data->hist[cpu].min_sample, &duration); 135*829a6c0bSDaniel Bristot de Oliveira update_sum(&data->hist[cpu].sum_sample, &duration); 136*829a6c0bSDaniel Bristot de Oliveira update_max(&data->hist[cpu].max_sample, &duration); 137*829a6c0bSDaniel Bristot de Oliveira 138*829a6c0bSDaniel Bristot de Oliveira if (bucket < entries) 139*829a6c0bSDaniel Bristot de Oliveira hist[bucket] += count; 140*829a6c0bSDaniel Bristot de Oliveira else 141*829a6c0bSDaniel Bristot de Oliveira hist[entries] += count; 142*829a6c0bSDaniel Bristot de Oliveira } 143*829a6c0bSDaniel Bristot de Oliveira 144*829a6c0bSDaniel Bristot de Oliveira /* 145*829a6c0bSDaniel Bristot de Oliveira * osnoise_destroy_trace_hist - disable events used to collect histogram 146*829a6c0bSDaniel Bristot de Oliveira */ 147*829a6c0bSDaniel Bristot de Oliveira static void osnoise_destroy_trace_hist(struct osnoise_tool *tool) 148*829a6c0bSDaniel Bristot de Oliveira { 149*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_data *data = tool->data; 150*829a6c0bSDaniel Bristot de Oliveira 151*829a6c0bSDaniel Bristot de Oliveira tracefs_hist_pause(tool->trace.inst, data->trace_hist); 152*829a6c0bSDaniel Bristot de Oliveira tracefs_hist_destroy(tool->trace.inst, data->trace_hist); 153*829a6c0bSDaniel Bristot de Oliveira } 154*829a6c0bSDaniel Bristot de Oliveira 155*829a6c0bSDaniel Bristot de Oliveira /* 156*829a6c0bSDaniel Bristot de Oliveira * osnoise_init_trace_hist - enable events used to collect histogram 157*829a6c0bSDaniel Bristot de Oliveira */ 158*829a6c0bSDaniel Bristot de Oliveira static int osnoise_init_trace_hist(struct osnoise_tool *tool) 159*829a6c0bSDaniel Bristot de Oliveira { 160*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_params *params = tool->params; 161*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_data *data = tool->data; 162*829a6c0bSDaniel Bristot de Oliveira int bucket_size; 163*829a6c0bSDaniel Bristot de Oliveira char buff[128]; 164*829a6c0bSDaniel Bristot de Oliveira int retval = 0; 165*829a6c0bSDaniel Bristot de Oliveira 166*829a6c0bSDaniel Bristot de Oliveira /* 167*829a6c0bSDaniel Bristot de Oliveira * Set the size of the bucket. 168*829a6c0bSDaniel Bristot de Oliveira */ 169*829a6c0bSDaniel Bristot de Oliveira bucket_size = params->output_divisor * params->bucket_size; 170*829a6c0bSDaniel Bristot de Oliveira snprintf(buff, sizeof(buff), "duration.buckets=%d", bucket_size); 171*829a6c0bSDaniel Bristot de Oliveira 172*829a6c0bSDaniel Bristot de Oliveira data->trace_hist = tracefs_hist_alloc(tool->trace.tep, "osnoise", "sample_threshold", 173*829a6c0bSDaniel Bristot de Oliveira buff, TRACEFS_HIST_KEY_NORMAL); 174*829a6c0bSDaniel Bristot de Oliveira if (!data->trace_hist) 175*829a6c0bSDaniel Bristot de Oliveira return 1; 176*829a6c0bSDaniel Bristot de Oliveira 177*829a6c0bSDaniel Bristot de Oliveira retval = tracefs_hist_add_key(data->trace_hist, "cpu", 0); 178*829a6c0bSDaniel Bristot de Oliveira if (retval) 179*829a6c0bSDaniel Bristot de Oliveira goto out_err; 180*829a6c0bSDaniel Bristot de Oliveira 181*829a6c0bSDaniel Bristot de Oliveira retval = tracefs_hist_start(tool->trace.inst, data->trace_hist); 182*829a6c0bSDaniel Bristot de Oliveira if (retval) 183*829a6c0bSDaniel Bristot de Oliveira goto out_err; 184*829a6c0bSDaniel Bristot de Oliveira 185*829a6c0bSDaniel Bristot de Oliveira return 0; 186*829a6c0bSDaniel Bristot de Oliveira 187*829a6c0bSDaniel Bristot de Oliveira out_err: 188*829a6c0bSDaniel Bristot de Oliveira osnoise_destroy_trace_hist(tool); 189*829a6c0bSDaniel Bristot de Oliveira return 1; 190*829a6c0bSDaniel Bristot de Oliveira } 191*829a6c0bSDaniel Bristot de Oliveira 192*829a6c0bSDaniel Bristot de Oliveira /* 193*829a6c0bSDaniel Bristot de Oliveira * osnoise_read_trace_hist - parse histogram file and file osnoise histogram 194*829a6c0bSDaniel Bristot de Oliveira */ 195*829a6c0bSDaniel Bristot de Oliveira static void osnoise_read_trace_hist(struct osnoise_tool *tool) 196*829a6c0bSDaniel Bristot de Oliveira { 197*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_data *data = tool->data; 198*829a6c0bSDaniel Bristot de Oliveira long long cpu, counter, duration; 199*829a6c0bSDaniel Bristot de Oliveira char *content, *position; 200*829a6c0bSDaniel Bristot de Oliveira 201*829a6c0bSDaniel Bristot de Oliveira tracefs_hist_pause(tool->trace.inst, data->trace_hist); 202*829a6c0bSDaniel Bristot de Oliveira 203*829a6c0bSDaniel Bristot de Oliveira content = tracefs_event_file_read(tool->trace.inst, "osnoise", 204*829a6c0bSDaniel Bristot de Oliveira "sample_threshold", 205*829a6c0bSDaniel Bristot de Oliveira "hist", NULL); 206*829a6c0bSDaniel Bristot de Oliveira if (!content) 207*829a6c0bSDaniel Bristot de Oliveira return; 208*829a6c0bSDaniel Bristot de Oliveira 209*829a6c0bSDaniel Bristot de Oliveira position = content; 210*829a6c0bSDaniel Bristot de Oliveira while (true) { 211*829a6c0bSDaniel Bristot de Oliveira position = strstr(position, "duration: ~"); 212*829a6c0bSDaniel Bristot de Oliveira if (!position) 213*829a6c0bSDaniel Bristot de Oliveira break; 214*829a6c0bSDaniel Bristot de Oliveira position += strlen("duration: ~"); 215*829a6c0bSDaniel Bristot de Oliveira duration = get_llong_from_str(position); 216*829a6c0bSDaniel Bristot de Oliveira if (duration == -1) 217*829a6c0bSDaniel Bristot de Oliveira err_msg("error reading duration from histogram\n"); 218*829a6c0bSDaniel Bristot de Oliveira 219*829a6c0bSDaniel Bristot de Oliveira position = strstr(position, "cpu:"); 220*829a6c0bSDaniel Bristot de Oliveira if (!position) 221*829a6c0bSDaniel Bristot de Oliveira break; 222*829a6c0bSDaniel Bristot de Oliveira position += strlen("cpu: "); 223*829a6c0bSDaniel Bristot de Oliveira cpu = get_llong_from_str(position); 224*829a6c0bSDaniel Bristot de Oliveira if (cpu == -1) 225*829a6c0bSDaniel Bristot de Oliveira err_msg("error reading cpu from histogram\n"); 226*829a6c0bSDaniel Bristot de Oliveira 227*829a6c0bSDaniel Bristot de Oliveira position = strstr(position, "hitcount:"); 228*829a6c0bSDaniel Bristot de Oliveira if (!position) 229*829a6c0bSDaniel Bristot de Oliveira break; 230*829a6c0bSDaniel Bristot de Oliveira position += strlen("hitcount: "); 231*829a6c0bSDaniel Bristot de Oliveira counter = get_llong_from_str(position); 232*829a6c0bSDaniel Bristot de Oliveira if (counter == -1) 233*829a6c0bSDaniel Bristot de Oliveira err_msg("error reading counter from histogram\n"); 234*829a6c0bSDaniel Bristot de Oliveira 235*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_update_multiple(tool, cpu, duration, counter); 236*829a6c0bSDaniel Bristot de Oliveira } 237*829a6c0bSDaniel Bristot de Oliveira free(content); 238*829a6c0bSDaniel Bristot de Oliveira } 239*829a6c0bSDaniel Bristot de Oliveira 240*829a6c0bSDaniel Bristot de Oliveira /* 241*829a6c0bSDaniel Bristot de Oliveira * osnoise_hist_header - print the header of the tracer to the output 242*829a6c0bSDaniel Bristot de Oliveira */ 243*829a6c0bSDaniel Bristot de Oliveira static void osnoise_hist_header(struct osnoise_tool *tool) 244*829a6c0bSDaniel Bristot de Oliveira { 245*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_params *params = tool->params; 246*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_data *data = tool->data; 247*829a6c0bSDaniel Bristot de Oliveira struct trace_seq *s = tool->trace.seq; 248*829a6c0bSDaniel Bristot de Oliveira char duration[26]; 249*829a6c0bSDaniel Bristot de Oliveira int cpu; 250*829a6c0bSDaniel Bristot de Oliveira 251*829a6c0bSDaniel Bristot de Oliveira if (params->no_header) 252*829a6c0bSDaniel Bristot de Oliveira return; 253*829a6c0bSDaniel Bristot de Oliveira 254*829a6c0bSDaniel Bristot de Oliveira get_duration(tool->start_time, duration, sizeof(duration)); 255*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(s, "# RTLA osnoise histogram\n"); 256*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(s, "# Time unit is %s (%s)\n", 257*829a6c0bSDaniel Bristot de Oliveira params->output_divisor == 1 ? "nanoseconds" : "microseconds", 258*829a6c0bSDaniel Bristot de Oliveira params->output_divisor == 1 ? "ns" : "us"); 259*829a6c0bSDaniel Bristot de Oliveira 260*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(s, "# Duration: %s\n", duration); 261*829a6c0bSDaniel Bristot de Oliveira 262*829a6c0bSDaniel Bristot de Oliveira if (!params->no_index) 263*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(s, "Index"); 264*829a6c0bSDaniel Bristot de Oliveira 265*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) { 266*829a6c0bSDaniel Bristot de Oliveira if (params->cpus && !params->monitored_cpus[cpu]) 267*829a6c0bSDaniel Bristot de Oliveira continue; 268*829a6c0bSDaniel Bristot de Oliveira 269*829a6c0bSDaniel Bristot de Oliveira if (!data->hist[cpu].count) 270*829a6c0bSDaniel Bristot de Oliveira continue; 271*829a6c0bSDaniel Bristot de Oliveira 272*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(s, " CPU-%03d", cpu); 273*829a6c0bSDaniel Bristot de Oliveira } 274*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(s, "\n"); 275*829a6c0bSDaniel Bristot de Oliveira 276*829a6c0bSDaniel Bristot de Oliveira trace_seq_do_printf(s); 277*829a6c0bSDaniel Bristot de Oliveira trace_seq_reset(s); 278*829a6c0bSDaniel Bristot de Oliveira } 279*829a6c0bSDaniel Bristot de Oliveira 280*829a6c0bSDaniel Bristot de Oliveira /* 281*829a6c0bSDaniel Bristot de Oliveira * osnoise_print_summary - print the summary of the hist data to the output 282*829a6c0bSDaniel Bristot de Oliveira */ 283*829a6c0bSDaniel Bristot de Oliveira static void 284*829a6c0bSDaniel Bristot de Oliveira osnoise_print_summary(struct osnoise_hist_params *params, 285*829a6c0bSDaniel Bristot de Oliveira struct trace_instance *trace, 286*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_data *data) 287*829a6c0bSDaniel Bristot de Oliveira { 288*829a6c0bSDaniel Bristot de Oliveira int cpu; 289*829a6c0bSDaniel Bristot de Oliveira 290*829a6c0bSDaniel Bristot de Oliveira if (params->no_summary) 291*829a6c0bSDaniel Bristot de Oliveira return; 292*829a6c0bSDaniel Bristot de Oliveira 293*829a6c0bSDaniel Bristot de Oliveira if (!params->no_index) 294*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "count:"); 295*829a6c0bSDaniel Bristot de Oliveira 296*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) { 297*829a6c0bSDaniel Bristot de Oliveira if (params->cpus && !params->monitored_cpus[cpu]) 298*829a6c0bSDaniel Bristot de Oliveira continue; 299*829a6c0bSDaniel Bristot de Oliveira 300*829a6c0bSDaniel Bristot de Oliveira if (!data->hist[cpu].count) 301*829a6c0bSDaniel Bristot de Oliveira continue; 302*829a6c0bSDaniel Bristot de Oliveira 303*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].count); 304*829a6c0bSDaniel Bristot de Oliveira } 305*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n"); 306*829a6c0bSDaniel Bristot de Oliveira 307*829a6c0bSDaniel Bristot de Oliveira if (!params->no_index) 308*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "min: "); 309*829a6c0bSDaniel Bristot de Oliveira 310*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) { 311*829a6c0bSDaniel Bristot de Oliveira if (params->cpus && !params->monitored_cpus[cpu]) 312*829a6c0bSDaniel Bristot de Oliveira continue; 313*829a6c0bSDaniel Bristot de Oliveira 314*829a6c0bSDaniel Bristot de Oliveira if (!data->hist[cpu].count) 315*829a6c0bSDaniel Bristot de Oliveira continue; 316*829a6c0bSDaniel Bristot de Oliveira 317*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9llu ", data->hist[cpu].min_sample); 318*829a6c0bSDaniel Bristot de Oliveira 319*829a6c0bSDaniel Bristot de Oliveira } 320*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n"); 321*829a6c0bSDaniel Bristot de Oliveira 322*829a6c0bSDaniel Bristot de Oliveira if (!params->no_index) 323*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "avg: "); 324*829a6c0bSDaniel Bristot de Oliveira 325*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) { 326*829a6c0bSDaniel Bristot de Oliveira if (params->cpus && !params->monitored_cpus[cpu]) 327*829a6c0bSDaniel Bristot de Oliveira continue; 328*829a6c0bSDaniel Bristot de Oliveira 329*829a6c0bSDaniel Bristot de Oliveira if (!data->hist[cpu].count) 330*829a6c0bSDaniel Bristot de Oliveira continue; 331*829a6c0bSDaniel Bristot de Oliveira 332*829a6c0bSDaniel Bristot de Oliveira if (data->hist[cpu].count) 333*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9llu ", 334*829a6c0bSDaniel Bristot de Oliveira data->hist[cpu].sum_sample / data->hist[cpu].count); 335*829a6c0bSDaniel Bristot de Oliveira else 336*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, " - "); 337*829a6c0bSDaniel Bristot de Oliveira } 338*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n"); 339*829a6c0bSDaniel Bristot de Oliveira 340*829a6c0bSDaniel Bristot de Oliveira if (!params->no_index) 341*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "max: "); 342*829a6c0bSDaniel Bristot de Oliveira 343*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) { 344*829a6c0bSDaniel Bristot de Oliveira if (params->cpus && !params->monitored_cpus[cpu]) 345*829a6c0bSDaniel Bristot de Oliveira continue; 346*829a6c0bSDaniel Bristot de Oliveira 347*829a6c0bSDaniel Bristot de Oliveira if (!data->hist[cpu].count) 348*829a6c0bSDaniel Bristot de Oliveira continue; 349*829a6c0bSDaniel Bristot de Oliveira 350*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9llu ", data->hist[cpu].max_sample); 351*829a6c0bSDaniel Bristot de Oliveira 352*829a6c0bSDaniel Bristot de Oliveira } 353*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n"); 354*829a6c0bSDaniel Bristot de Oliveira trace_seq_do_printf(trace->seq); 355*829a6c0bSDaniel Bristot de Oliveira trace_seq_reset(trace->seq); 356*829a6c0bSDaniel Bristot de Oliveira } 357*829a6c0bSDaniel Bristot de Oliveira 358*829a6c0bSDaniel Bristot de Oliveira /* 359*829a6c0bSDaniel Bristot de Oliveira * osnoise_print_stats - print data for all CPUs 360*829a6c0bSDaniel Bristot de Oliveira */ 361*829a6c0bSDaniel Bristot de Oliveira static void 362*829a6c0bSDaniel Bristot de Oliveira osnoise_print_stats(struct osnoise_hist_params *params, struct osnoise_tool *tool) 363*829a6c0bSDaniel Bristot de Oliveira { 364*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_data *data = tool->data; 365*829a6c0bSDaniel Bristot de Oliveira struct trace_instance *trace = &tool->trace; 366*829a6c0bSDaniel Bristot de Oliveira int bucket, cpu; 367*829a6c0bSDaniel Bristot de Oliveira int total; 368*829a6c0bSDaniel Bristot de Oliveira 369*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_header(tool); 370*829a6c0bSDaniel Bristot de Oliveira 371*829a6c0bSDaniel Bristot de Oliveira for (bucket = 0; bucket < data->entries; bucket++) { 372*829a6c0bSDaniel Bristot de Oliveira total = 0; 373*829a6c0bSDaniel Bristot de Oliveira 374*829a6c0bSDaniel Bristot de Oliveira if (!params->no_index) 375*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%-6d", 376*829a6c0bSDaniel Bristot de Oliveira bucket * data->bucket_size); 377*829a6c0bSDaniel Bristot de Oliveira 378*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) { 379*829a6c0bSDaniel Bristot de Oliveira if (params->cpus && !params->monitored_cpus[cpu]) 380*829a6c0bSDaniel Bristot de Oliveira continue; 381*829a6c0bSDaniel Bristot de Oliveira 382*829a6c0bSDaniel Bristot de Oliveira if (!data->hist[cpu].count) 383*829a6c0bSDaniel Bristot de Oliveira continue; 384*829a6c0bSDaniel Bristot de Oliveira 385*829a6c0bSDaniel Bristot de Oliveira total += data->hist[cpu].samples[bucket]; 386*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9d ", data->hist[cpu].samples[bucket]); 387*829a6c0bSDaniel Bristot de Oliveira } 388*829a6c0bSDaniel Bristot de Oliveira 389*829a6c0bSDaniel Bristot de Oliveira if (total == 0 && !params->with_zeros) { 390*829a6c0bSDaniel Bristot de Oliveira trace_seq_reset(trace->seq); 391*829a6c0bSDaniel Bristot de Oliveira continue; 392*829a6c0bSDaniel Bristot de Oliveira } 393*829a6c0bSDaniel Bristot de Oliveira 394*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n"); 395*829a6c0bSDaniel Bristot de Oliveira trace_seq_do_printf(trace->seq); 396*829a6c0bSDaniel Bristot de Oliveira trace_seq_reset(trace->seq); 397*829a6c0bSDaniel Bristot de Oliveira } 398*829a6c0bSDaniel Bristot de Oliveira 399*829a6c0bSDaniel Bristot de Oliveira if (!params->no_index) 400*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "over: "); 401*829a6c0bSDaniel Bristot de Oliveira 402*829a6c0bSDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) { 403*829a6c0bSDaniel Bristot de Oliveira if (params->cpus && !params->monitored_cpus[cpu]) 404*829a6c0bSDaniel Bristot de Oliveira continue; 405*829a6c0bSDaniel Bristot de Oliveira 406*829a6c0bSDaniel Bristot de Oliveira if (!data->hist[cpu].count) 407*829a6c0bSDaniel Bristot de Oliveira continue; 408*829a6c0bSDaniel Bristot de Oliveira 409*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9d ", 410*829a6c0bSDaniel Bristot de Oliveira data->hist[cpu].samples[data->entries]); 411*829a6c0bSDaniel Bristot de Oliveira } 412*829a6c0bSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n"); 413*829a6c0bSDaniel Bristot de Oliveira trace_seq_do_printf(trace->seq); 414*829a6c0bSDaniel Bristot de Oliveira trace_seq_reset(trace->seq); 415*829a6c0bSDaniel Bristot de Oliveira 416*829a6c0bSDaniel Bristot de Oliveira osnoise_print_summary(params, trace, data); 417*829a6c0bSDaniel Bristot de Oliveira } 418*829a6c0bSDaniel Bristot de Oliveira 419*829a6c0bSDaniel Bristot de Oliveira /* 420*829a6c0bSDaniel Bristot de Oliveira * osnoise_hist_usage - prints osnoise hist usage message 421*829a6c0bSDaniel Bristot de Oliveira */ 422*829a6c0bSDaniel Bristot de Oliveira static void osnoise_hist_usage(char *usage) 423*829a6c0bSDaniel Bristot de Oliveira { 424*829a6c0bSDaniel Bristot de Oliveira int i; 425*829a6c0bSDaniel Bristot de Oliveira 426*829a6c0bSDaniel Bristot de Oliveira static const char * const msg[] = { 427*829a6c0bSDaniel Bristot de Oliveira "", 428*829a6c0bSDaniel Bristot de Oliveira " usage: rtla osnoise hist [-h] [-D] [-d s] [-p us] [-r us] [-s us] [-S us] [-t[=file]] \\", 429*829a6c0bSDaniel Bristot de Oliveira " [-c cpu-list] [-P priority] [-b N] [-e N] [--no-header] [--no-summary] \\", 430*829a6c0bSDaniel Bristot de Oliveira " [--no-index] [--with-zeros]", 431*829a6c0bSDaniel Bristot de Oliveira "", 432*829a6c0bSDaniel Bristot de Oliveira " -h/--help: print this menu", 433*829a6c0bSDaniel Bristot de Oliveira " -p/--period us: osnoise period in us", 434*829a6c0bSDaniel Bristot de Oliveira " -r/--runtime us: osnoise runtime in us", 435*829a6c0bSDaniel Bristot de Oliveira " -s/--stop us: stop trace if a single sample is higher than the argument in us", 436*829a6c0bSDaniel Bristot de Oliveira " -S/--stop-total us: stop trace if the total sample is higher than the argument in us", 437*829a6c0bSDaniel Bristot de Oliveira " -c/--cpus cpu-list: list of cpus to run osnoise threads", 438*829a6c0bSDaniel Bristot de Oliveira " -d/--duration time[s|m|h|d]: duration of the session", 439*829a6c0bSDaniel Bristot de Oliveira " -D/--debug: print debug info", 440*829a6c0bSDaniel Bristot de Oliveira " -t/--trace[=file]: save the stopped trace to [file|osnoise_trace.txt]", 441*829a6c0bSDaniel Bristot de Oliveira " -b/--bucket-size N: set the histogram bucket size (default 1)", 442*829a6c0bSDaniel Bristot de Oliveira " -e/--entries N: set the number of entries of the histogram (default 256)", 443*829a6c0bSDaniel Bristot de Oliveira " --no-header: do not print header", 444*829a6c0bSDaniel Bristot de Oliveira " --no-summary: do not print summary", 445*829a6c0bSDaniel Bristot de Oliveira " --no-index: do not print index", 446*829a6c0bSDaniel Bristot de Oliveira " --with-zeros: print zero only entries", 447*829a6c0bSDaniel Bristot de Oliveira " -P/--priority o:prio|r:prio|f:prio|d:runtime:period: set scheduling parameters", 448*829a6c0bSDaniel Bristot de Oliveira " o:prio - use SCHED_OTHER with prio", 449*829a6c0bSDaniel Bristot de Oliveira " r:prio - use SCHED_RR with prio", 450*829a6c0bSDaniel Bristot de Oliveira " f:prio - use SCHED_FIFO with prio", 451*829a6c0bSDaniel Bristot de Oliveira " d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period", 452*829a6c0bSDaniel Bristot de Oliveira " in nanoseconds", 453*829a6c0bSDaniel Bristot de Oliveira NULL, 454*829a6c0bSDaniel Bristot de Oliveira }; 455*829a6c0bSDaniel Bristot de Oliveira 456*829a6c0bSDaniel Bristot de Oliveira if (usage) 457*829a6c0bSDaniel Bristot de Oliveira fprintf(stderr, "%s\n", usage); 458*829a6c0bSDaniel Bristot de Oliveira 459*829a6c0bSDaniel Bristot de Oliveira fprintf(stderr, "rtla osnoise hist: a per-cpu histogram of the OS noise (version %s)\n", 460*829a6c0bSDaniel Bristot de Oliveira VERSION); 461*829a6c0bSDaniel Bristot de Oliveira 462*829a6c0bSDaniel Bristot de Oliveira for (i = 0; msg[i]; i++) 463*829a6c0bSDaniel Bristot de Oliveira fprintf(stderr, "%s\n", msg[i]); 464*829a6c0bSDaniel Bristot de Oliveira exit(1); 465*829a6c0bSDaniel Bristot de Oliveira } 466*829a6c0bSDaniel Bristot de Oliveira 467*829a6c0bSDaniel Bristot de Oliveira /* 468*829a6c0bSDaniel Bristot de Oliveira * osnoise_hist_parse_args - allocs, parse and fill the cmd line parameters 469*829a6c0bSDaniel Bristot de Oliveira */ 470*829a6c0bSDaniel Bristot de Oliveira static struct osnoise_hist_params 471*829a6c0bSDaniel Bristot de Oliveira *osnoise_hist_parse_args(int argc, char *argv[]) 472*829a6c0bSDaniel Bristot de Oliveira { 473*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_params *params; 474*829a6c0bSDaniel Bristot de Oliveira int retval; 475*829a6c0bSDaniel Bristot de Oliveira int c; 476*829a6c0bSDaniel Bristot de Oliveira 477*829a6c0bSDaniel Bristot de Oliveira params = calloc(1, sizeof(*params)); 478*829a6c0bSDaniel Bristot de Oliveira if (!params) 479*829a6c0bSDaniel Bristot de Oliveira exit(1); 480*829a6c0bSDaniel Bristot de Oliveira 481*829a6c0bSDaniel Bristot de Oliveira /* display data in microseconds */ 482*829a6c0bSDaniel Bristot de Oliveira params->output_divisor = 1000; 483*829a6c0bSDaniel Bristot de Oliveira params->bucket_size = 1; 484*829a6c0bSDaniel Bristot de Oliveira params->entries = 256; 485*829a6c0bSDaniel Bristot de Oliveira 486*829a6c0bSDaniel Bristot de Oliveira while (1) { 487*829a6c0bSDaniel Bristot de Oliveira static struct option long_options[] = { 488*829a6c0bSDaniel Bristot de Oliveira {"bucket-size", required_argument, 0, 'b'}, 489*829a6c0bSDaniel Bristot de Oliveira {"entries", required_argument, 0, 'e'}, 490*829a6c0bSDaniel Bristot de Oliveira {"cpus", required_argument, 0, 'c'}, 491*829a6c0bSDaniel Bristot de Oliveira {"debug", no_argument, 0, 'D'}, 492*829a6c0bSDaniel Bristot de Oliveira {"duration", required_argument, 0, 'd'}, 493*829a6c0bSDaniel Bristot de Oliveira {"help", no_argument, 0, 'h'}, 494*829a6c0bSDaniel Bristot de Oliveira {"period", required_argument, 0, 'p'}, 495*829a6c0bSDaniel Bristot de Oliveira {"priority", required_argument, 0, 'P'}, 496*829a6c0bSDaniel Bristot de Oliveira {"runtime", required_argument, 0, 'r'}, 497*829a6c0bSDaniel Bristot de Oliveira {"stop", required_argument, 0, 's'}, 498*829a6c0bSDaniel Bristot de Oliveira {"stop-total", required_argument, 0, 'S'}, 499*829a6c0bSDaniel Bristot de Oliveira {"trace", optional_argument, 0, 't'}, 500*829a6c0bSDaniel Bristot de Oliveira {"no-header", no_argument, 0, '0'}, 501*829a6c0bSDaniel Bristot de Oliveira {"no-summary", no_argument, 0, '1'}, 502*829a6c0bSDaniel Bristot de Oliveira {"no-index", no_argument, 0, '2'}, 503*829a6c0bSDaniel Bristot de Oliveira {"with-zeros", no_argument, 0, '3'}, 504*829a6c0bSDaniel Bristot de Oliveira {0, 0, 0, 0} 505*829a6c0bSDaniel Bristot de Oliveira }; 506*829a6c0bSDaniel Bristot de Oliveira 507*829a6c0bSDaniel Bristot de Oliveira /* getopt_long stores the option index here. */ 508*829a6c0bSDaniel Bristot de Oliveira int option_index = 0; 509*829a6c0bSDaniel Bristot de Oliveira 510*829a6c0bSDaniel Bristot de Oliveira c = getopt_long(argc, argv, "c:b:d:e:Dhp:P:r:s:S:t::0123", 511*829a6c0bSDaniel Bristot de Oliveira long_options, &option_index); 512*829a6c0bSDaniel Bristot de Oliveira 513*829a6c0bSDaniel Bristot de Oliveira /* detect the end of the options. */ 514*829a6c0bSDaniel Bristot de Oliveira if (c == -1) 515*829a6c0bSDaniel Bristot de Oliveira break; 516*829a6c0bSDaniel Bristot de Oliveira 517*829a6c0bSDaniel Bristot de Oliveira switch (c) { 518*829a6c0bSDaniel Bristot de Oliveira case 'b': 519*829a6c0bSDaniel Bristot de Oliveira params->bucket_size = get_llong_from_str(optarg); 520*829a6c0bSDaniel Bristot de Oliveira if ((params->bucket_size == 0) || (params->bucket_size >= 1000000)) 521*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage("Bucket size needs to be > 0 and <= 1000000\n"); 522*829a6c0bSDaniel Bristot de Oliveira break; 523*829a6c0bSDaniel Bristot de Oliveira case 'c': 524*829a6c0bSDaniel Bristot de Oliveira retval = parse_cpu_list(optarg, ¶ms->monitored_cpus); 525*829a6c0bSDaniel Bristot de Oliveira if (retval) 526*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage("\nInvalid -c cpu list\n"); 527*829a6c0bSDaniel Bristot de Oliveira params->cpus = optarg; 528*829a6c0bSDaniel Bristot de Oliveira break; 529*829a6c0bSDaniel Bristot de Oliveira case 'D': 530*829a6c0bSDaniel Bristot de Oliveira config_debug = 1; 531*829a6c0bSDaniel Bristot de Oliveira break; 532*829a6c0bSDaniel Bristot de Oliveira case 'd': 533*829a6c0bSDaniel Bristot de Oliveira params->duration = parse_seconds_duration(optarg); 534*829a6c0bSDaniel Bristot de Oliveira if (!params->duration) 535*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage("Invalid -D duration\n"); 536*829a6c0bSDaniel Bristot de Oliveira break; 537*829a6c0bSDaniel Bristot de Oliveira case 'e': 538*829a6c0bSDaniel Bristot de Oliveira params->entries = get_llong_from_str(optarg); 539*829a6c0bSDaniel Bristot de Oliveira if ((params->entries < 10) || (params->entries > 9999999)) 540*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage("Entries must be > 10 and < 9999999\n"); 541*829a6c0bSDaniel Bristot de Oliveira break; 542*829a6c0bSDaniel Bristot de Oliveira case 'h': 543*829a6c0bSDaniel Bristot de Oliveira case '?': 544*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage(NULL); 545*829a6c0bSDaniel Bristot de Oliveira break; 546*829a6c0bSDaniel Bristot de Oliveira case 'p': 547*829a6c0bSDaniel Bristot de Oliveira params->period = get_llong_from_str(optarg); 548*829a6c0bSDaniel Bristot de Oliveira if (params->period > 10000000) 549*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage("Period longer than 10 s\n"); 550*829a6c0bSDaniel Bristot de Oliveira break; 551*829a6c0bSDaniel Bristot de Oliveira case 'P': 552*829a6c0bSDaniel Bristot de Oliveira retval = parse_prio(optarg, ¶ms->sched_param); 553*829a6c0bSDaniel Bristot de Oliveira if (retval == -1) 554*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage("Invalid -P priority"); 555*829a6c0bSDaniel Bristot de Oliveira params->set_sched = 1; 556*829a6c0bSDaniel Bristot de Oliveira break; 557*829a6c0bSDaniel Bristot de Oliveira case 'r': 558*829a6c0bSDaniel Bristot de Oliveira params->runtime = get_llong_from_str(optarg); 559*829a6c0bSDaniel Bristot de Oliveira if (params->runtime < 100) 560*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage("Runtime shorter than 100 us\n"); 561*829a6c0bSDaniel Bristot de Oliveira break; 562*829a6c0bSDaniel Bristot de Oliveira case 's': 563*829a6c0bSDaniel Bristot de Oliveira params->stop_us = get_llong_from_str(optarg); 564*829a6c0bSDaniel Bristot de Oliveira break; 565*829a6c0bSDaniel Bristot de Oliveira case 'S': 566*829a6c0bSDaniel Bristot de Oliveira params->stop_total_us = get_llong_from_str(optarg); 567*829a6c0bSDaniel Bristot de Oliveira break; 568*829a6c0bSDaniel Bristot de Oliveira case 't': 569*829a6c0bSDaniel Bristot de Oliveira if (optarg) 570*829a6c0bSDaniel Bristot de Oliveira /* skip = */ 571*829a6c0bSDaniel Bristot de Oliveira params->trace_output = &optarg[1]; 572*829a6c0bSDaniel Bristot de Oliveira else 573*829a6c0bSDaniel Bristot de Oliveira params->trace_output = "osnoise_trace.txt"; 574*829a6c0bSDaniel Bristot de Oliveira break; 575*829a6c0bSDaniel Bristot de Oliveira case '0': /* no header */ 576*829a6c0bSDaniel Bristot de Oliveira params->no_header = 1; 577*829a6c0bSDaniel Bristot de Oliveira break; 578*829a6c0bSDaniel Bristot de Oliveira case '1': /* no summary */ 579*829a6c0bSDaniel Bristot de Oliveira params->no_summary = 1; 580*829a6c0bSDaniel Bristot de Oliveira break; 581*829a6c0bSDaniel Bristot de Oliveira case '2': /* no index */ 582*829a6c0bSDaniel Bristot de Oliveira params->no_index = 1; 583*829a6c0bSDaniel Bristot de Oliveira break; 584*829a6c0bSDaniel Bristot de Oliveira case '3': /* with zeros */ 585*829a6c0bSDaniel Bristot de Oliveira params->with_zeros = 1; 586*829a6c0bSDaniel Bristot de Oliveira break; 587*829a6c0bSDaniel Bristot de Oliveira default: 588*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage("Invalid option"); 589*829a6c0bSDaniel Bristot de Oliveira } 590*829a6c0bSDaniel Bristot de Oliveira } 591*829a6c0bSDaniel Bristot de Oliveira 592*829a6c0bSDaniel Bristot de Oliveira if (geteuid()) { 593*829a6c0bSDaniel Bristot de Oliveira err_msg("rtla needs root permission\n"); 594*829a6c0bSDaniel Bristot de Oliveira exit(EXIT_FAILURE); 595*829a6c0bSDaniel Bristot de Oliveira } 596*829a6c0bSDaniel Bristot de Oliveira 597*829a6c0bSDaniel Bristot de Oliveira if (params->no_index && !params->with_zeros) 598*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_usage("no-index set and with-zeros not set - it does not make sense"); 599*829a6c0bSDaniel Bristot de Oliveira 600*829a6c0bSDaniel Bristot de Oliveira return params; 601*829a6c0bSDaniel Bristot de Oliveira } 602*829a6c0bSDaniel Bristot de Oliveira 603*829a6c0bSDaniel Bristot de Oliveira /* 604*829a6c0bSDaniel Bristot de Oliveira * osnoise_hist_apply_config - apply the hist configs to the initialized tool 605*829a6c0bSDaniel Bristot de Oliveira */ 606*829a6c0bSDaniel Bristot de Oliveira static int 607*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_apply_config(struct osnoise_tool *tool, struct osnoise_hist_params *params) 608*829a6c0bSDaniel Bristot de Oliveira { 609*829a6c0bSDaniel Bristot de Oliveira int retval; 610*829a6c0bSDaniel Bristot de Oliveira 611*829a6c0bSDaniel Bristot de Oliveira if (!params->sleep_time) 612*829a6c0bSDaniel Bristot de Oliveira params->sleep_time = 1; 613*829a6c0bSDaniel Bristot de Oliveira 614*829a6c0bSDaniel Bristot de Oliveira if (params->cpus) { 615*829a6c0bSDaniel Bristot de Oliveira retval = osnoise_set_cpus(tool->context, params->cpus); 616*829a6c0bSDaniel Bristot de Oliveira if (retval) { 617*829a6c0bSDaniel Bristot de Oliveira err_msg("Failed to apply CPUs config\n"); 618*829a6c0bSDaniel Bristot de Oliveira goto out_err; 619*829a6c0bSDaniel Bristot de Oliveira } 620*829a6c0bSDaniel Bristot de Oliveira } 621*829a6c0bSDaniel Bristot de Oliveira 622*829a6c0bSDaniel Bristot de Oliveira if (params->runtime || params->period) { 623*829a6c0bSDaniel Bristot de Oliveira retval = osnoise_set_runtime_period(tool->context, 624*829a6c0bSDaniel Bristot de Oliveira params->runtime, 625*829a6c0bSDaniel Bristot de Oliveira params->period); 626*829a6c0bSDaniel Bristot de Oliveira if (retval) { 627*829a6c0bSDaniel Bristot de Oliveira err_msg("Failed to set runtime and/or period\n"); 628*829a6c0bSDaniel Bristot de Oliveira goto out_err; 629*829a6c0bSDaniel Bristot de Oliveira } 630*829a6c0bSDaniel Bristot de Oliveira } 631*829a6c0bSDaniel Bristot de Oliveira 632*829a6c0bSDaniel Bristot de Oliveira if (params->stop_us) { 633*829a6c0bSDaniel Bristot de Oliveira retval = osnoise_set_stop_us(tool->context, params->stop_us); 634*829a6c0bSDaniel Bristot de Oliveira if (retval) { 635*829a6c0bSDaniel Bristot de Oliveira err_msg("Failed to set stop us\n"); 636*829a6c0bSDaniel Bristot de Oliveira goto out_err; 637*829a6c0bSDaniel Bristot de Oliveira } 638*829a6c0bSDaniel Bristot de Oliveira } 639*829a6c0bSDaniel Bristot de Oliveira 640*829a6c0bSDaniel Bristot de Oliveira if (params->stop_total_us) { 641*829a6c0bSDaniel Bristot de Oliveira retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); 642*829a6c0bSDaniel Bristot de Oliveira if (retval) { 643*829a6c0bSDaniel Bristot de Oliveira err_msg("Failed to set stop total us\n"); 644*829a6c0bSDaniel Bristot de Oliveira goto out_err; 645*829a6c0bSDaniel Bristot de Oliveira } 646*829a6c0bSDaniel Bristot de Oliveira } 647*829a6c0bSDaniel Bristot de Oliveira 648*829a6c0bSDaniel Bristot de Oliveira return 0; 649*829a6c0bSDaniel Bristot de Oliveira 650*829a6c0bSDaniel Bristot de Oliveira out_err: 651*829a6c0bSDaniel Bristot de Oliveira return -1; 652*829a6c0bSDaniel Bristot de Oliveira } 653*829a6c0bSDaniel Bristot de Oliveira 654*829a6c0bSDaniel Bristot de Oliveira /* 655*829a6c0bSDaniel Bristot de Oliveira * osnoise_init_hist - initialize a osnoise hist tool with parameters 656*829a6c0bSDaniel Bristot de Oliveira */ 657*829a6c0bSDaniel Bristot de Oliveira static struct osnoise_tool 658*829a6c0bSDaniel Bristot de Oliveira *osnoise_init_hist(struct osnoise_hist_params *params) 659*829a6c0bSDaniel Bristot de Oliveira { 660*829a6c0bSDaniel Bristot de Oliveira struct osnoise_tool *tool; 661*829a6c0bSDaniel Bristot de Oliveira int nr_cpus; 662*829a6c0bSDaniel Bristot de Oliveira 663*829a6c0bSDaniel Bristot de Oliveira nr_cpus = sysconf(_SC_NPROCESSORS_CONF); 664*829a6c0bSDaniel Bristot de Oliveira 665*829a6c0bSDaniel Bristot de Oliveira tool = osnoise_init_tool("osnoise_hist"); 666*829a6c0bSDaniel Bristot de Oliveira if (!tool) 667*829a6c0bSDaniel Bristot de Oliveira return NULL; 668*829a6c0bSDaniel Bristot de Oliveira 669*829a6c0bSDaniel Bristot de Oliveira tool->data = osnoise_alloc_histogram(nr_cpus, params->entries, params->bucket_size); 670*829a6c0bSDaniel Bristot de Oliveira if (!tool->data) 671*829a6c0bSDaniel Bristot de Oliveira goto out_err; 672*829a6c0bSDaniel Bristot de Oliveira 673*829a6c0bSDaniel Bristot de Oliveira tool->params = params; 674*829a6c0bSDaniel Bristot de Oliveira 675*829a6c0bSDaniel Bristot de Oliveira return tool; 676*829a6c0bSDaniel Bristot de Oliveira 677*829a6c0bSDaniel Bristot de Oliveira out_err: 678*829a6c0bSDaniel Bristot de Oliveira osnoise_destroy_tool(tool); 679*829a6c0bSDaniel Bristot de Oliveira return NULL; 680*829a6c0bSDaniel Bristot de Oliveira } 681*829a6c0bSDaniel Bristot de Oliveira 682*829a6c0bSDaniel Bristot de Oliveira static int stop_tracing; 683*829a6c0bSDaniel Bristot de Oliveira static void stop_hist(int sig) 684*829a6c0bSDaniel Bristot de Oliveira { 685*829a6c0bSDaniel Bristot de Oliveira stop_tracing = 1; 686*829a6c0bSDaniel Bristot de Oliveira } 687*829a6c0bSDaniel Bristot de Oliveira 688*829a6c0bSDaniel Bristot de Oliveira /* 689*829a6c0bSDaniel Bristot de Oliveira * osnoise_hist_set_signals - handles the signal to stop the tool 690*829a6c0bSDaniel Bristot de Oliveira */ 691*829a6c0bSDaniel Bristot de Oliveira static void 692*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_set_signals(struct osnoise_hist_params *params) 693*829a6c0bSDaniel Bristot de Oliveira { 694*829a6c0bSDaniel Bristot de Oliveira signal(SIGINT, stop_hist); 695*829a6c0bSDaniel Bristot de Oliveira if (params->duration) { 696*829a6c0bSDaniel Bristot de Oliveira signal(SIGALRM, stop_hist); 697*829a6c0bSDaniel Bristot de Oliveira alarm(params->duration); 698*829a6c0bSDaniel Bristot de Oliveira } 699*829a6c0bSDaniel Bristot de Oliveira } 700*829a6c0bSDaniel Bristot de Oliveira 701*829a6c0bSDaniel Bristot de Oliveira int osnoise_hist_main(int argc, char *argv[]) 702*829a6c0bSDaniel Bristot de Oliveira { 703*829a6c0bSDaniel Bristot de Oliveira struct osnoise_hist_params *params; 704*829a6c0bSDaniel Bristot de Oliveira struct trace_instance *trace; 705*829a6c0bSDaniel Bristot de Oliveira struct osnoise_tool *record; 706*829a6c0bSDaniel Bristot de Oliveira struct osnoise_tool *tool; 707*829a6c0bSDaniel Bristot de Oliveira int return_value = 1; 708*829a6c0bSDaniel Bristot de Oliveira int retval; 709*829a6c0bSDaniel Bristot de Oliveira 710*829a6c0bSDaniel Bristot de Oliveira params = osnoise_hist_parse_args(argc, argv); 711*829a6c0bSDaniel Bristot de Oliveira if (!params) 712*829a6c0bSDaniel Bristot de Oliveira exit(1); 713*829a6c0bSDaniel Bristot de Oliveira 714*829a6c0bSDaniel Bristot de Oliveira tool = osnoise_init_hist(params); 715*829a6c0bSDaniel Bristot de Oliveira if (!tool) { 716*829a6c0bSDaniel Bristot de Oliveira err_msg("Could not init osnoise hist\n"); 717*829a6c0bSDaniel Bristot de Oliveira goto out_exit; 718*829a6c0bSDaniel Bristot de Oliveira } 719*829a6c0bSDaniel Bristot de Oliveira 720*829a6c0bSDaniel Bristot de Oliveira retval = osnoise_hist_apply_config(tool, params); 721*829a6c0bSDaniel Bristot de Oliveira if (retval) { 722*829a6c0bSDaniel Bristot de Oliveira err_msg("Could not apply config\n"); 723*829a6c0bSDaniel Bristot de Oliveira goto out_destroy; 724*829a6c0bSDaniel Bristot de Oliveira } 725*829a6c0bSDaniel Bristot de Oliveira 726*829a6c0bSDaniel Bristot de Oliveira trace = &tool->trace; 727*829a6c0bSDaniel Bristot de Oliveira 728*829a6c0bSDaniel Bristot de Oliveira retval = enable_osnoise(trace); 729*829a6c0bSDaniel Bristot de Oliveira if (retval) { 730*829a6c0bSDaniel Bristot de Oliveira err_msg("Failed to enable osnoise tracer\n"); 731*829a6c0bSDaniel Bristot de Oliveira goto out_destroy; 732*829a6c0bSDaniel Bristot de Oliveira } 733*829a6c0bSDaniel Bristot de Oliveira 734*829a6c0bSDaniel Bristot de Oliveira retval = osnoise_init_trace_hist(tool); 735*829a6c0bSDaniel Bristot de Oliveira if (retval) 736*829a6c0bSDaniel Bristot de Oliveira goto out_destroy; 737*829a6c0bSDaniel Bristot de Oliveira 738*829a6c0bSDaniel Bristot de Oliveira if (params->set_sched) { 739*829a6c0bSDaniel Bristot de Oliveira retval = set_comm_sched_attr("osnoise/", ¶ms->sched_param); 740*829a6c0bSDaniel Bristot de Oliveira if (retval) { 741*829a6c0bSDaniel Bristot de Oliveira err_msg("Failed to set sched parameters\n"); 742*829a6c0bSDaniel Bristot de Oliveira goto out_hist; 743*829a6c0bSDaniel Bristot de Oliveira } 744*829a6c0bSDaniel Bristot de Oliveira } 745*829a6c0bSDaniel Bristot de Oliveira 746*829a6c0bSDaniel Bristot de Oliveira trace_instance_start(trace); 747*829a6c0bSDaniel Bristot de Oliveira 748*829a6c0bSDaniel Bristot de Oliveira if (params->trace_output) { 749*829a6c0bSDaniel Bristot de Oliveira record = osnoise_init_trace_tool("osnoise"); 750*829a6c0bSDaniel Bristot de Oliveira if (!record) { 751*829a6c0bSDaniel Bristot de Oliveira err_msg("Failed to enable the trace instance\n"); 752*829a6c0bSDaniel Bristot de Oliveira goto out_hist; 753*829a6c0bSDaniel Bristot de Oliveira } 754*829a6c0bSDaniel Bristot de Oliveira trace_instance_start(&record->trace); 755*829a6c0bSDaniel Bristot de Oliveira } 756*829a6c0bSDaniel Bristot de Oliveira 757*829a6c0bSDaniel Bristot de Oliveira tool->start_time = time(NULL); 758*829a6c0bSDaniel Bristot de Oliveira osnoise_hist_set_signals(params); 759*829a6c0bSDaniel Bristot de Oliveira 760*829a6c0bSDaniel Bristot de Oliveira while (!stop_tracing) { 761*829a6c0bSDaniel Bristot de Oliveira sleep(params->sleep_time); 762*829a6c0bSDaniel Bristot de Oliveira 763*829a6c0bSDaniel Bristot de Oliveira retval = tracefs_iterate_raw_events(trace->tep, 764*829a6c0bSDaniel Bristot de Oliveira trace->inst, 765*829a6c0bSDaniel Bristot de Oliveira NULL, 766*829a6c0bSDaniel Bristot de Oliveira 0, 767*829a6c0bSDaniel Bristot de Oliveira collect_registered_events, 768*829a6c0bSDaniel Bristot de Oliveira trace); 769*829a6c0bSDaniel Bristot de Oliveira if (retval < 0) { 770*829a6c0bSDaniel Bristot de Oliveira err_msg("Error iterating on events\n"); 771*829a6c0bSDaniel Bristot de Oliveira goto out_hist; 772*829a6c0bSDaniel Bristot de Oliveira } 773*829a6c0bSDaniel Bristot de Oliveira 774*829a6c0bSDaniel Bristot de Oliveira if (!tracefs_trace_is_on(trace->inst)) 775*829a6c0bSDaniel Bristot de Oliveira break; 776*829a6c0bSDaniel Bristot de Oliveira }; 777*829a6c0bSDaniel Bristot de Oliveira 778*829a6c0bSDaniel Bristot de Oliveira osnoise_read_trace_hist(tool); 779*829a6c0bSDaniel Bristot de Oliveira 780*829a6c0bSDaniel Bristot de Oliveira osnoise_print_stats(params, tool); 781*829a6c0bSDaniel Bristot de Oliveira 782*829a6c0bSDaniel Bristot de Oliveira return_value = 0; 783*829a6c0bSDaniel Bristot de Oliveira 784*829a6c0bSDaniel Bristot de Oliveira if (!tracefs_trace_is_on(trace->inst)) { 785*829a6c0bSDaniel Bristot de Oliveira printf("rtla timelat hit stop tracing\n"); 786*829a6c0bSDaniel Bristot de Oliveira if (params->trace_output) { 787*829a6c0bSDaniel Bristot de Oliveira printf(" Saving trace to %s\n", params->trace_output); 788*829a6c0bSDaniel Bristot de Oliveira save_trace_to_file(record->trace.inst, params->trace_output); 789*829a6c0bSDaniel Bristot de Oliveira } 790*829a6c0bSDaniel Bristot de Oliveira } 791*829a6c0bSDaniel Bristot de Oliveira 792*829a6c0bSDaniel Bristot de Oliveira out_hist: 793*829a6c0bSDaniel Bristot de Oliveira osnoise_free_histogram(tool->data); 794*829a6c0bSDaniel Bristot de Oliveira out_destroy: 795*829a6c0bSDaniel Bristot de Oliveira osnoise_destroy_tool(tool); 796*829a6c0bSDaniel Bristot de Oliveira if (params->trace_output) 797*829a6c0bSDaniel Bristot de Oliveira osnoise_destroy_tool(record); 798*829a6c0bSDaniel Bristot de Oliveira free(params); 799*829a6c0bSDaniel Bristot de Oliveira out_exit: 800*829a6c0bSDaniel Bristot de Oliveira exit(return_value); 801*829a6c0bSDaniel Bristot de Oliveira } 802