11eeb6328SDaniel Bristot de Oliveira // SPDX-License-Identifier: GPL-2.0
21eeb6328SDaniel Bristot de Oliveira /*
31eeb6328SDaniel Bristot de Oliveira * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <[email protected]>
41eeb6328SDaniel Bristot de Oliveira */
51eeb6328SDaniel Bristot de Oliveira
6272ced25SDaniel Bristot de Oliveira #define _GNU_SOURCE
71eeb6328SDaniel Bristot de Oliveira #include <getopt.h>
81eeb6328SDaniel Bristot de Oliveira #include <stdlib.h>
91eeb6328SDaniel Bristot de Oliveira #include <string.h>
101eeb6328SDaniel Bristot de Oliveira #include <signal.h>
111eeb6328SDaniel Bristot de Oliveira #include <unistd.h>
121eeb6328SDaniel Bristot de Oliveira #include <stdio.h>
131eeb6328SDaniel Bristot de Oliveira #include <time.h>
14272ced25SDaniel Bristot de Oliveira #include <sched.h>
15ed774f74SDaniel Bristot de Oliveira #include <pthread.h>
161eeb6328SDaniel Bristot de Oliveira
171eeb6328SDaniel Bristot de Oliveira #include "timerlat.h"
182091336bSDaniel Bristot de Oliveira #include "timerlat_aa.h"
19ed774f74SDaniel Bristot de Oliveira #include "timerlat_u.h"
20fd7925cbSTomas Glozar #include "timerlat_bpf.h"
211eeb6328SDaniel Bristot de Oliveira
221eeb6328SDaniel Bristot de Oliveira struct timerlat_hist_cpu {
231eeb6328SDaniel Bristot de Oliveira int *irq;
241eeb6328SDaniel Bristot de Oliveira int *thread;
25ed774f74SDaniel Bristot de Oliveira int *user;
261eeb6328SDaniel Bristot de Oliveira
2776b31021STomas Glozar unsigned long long irq_count;
2876b31021STomas Glozar unsigned long long thread_count;
2976b31021STomas Glozar unsigned long long user_count;
301eeb6328SDaniel Bristot de Oliveira
311eeb6328SDaniel Bristot de Oliveira unsigned long long min_irq;
321eeb6328SDaniel Bristot de Oliveira unsigned long long sum_irq;
331eeb6328SDaniel Bristot de Oliveira unsigned long long max_irq;
341eeb6328SDaniel Bristot de Oliveira
351eeb6328SDaniel Bristot de Oliveira unsigned long long min_thread;
361eeb6328SDaniel Bristot de Oliveira unsigned long long sum_thread;
371eeb6328SDaniel Bristot de Oliveira unsigned long long max_thread;
38ed774f74SDaniel Bristot de Oliveira
39ed774f74SDaniel Bristot de Oliveira unsigned long long min_user;
40ed774f74SDaniel Bristot de Oliveira unsigned long long sum_user;
41ed774f74SDaniel Bristot de Oliveira unsigned long long max_user;
421eeb6328SDaniel Bristot de Oliveira };
431eeb6328SDaniel Bristot de Oliveira
441eeb6328SDaniel Bristot de Oliveira struct timerlat_hist_data {
451eeb6328SDaniel Bristot de Oliveira struct timerlat_hist_cpu *hist;
461eeb6328SDaniel Bristot de Oliveira int entries;
471eeb6328SDaniel Bristot de Oliveira int bucket_size;
481eeb6328SDaniel Bristot de Oliveira int nr_cpus;
491eeb6328SDaniel Bristot de Oliveira };
501eeb6328SDaniel Bristot de Oliveira
511eeb6328SDaniel Bristot de Oliveira /*
521eeb6328SDaniel Bristot de Oliveira * timerlat_free_histogram - free runtime data
531eeb6328SDaniel Bristot de Oliveira */
541eeb6328SDaniel Bristot de Oliveira static void
timerlat_free_histogram(struct timerlat_hist_data * data)551eeb6328SDaniel Bristot de Oliveira timerlat_free_histogram(struct timerlat_hist_data *data)
561eeb6328SDaniel Bristot de Oliveira {
571eeb6328SDaniel Bristot de Oliveira int cpu;
581eeb6328SDaniel Bristot de Oliveira
591eeb6328SDaniel Bristot de Oliveira /* one histogram for IRQ and one for thread, per CPU */
601eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) {
611eeb6328SDaniel Bristot de Oliveira if (data->hist[cpu].irq)
621eeb6328SDaniel Bristot de Oliveira free(data->hist[cpu].irq);
631eeb6328SDaniel Bristot de Oliveira
641eeb6328SDaniel Bristot de Oliveira if (data->hist[cpu].thread)
651eeb6328SDaniel Bristot de Oliveira free(data->hist[cpu].thread);
66ed774f74SDaniel Bristot de Oliveira
67ed774f74SDaniel Bristot de Oliveira if (data->hist[cpu].user)
68ed774f74SDaniel Bristot de Oliveira free(data->hist[cpu].user);
69ed774f74SDaniel Bristot de Oliveira
701eeb6328SDaniel Bristot de Oliveira }
711eeb6328SDaniel Bristot de Oliveira
721eeb6328SDaniel Bristot de Oliveira /* one set of histograms per CPU */
731eeb6328SDaniel Bristot de Oliveira if (data->hist)
741eeb6328SDaniel Bristot de Oliveira free(data->hist);
751eeb6328SDaniel Bristot de Oliveira
761eeb6328SDaniel Bristot de Oliveira free(data);
771eeb6328SDaniel Bristot de Oliveira }
781eeb6328SDaniel Bristot de Oliveira
791eeb6328SDaniel Bristot de Oliveira /*
801eeb6328SDaniel Bristot de Oliveira * timerlat_alloc_histogram - alloc runtime data
811eeb6328SDaniel Bristot de Oliveira */
821eeb6328SDaniel Bristot de Oliveira static struct timerlat_hist_data
timerlat_alloc_histogram(int nr_cpus,int entries,int bucket_size)831eeb6328SDaniel Bristot de Oliveira *timerlat_alloc_histogram(int nr_cpus, int entries, int bucket_size)
841eeb6328SDaniel Bristot de Oliveira {
851eeb6328SDaniel Bristot de Oliveira struct timerlat_hist_data *data;
861eeb6328SDaniel Bristot de Oliveira int cpu;
871eeb6328SDaniel Bristot de Oliveira
881eeb6328SDaniel Bristot de Oliveira data = calloc(1, sizeof(*data));
891eeb6328SDaniel Bristot de Oliveira if (!data)
901eeb6328SDaniel Bristot de Oliveira return NULL;
911eeb6328SDaniel Bristot de Oliveira
921eeb6328SDaniel Bristot de Oliveira data->entries = entries;
931eeb6328SDaniel Bristot de Oliveira data->bucket_size = bucket_size;
941eeb6328SDaniel Bristot de Oliveira data->nr_cpus = nr_cpus;
951eeb6328SDaniel Bristot de Oliveira
961eeb6328SDaniel Bristot de Oliveira /* one set of histograms per CPU */
971eeb6328SDaniel Bristot de Oliveira data->hist = calloc(1, sizeof(*data->hist) * nr_cpus);
981eeb6328SDaniel Bristot de Oliveira if (!data->hist)
991eeb6328SDaniel Bristot de Oliveira goto cleanup;
1001eeb6328SDaniel Bristot de Oliveira
1011eeb6328SDaniel Bristot de Oliveira /* one histogram for IRQ and one for thread, per cpu */
1021eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < nr_cpus; cpu++) {
1031eeb6328SDaniel Bristot de Oliveira data->hist[cpu].irq = calloc(1, sizeof(*data->hist->irq) * (entries + 1));
1041eeb6328SDaniel Bristot de Oliveira if (!data->hist[cpu].irq)
1051eeb6328SDaniel Bristot de Oliveira goto cleanup;
106ed774f74SDaniel Bristot de Oliveira
1071eeb6328SDaniel Bristot de Oliveira data->hist[cpu].thread = calloc(1, sizeof(*data->hist->thread) * (entries + 1));
1081eeb6328SDaniel Bristot de Oliveira if (!data->hist[cpu].thread)
1091eeb6328SDaniel Bristot de Oliveira goto cleanup;
110ed774f74SDaniel Bristot de Oliveira
111ed774f74SDaniel Bristot de Oliveira data->hist[cpu].user = calloc(1, sizeof(*data->hist->user) * (entries + 1));
112ed774f74SDaniel Bristot de Oliveira if (!data->hist[cpu].user)
113ed774f74SDaniel Bristot de Oliveira goto cleanup;
1141eeb6328SDaniel Bristot de Oliveira }
1151eeb6328SDaniel Bristot de Oliveira
1161eeb6328SDaniel Bristot de Oliveira /* set the min to max */
1171eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < nr_cpus; cpu++) {
1181eeb6328SDaniel Bristot de Oliveira data->hist[cpu].min_irq = ~0;
1191eeb6328SDaniel Bristot de Oliveira data->hist[cpu].min_thread = ~0;
120ed774f74SDaniel Bristot de Oliveira data->hist[cpu].min_user = ~0;
1211eeb6328SDaniel Bristot de Oliveira }
1221eeb6328SDaniel Bristot de Oliveira
1231eeb6328SDaniel Bristot de Oliveira return data;
1241eeb6328SDaniel Bristot de Oliveira
1251eeb6328SDaniel Bristot de Oliveira cleanup:
1261eeb6328SDaniel Bristot de Oliveira timerlat_free_histogram(data);
1271eeb6328SDaniel Bristot de Oliveira return NULL;
1281eeb6328SDaniel Bristot de Oliveira }
1291eeb6328SDaniel Bristot de Oliveira
1301eeb6328SDaniel Bristot de Oliveira /*
1311eeb6328SDaniel Bristot de Oliveira * timerlat_hist_update - record a new timerlat occurent on cpu, updating data
1321eeb6328SDaniel Bristot de Oliveira */
1331eeb6328SDaniel Bristot de Oliveira static void
timerlat_hist_update(struct osnoise_tool * tool,int cpu,unsigned long long context,unsigned long long latency)1341eeb6328SDaniel Bristot de Oliveira timerlat_hist_update(struct osnoise_tool *tool, int cpu,
135ed774f74SDaniel Bristot de Oliveira unsigned long long context,
1361eeb6328SDaniel Bristot de Oliveira unsigned long long latency)
1371eeb6328SDaniel Bristot de Oliveira {
1386fa5e3a8STomas Glozar struct timerlat_params *params = tool->params;
1391eeb6328SDaniel Bristot de Oliveira struct timerlat_hist_data *data = tool->data;
1401eeb6328SDaniel Bristot de Oliveira int entries = data->entries;
1411eeb6328SDaniel Bristot de Oliveira int bucket;
1421eeb6328SDaniel Bristot de Oliveira int *hist;
1431eeb6328SDaniel Bristot de Oliveira
1441eeb6328SDaniel Bristot de Oliveira if (params->output_divisor)
1451eeb6328SDaniel Bristot de Oliveira latency = latency / params->output_divisor;
1461eeb6328SDaniel Bristot de Oliveira
1471eeb6328SDaniel Bristot de Oliveira bucket = latency / data->bucket_size;
1481eeb6328SDaniel Bristot de Oliveira
149ed774f74SDaniel Bristot de Oliveira if (!context) {
1501eeb6328SDaniel Bristot de Oliveira hist = data->hist[cpu].irq;
1511eeb6328SDaniel Bristot de Oliveira data->hist[cpu].irq_count++;
1521eeb6328SDaniel Bristot de Oliveira update_min(&data->hist[cpu].min_irq, &latency);
1531eeb6328SDaniel Bristot de Oliveira update_sum(&data->hist[cpu].sum_irq, &latency);
1541eeb6328SDaniel Bristot de Oliveira update_max(&data->hist[cpu].max_irq, &latency);
155ed774f74SDaniel Bristot de Oliveira } else if (context == 1) {
1561eeb6328SDaniel Bristot de Oliveira hist = data->hist[cpu].thread;
1571eeb6328SDaniel Bristot de Oliveira data->hist[cpu].thread_count++;
1581eeb6328SDaniel Bristot de Oliveira update_min(&data->hist[cpu].min_thread, &latency);
1591eeb6328SDaniel Bristot de Oliveira update_sum(&data->hist[cpu].sum_thread, &latency);
1601eeb6328SDaniel Bristot de Oliveira update_max(&data->hist[cpu].max_thread, &latency);
161ed774f74SDaniel Bristot de Oliveira } else { /* user */
162ed774f74SDaniel Bristot de Oliveira hist = data->hist[cpu].user;
163ed774f74SDaniel Bristot de Oliveira data->hist[cpu].user_count++;
164ed774f74SDaniel Bristot de Oliveira update_min(&data->hist[cpu].min_user, &latency);
165ed774f74SDaniel Bristot de Oliveira update_sum(&data->hist[cpu].sum_user, &latency);
166ed774f74SDaniel Bristot de Oliveira update_max(&data->hist[cpu].max_user, &latency);
1671eeb6328SDaniel Bristot de Oliveira }
1681eeb6328SDaniel Bristot de Oliveira
1691eeb6328SDaniel Bristot de Oliveira if (bucket < entries)
1701eeb6328SDaniel Bristot de Oliveira hist[bucket]++;
1711eeb6328SDaniel Bristot de Oliveira else
1721eeb6328SDaniel Bristot de Oliveira hist[entries]++;
1731eeb6328SDaniel Bristot de Oliveira }
1741eeb6328SDaniel Bristot de Oliveira
1751eeb6328SDaniel Bristot de Oliveira /*
1761eeb6328SDaniel Bristot de Oliveira * timerlat_hist_handler - this is the handler for timerlat tracer events
1771eeb6328SDaniel Bristot de Oliveira */
1781eeb6328SDaniel Bristot de Oliveira static int
timerlat_hist_handler(struct trace_seq * s,struct tep_record * record,struct tep_event * event,void * data)1791eeb6328SDaniel Bristot de Oliveira timerlat_hist_handler(struct trace_seq *s, struct tep_record *record,
1801eeb6328SDaniel Bristot de Oliveira struct tep_event *event, void *data)
1811eeb6328SDaniel Bristot de Oliveira {
1821eeb6328SDaniel Bristot de Oliveira struct trace_instance *trace = data;
183ed774f74SDaniel Bristot de Oliveira unsigned long long context, latency;
1841eeb6328SDaniel Bristot de Oliveira struct osnoise_tool *tool;
1851eeb6328SDaniel Bristot de Oliveira int cpu = record->cpu;
1861eeb6328SDaniel Bristot de Oliveira
1871eeb6328SDaniel Bristot de Oliveira tool = container_of(trace, struct osnoise_tool, trace);
1881eeb6328SDaniel Bristot de Oliveira
189ed774f74SDaniel Bristot de Oliveira tep_get_field_val(s, event, "context", record, &context, 1);
1901eeb6328SDaniel Bristot de Oliveira tep_get_field_val(s, event, "timer_latency", record, &latency, 1);
1911eeb6328SDaniel Bristot de Oliveira
192ed774f74SDaniel Bristot de Oliveira timerlat_hist_update(tool, cpu, context, latency);
1931eeb6328SDaniel Bristot de Oliveira
1941eeb6328SDaniel Bristot de Oliveira return 0;
1951eeb6328SDaniel Bristot de Oliveira }
1961eeb6328SDaniel Bristot de Oliveira
1971eeb6328SDaniel Bristot de Oliveira /*
198fd7925cbSTomas Glozar * timerlat_hist_bpf_pull_data - copy data from BPF maps into userspace
199fd7925cbSTomas Glozar */
timerlat_hist_bpf_pull_data(struct osnoise_tool * tool)200fd7925cbSTomas Glozar static int timerlat_hist_bpf_pull_data(struct osnoise_tool *tool)
201fd7925cbSTomas Glozar {
202fd7925cbSTomas Glozar struct timerlat_hist_data *data = tool->data;
203fd7925cbSTomas Glozar int i, j, err;
204fd7925cbSTomas Glozar long long value_irq[data->nr_cpus],
205fd7925cbSTomas Glozar value_thread[data->nr_cpus],
206fd7925cbSTomas Glozar value_user[data->nr_cpus];
207fd7925cbSTomas Glozar
208fd7925cbSTomas Glozar /* Pull histogram */
209fd7925cbSTomas Glozar for (i = 0; i < data->entries; i++) {
210fd7925cbSTomas Glozar err = timerlat_bpf_get_hist_value(i, value_irq, value_thread,
211fd7925cbSTomas Glozar value_user, data->nr_cpus);
212fd7925cbSTomas Glozar if (err)
213fd7925cbSTomas Glozar return err;
214fd7925cbSTomas Glozar for (j = 0; j < data->nr_cpus; j++) {
215fd7925cbSTomas Glozar data->hist[j].irq[i] = value_irq[j];
216fd7925cbSTomas Glozar data->hist[j].thread[i] = value_thread[j];
217fd7925cbSTomas Glozar data->hist[j].user[i] = value_user[j];
218fd7925cbSTomas Glozar }
219fd7925cbSTomas Glozar }
220fd7925cbSTomas Glozar
221fd7925cbSTomas Glozar /* Pull summary */
222fd7925cbSTomas Glozar err = timerlat_bpf_get_summary_value(SUMMARY_COUNT,
223fd7925cbSTomas Glozar value_irq, value_thread, value_user,
224fd7925cbSTomas Glozar data->nr_cpus);
225fd7925cbSTomas Glozar if (err)
226fd7925cbSTomas Glozar return err;
227fd7925cbSTomas Glozar for (i = 0; i < data->nr_cpus; i++) {
228fd7925cbSTomas Glozar data->hist[i].irq_count = value_irq[i];
229fd7925cbSTomas Glozar data->hist[i].thread_count = value_thread[i];
230fd7925cbSTomas Glozar data->hist[i].user_count = value_user[i];
231fd7925cbSTomas Glozar }
232fd7925cbSTomas Glozar
233fd7925cbSTomas Glozar err = timerlat_bpf_get_summary_value(SUMMARY_MIN,
234fd7925cbSTomas Glozar value_irq, value_thread, value_user,
235fd7925cbSTomas Glozar data->nr_cpus);
236fd7925cbSTomas Glozar if (err)
237fd7925cbSTomas Glozar return err;
238fd7925cbSTomas Glozar for (i = 0; i < data->nr_cpus; i++) {
239fd7925cbSTomas Glozar data->hist[i].min_irq = value_irq[i];
240fd7925cbSTomas Glozar data->hist[i].min_thread = value_thread[i];
241fd7925cbSTomas Glozar data->hist[i].min_user = value_user[i];
242fd7925cbSTomas Glozar }
243fd7925cbSTomas Glozar
244fd7925cbSTomas Glozar err = timerlat_bpf_get_summary_value(SUMMARY_MAX,
245fd7925cbSTomas Glozar value_irq, value_thread, value_user,
246fd7925cbSTomas Glozar data->nr_cpus);
247fd7925cbSTomas Glozar if (err)
248fd7925cbSTomas Glozar return err;
249fd7925cbSTomas Glozar for (i = 0; i < data->nr_cpus; i++) {
250fd7925cbSTomas Glozar data->hist[i].max_irq = value_irq[i];
251fd7925cbSTomas Glozar data->hist[i].max_thread = value_thread[i];
252fd7925cbSTomas Glozar data->hist[i].max_user = value_user[i];
253fd7925cbSTomas Glozar }
254fd7925cbSTomas Glozar
255fd7925cbSTomas Glozar err = timerlat_bpf_get_summary_value(SUMMARY_SUM,
256fd7925cbSTomas Glozar value_irq, value_thread, value_user,
257fd7925cbSTomas Glozar data->nr_cpus);
258fd7925cbSTomas Glozar if (err)
259fd7925cbSTomas Glozar return err;
260fd7925cbSTomas Glozar for (i = 0; i < data->nr_cpus; i++) {
261fd7925cbSTomas Glozar data->hist[i].sum_irq = value_irq[i];
262fd7925cbSTomas Glozar data->hist[i].sum_thread = value_thread[i];
263fd7925cbSTomas Glozar data->hist[i].sum_user = value_user[i];
264fd7925cbSTomas Glozar }
265fd7925cbSTomas Glozar
266fd7925cbSTomas Glozar err = timerlat_bpf_get_summary_value(SUMMARY_OVERFLOW,
267fd7925cbSTomas Glozar value_irq, value_thread, value_user,
268fd7925cbSTomas Glozar data->nr_cpus);
269fd7925cbSTomas Glozar if (err)
270fd7925cbSTomas Glozar return err;
271fd7925cbSTomas Glozar for (i = 0; i < data->nr_cpus; i++) {
272fd7925cbSTomas Glozar data->hist[i].irq[data->entries] = value_irq[i];
273fd7925cbSTomas Glozar data->hist[i].thread[data->entries] = value_thread[i];
274fd7925cbSTomas Glozar data->hist[i].user[data->entries] = value_user[i];
275fd7925cbSTomas Glozar }
276fd7925cbSTomas Glozar
277fd7925cbSTomas Glozar return 0;
278fd7925cbSTomas Glozar }
279fd7925cbSTomas Glozar
280fd7925cbSTomas Glozar /*
2811eeb6328SDaniel Bristot de Oliveira * timerlat_hist_header - print the header of the tracer to the output
2821eeb6328SDaniel Bristot de Oliveira */
timerlat_hist_header(struct osnoise_tool * tool)2831eeb6328SDaniel Bristot de Oliveira static void timerlat_hist_header(struct osnoise_tool *tool)
2841eeb6328SDaniel Bristot de Oliveira {
2856fa5e3a8STomas Glozar struct timerlat_params *params = tool->params;
2861eeb6328SDaniel Bristot de Oliveira struct timerlat_hist_data *data = tool->data;
2871eeb6328SDaniel Bristot de Oliveira struct trace_seq *s = tool->trace.seq;
2881eeb6328SDaniel Bristot de Oliveira char duration[26];
2891eeb6328SDaniel Bristot de Oliveira int cpu;
2901eeb6328SDaniel Bristot de Oliveira
2911eeb6328SDaniel Bristot de Oliveira if (params->no_header)
2921eeb6328SDaniel Bristot de Oliveira return;
2931eeb6328SDaniel Bristot de Oliveira
2941eeb6328SDaniel Bristot de Oliveira get_duration(tool->start_time, duration, sizeof(duration));
2951eeb6328SDaniel Bristot de Oliveira trace_seq_printf(s, "# RTLA timerlat histogram\n");
2961eeb6328SDaniel Bristot de Oliveira trace_seq_printf(s, "# Time unit is %s (%s)\n",
2971eeb6328SDaniel Bristot de Oliveira params->output_divisor == 1 ? "nanoseconds" : "microseconds",
2981eeb6328SDaniel Bristot de Oliveira params->output_divisor == 1 ? "ns" : "us");
2991eeb6328SDaniel Bristot de Oliveira
3001eeb6328SDaniel Bristot de Oliveira trace_seq_printf(s, "# Duration: %s\n", duration);
3011eeb6328SDaniel Bristot de Oliveira
3021eeb6328SDaniel Bristot de Oliveira if (!params->no_index)
3031eeb6328SDaniel Bristot de Oliveira trace_seq_printf(s, "Index");
3041eeb6328SDaniel Bristot de Oliveira
3051eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) {
306894c29c7SDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
3071eeb6328SDaniel Bristot de Oliveira continue;
3081eeb6328SDaniel Bristot de Oliveira
3091eeb6328SDaniel Bristot de Oliveira if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
3101eeb6328SDaniel Bristot de Oliveira continue;
3111eeb6328SDaniel Bristot de Oliveira
3121eeb6328SDaniel Bristot de Oliveira if (!params->no_irq)
3131eeb6328SDaniel Bristot de Oliveira trace_seq_printf(s, " IRQ-%03d", cpu);
3141eeb6328SDaniel Bristot de Oliveira
3151eeb6328SDaniel Bristot de Oliveira if (!params->no_thread)
3161eeb6328SDaniel Bristot de Oliveira trace_seq_printf(s, " Thr-%03d", cpu);
317ed774f74SDaniel Bristot de Oliveira
318*20d6b075STomas Glozar if (params->user_data)
319ed774f74SDaniel Bristot de Oliveira trace_seq_printf(s, " Usr-%03d", cpu);
3201eeb6328SDaniel Bristot de Oliveira }
3211eeb6328SDaniel Bristot de Oliveira trace_seq_printf(s, "\n");
3221eeb6328SDaniel Bristot de Oliveira
3231eeb6328SDaniel Bristot de Oliveira
3241eeb6328SDaniel Bristot de Oliveira trace_seq_do_printf(s);
3251eeb6328SDaniel Bristot de Oliveira trace_seq_reset(s);
3261eeb6328SDaniel Bristot de Oliveira }
3271eeb6328SDaniel Bristot de Oliveira
3281eeb6328SDaniel Bristot de Oliveira /*
3296cc45f8cSTomas Glozar * format_summary_value - format a line of summary value (min, max or avg)
3306cc45f8cSTomas Glozar * of hist data
3316cc45f8cSTomas Glozar */
format_summary_value(struct trace_seq * seq,int count,unsigned long long val,bool avg)3326cc45f8cSTomas Glozar static void format_summary_value(struct trace_seq *seq,
3336cc45f8cSTomas Glozar int count,
3346cc45f8cSTomas Glozar unsigned long long val,
3356cc45f8cSTomas Glozar bool avg)
3366cc45f8cSTomas Glozar {
3376cc45f8cSTomas Glozar if (count)
3386cc45f8cSTomas Glozar trace_seq_printf(seq, "%9llu ", avg ? val / count : val);
3396cc45f8cSTomas Glozar else
3406cc45f8cSTomas Glozar trace_seq_printf(seq, "%9c ", '-');
3416cc45f8cSTomas Glozar }
3426cc45f8cSTomas Glozar
3436cc45f8cSTomas Glozar /*
3441eeb6328SDaniel Bristot de Oliveira * timerlat_print_summary - print the summary of the hist data to the output
3451eeb6328SDaniel Bristot de Oliveira */
3461eeb6328SDaniel Bristot de Oliveira static void
timerlat_print_summary(struct timerlat_params * params,struct trace_instance * trace,struct timerlat_hist_data * data)3476fa5e3a8STomas Glozar timerlat_print_summary(struct timerlat_params *params,
3481eeb6328SDaniel Bristot de Oliveira struct trace_instance *trace,
3491eeb6328SDaniel Bristot de Oliveira struct timerlat_hist_data *data)
3501eeb6328SDaniel Bristot de Oliveira {
3511eeb6328SDaniel Bristot de Oliveira int cpu;
3521eeb6328SDaniel Bristot de Oliveira
3531eeb6328SDaniel Bristot de Oliveira if (params->no_summary)
3541eeb6328SDaniel Bristot de Oliveira return;
3551eeb6328SDaniel Bristot de Oliveira
3561eeb6328SDaniel Bristot de Oliveira if (!params->no_index)
3571eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "count:");
3581eeb6328SDaniel Bristot de Oliveira
3591eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) {
360894c29c7SDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
3611eeb6328SDaniel Bristot de Oliveira continue;
3621eeb6328SDaniel Bristot de Oliveira
3631eeb6328SDaniel Bristot de Oliveira if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
3641eeb6328SDaniel Bristot de Oliveira continue;
3651eeb6328SDaniel Bristot de Oliveira
3661eeb6328SDaniel Bristot de Oliveira if (!params->no_irq)
36776b31021STomas Glozar trace_seq_printf(trace->seq, "%9llu ",
3681eeb6328SDaniel Bristot de Oliveira data->hist[cpu].irq_count);
3691eeb6328SDaniel Bristot de Oliveira
3701eeb6328SDaniel Bristot de Oliveira if (!params->no_thread)
37176b31021STomas Glozar trace_seq_printf(trace->seq, "%9llu ",
3721eeb6328SDaniel Bristot de Oliveira data->hist[cpu].thread_count);
373ed774f74SDaniel Bristot de Oliveira
374*20d6b075STomas Glozar if (params->user_data)
37576b31021STomas Glozar trace_seq_printf(trace->seq, "%9llu ",
376ed774f74SDaniel Bristot de Oliveira data->hist[cpu].user_count);
3771eeb6328SDaniel Bristot de Oliveira }
3781eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
3791eeb6328SDaniel Bristot de Oliveira
3801eeb6328SDaniel Bristot de Oliveira if (!params->no_index)
3811eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "min: ");
3821eeb6328SDaniel Bristot de Oliveira
3831eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) {
384894c29c7SDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
3851eeb6328SDaniel Bristot de Oliveira continue;
3861eeb6328SDaniel Bristot de Oliveira
3871eeb6328SDaniel Bristot de Oliveira if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
3881eeb6328SDaniel Bristot de Oliveira continue;
3891eeb6328SDaniel Bristot de Oliveira
3906cc45f8cSTomas Glozar if (!params->no_irq)
3916cc45f8cSTomas Glozar format_summary_value(trace->seq,
3926cc45f8cSTomas Glozar data->hist[cpu].irq_count,
3936cc45f8cSTomas Glozar data->hist[cpu].min_irq,
3946cc45f8cSTomas Glozar false);
3951eeb6328SDaniel Bristot de Oliveira
3966cc45f8cSTomas Glozar if (!params->no_thread)
3976cc45f8cSTomas Glozar format_summary_value(trace->seq,
3986cc45f8cSTomas Glozar data->hist[cpu].thread_count,
3996cc45f8cSTomas Glozar data->hist[cpu].min_thread,
4006cc45f8cSTomas Glozar false);
401ed774f74SDaniel Bristot de Oliveira
402*20d6b075STomas Glozar if (params->user_data)
4036cc45f8cSTomas Glozar format_summary_value(trace->seq,
4046cc45f8cSTomas Glozar data->hist[cpu].user_count,
4056cc45f8cSTomas Glozar data->hist[cpu].min_user,
4066cc45f8cSTomas Glozar false);
4071eeb6328SDaniel Bristot de Oliveira }
4081eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
4091eeb6328SDaniel Bristot de Oliveira
4101eeb6328SDaniel Bristot de Oliveira if (!params->no_index)
4111eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "avg: ");
4121eeb6328SDaniel Bristot de Oliveira
4131eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) {
414894c29c7SDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
4151eeb6328SDaniel Bristot de Oliveira continue;
4161eeb6328SDaniel Bristot de Oliveira
4171eeb6328SDaniel Bristot de Oliveira if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
4181eeb6328SDaniel Bristot de Oliveira continue;
4191eeb6328SDaniel Bristot de Oliveira
4206cc45f8cSTomas Glozar if (!params->no_irq)
4216cc45f8cSTomas Glozar format_summary_value(trace->seq,
4226cc45f8cSTomas Glozar data->hist[cpu].irq_count,
4236cc45f8cSTomas Glozar data->hist[cpu].sum_irq,
4246cc45f8cSTomas Glozar true);
4251eeb6328SDaniel Bristot de Oliveira
4266cc45f8cSTomas Glozar if (!params->no_thread)
4276cc45f8cSTomas Glozar format_summary_value(trace->seq,
4286cc45f8cSTomas Glozar data->hist[cpu].thread_count,
4296cc45f8cSTomas Glozar data->hist[cpu].sum_thread,
4306cc45f8cSTomas Glozar true);
431ed774f74SDaniel Bristot de Oliveira
432*20d6b075STomas Glozar if (params->user_data)
4336cc45f8cSTomas Glozar format_summary_value(trace->seq,
4346cc45f8cSTomas Glozar data->hist[cpu].user_count,
4356cc45f8cSTomas Glozar data->hist[cpu].sum_user,
4366cc45f8cSTomas Glozar true);
4371eeb6328SDaniel Bristot de Oliveira }
4381eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
4391eeb6328SDaniel Bristot de Oliveira
4401eeb6328SDaniel Bristot de Oliveira if (!params->no_index)
4411eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "max: ");
4421eeb6328SDaniel Bristot de Oliveira
4431eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) {
444894c29c7SDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
4451eeb6328SDaniel Bristot de Oliveira continue;
4461eeb6328SDaniel Bristot de Oliveira
4471eeb6328SDaniel Bristot de Oliveira if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
4481eeb6328SDaniel Bristot de Oliveira continue;
4491eeb6328SDaniel Bristot de Oliveira
4506cc45f8cSTomas Glozar if (!params->no_irq)
4516cc45f8cSTomas Glozar format_summary_value(trace->seq,
4526cc45f8cSTomas Glozar data->hist[cpu].irq_count,
4536cc45f8cSTomas Glozar data->hist[cpu].max_irq,
4546cc45f8cSTomas Glozar false);
4551eeb6328SDaniel Bristot de Oliveira
4566cc45f8cSTomas Glozar if (!params->no_thread)
4576cc45f8cSTomas Glozar format_summary_value(trace->seq,
4586cc45f8cSTomas Glozar data->hist[cpu].thread_count,
4596cc45f8cSTomas Glozar data->hist[cpu].max_thread,
4606cc45f8cSTomas Glozar false);
461ed774f74SDaniel Bristot de Oliveira
462*20d6b075STomas Glozar if (params->user_data)
4636cc45f8cSTomas Glozar format_summary_value(trace->seq,
4646cc45f8cSTomas Glozar data->hist[cpu].user_count,
4656cc45f8cSTomas Glozar data->hist[cpu].max_user,
4666cc45f8cSTomas Glozar false);
4671eeb6328SDaniel Bristot de Oliveira }
4681eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
4691eeb6328SDaniel Bristot de Oliveira trace_seq_do_printf(trace->seq);
4701eeb6328SDaniel Bristot de Oliveira trace_seq_reset(trace->seq);
4711eeb6328SDaniel Bristot de Oliveira }
4721eeb6328SDaniel Bristot de Oliveira
4731462501cSDaniel Bristot de Oliveira static void
timerlat_print_stats_all(struct timerlat_params * params,struct trace_instance * trace,struct timerlat_hist_data * data)4746fa5e3a8STomas Glozar timerlat_print_stats_all(struct timerlat_params *params,
4751462501cSDaniel Bristot de Oliveira struct trace_instance *trace,
4761462501cSDaniel Bristot de Oliveira struct timerlat_hist_data *data)
4771462501cSDaniel Bristot de Oliveira {
4781462501cSDaniel Bristot de Oliveira struct timerlat_hist_cpu *cpu_data;
4791462501cSDaniel Bristot de Oliveira struct timerlat_hist_cpu sum;
4801462501cSDaniel Bristot de Oliveira int cpu;
4811462501cSDaniel Bristot de Oliveira
4821462501cSDaniel Bristot de Oliveira if (params->no_summary)
4831462501cSDaniel Bristot de Oliveira return;
4841462501cSDaniel Bristot de Oliveira
4851462501cSDaniel Bristot de Oliveira memset(&sum, 0, sizeof(sum));
4861462501cSDaniel Bristot de Oliveira sum.min_irq = ~0;
4871462501cSDaniel Bristot de Oliveira sum.min_thread = ~0;
4881462501cSDaniel Bristot de Oliveira sum.min_user = ~0;
4891462501cSDaniel Bristot de Oliveira
4901462501cSDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) {
4911462501cSDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
4921462501cSDaniel Bristot de Oliveira continue;
4931462501cSDaniel Bristot de Oliveira
4941462501cSDaniel Bristot de Oliveira if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
4951462501cSDaniel Bristot de Oliveira continue;
4961462501cSDaniel Bristot de Oliveira
4971462501cSDaniel Bristot de Oliveira cpu_data = &data->hist[cpu];
4981462501cSDaniel Bristot de Oliveira
4991462501cSDaniel Bristot de Oliveira sum.irq_count += cpu_data->irq_count;
5001462501cSDaniel Bristot de Oliveira update_min(&sum.min_irq, &cpu_data->min_irq);
5011462501cSDaniel Bristot de Oliveira update_sum(&sum.sum_irq, &cpu_data->sum_irq);
5021462501cSDaniel Bristot de Oliveira update_max(&sum.max_irq, &cpu_data->max_irq);
5031462501cSDaniel Bristot de Oliveira
5041462501cSDaniel Bristot de Oliveira sum.thread_count += cpu_data->thread_count;
5051462501cSDaniel Bristot de Oliveira update_min(&sum.min_thread, &cpu_data->min_thread);
5061462501cSDaniel Bristot de Oliveira update_sum(&sum.sum_thread, &cpu_data->sum_thread);
5071462501cSDaniel Bristot de Oliveira update_max(&sum.max_thread, &cpu_data->max_thread);
5081462501cSDaniel Bristot de Oliveira
5091462501cSDaniel Bristot de Oliveira sum.user_count += cpu_data->user_count;
5101462501cSDaniel Bristot de Oliveira update_min(&sum.min_user, &cpu_data->min_user);
5111462501cSDaniel Bristot de Oliveira update_sum(&sum.sum_user, &cpu_data->sum_user);
5121462501cSDaniel Bristot de Oliveira update_max(&sum.max_user, &cpu_data->max_user);
5131462501cSDaniel Bristot de Oliveira }
5141462501cSDaniel Bristot de Oliveira
5151462501cSDaniel Bristot de Oliveira if (!params->no_index)
5161462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "ALL: ");
5171462501cSDaniel Bristot de Oliveira
5181462501cSDaniel Bristot de Oliveira if (!params->no_irq)
5191462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, " IRQ");
5201462501cSDaniel Bristot de Oliveira
5211462501cSDaniel Bristot de Oliveira if (!params->no_thread)
5221462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, " Thr");
5231462501cSDaniel Bristot de Oliveira
524*20d6b075STomas Glozar if (params->user_data)
5251462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, " Usr");
5261462501cSDaniel Bristot de Oliveira
5271462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
5281462501cSDaniel Bristot de Oliveira
5291462501cSDaniel Bristot de Oliveira if (!params->no_index)
5301462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "count:");
5311462501cSDaniel Bristot de Oliveira
5321462501cSDaniel Bristot de Oliveira if (!params->no_irq)
53376b31021STomas Glozar trace_seq_printf(trace->seq, "%9llu ",
5341462501cSDaniel Bristot de Oliveira sum.irq_count);
5351462501cSDaniel Bristot de Oliveira
5361462501cSDaniel Bristot de Oliveira if (!params->no_thread)
53776b31021STomas Glozar trace_seq_printf(trace->seq, "%9llu ",
5381462501cSDaniel Bristot de Oliveira sum.thread_count);
5391462501cSDaniel Bristot de Oliveira
540*20d6b075STomas Glozar if (params->user_data)
54176b31021STomas Glozar trace_seq_printf(trace->seq, "%9llu ",
5421462501cSDaniel Bristot de Oliveira sum.user_count);
5431462501cSDaniel Bristot de Oliveira
5441462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
5451462501cSDaniel Bristot de Oliveira
5461462501cSDaniel Bristot de Oliveira if (!params->no_index)
5471462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "min: ");
5481462501cSDaniel Bristot de Oliveira
5491462501cSDaniel Bristot de Oliveira if (!params->no_irq)
5506cc45f8cSTomas Glozar format_summary_value(trace->seq,
5516cc45f8cSTomas Glozar sum.irq_count,
5526cc45f8cSTomas Glozar sum.min_irq,
5536cc45f8cSTomas Glozar false);
5541462501cSDaniel Bristot de Oliveira
5551462501cSDaniel Bristot de Oliveira if (!params->no_thread)
5566cc45f8cSTomas Glozar format_summary_value(trace->seq,
5576cc45f8cSTomas Glozar sum.thread_count,
5586cc45f8cSTomas Glozar sum.min_thread,
5596cc45f8cSTomas Glozar false);
5601462501cSDaniel Bristot de Oliveira
561*20d6b075STomas Glozar if (params->user_data)
5626cc45f8cSTomas Glozar format_summary_value(trace->seq,
5636cc45f8cSTomas Glozar sum.user_count,
5646cc45f8cSTomas Glozar sum.min_user,
5656cc45f8cSTomas Glozar false);
5661462501cSDaniel Bristot de Oliveira
5671462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
5681462501cSDaniel Bristot de Oliveira
5691462501cSDaniel Bristot de Oliveira if (!params->no_index)
5701462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "avg: ");
5711462501cSDaniel Bristot de Oliveira
5721462501cSDaniel Bristot de Oliveira if (!params->no_irq)
5736cc45f8cSTomas Glozar format_summary_value(trace->seq,
5746cc45f8cSTomas Glozar sum.irq_count,
5756cc45f8cSTomas Glozar sum.sum_irq,
5766cc45f8cSTomas Glozar true);
5771462501cSDaniel Bristot de Oliveira
5781462501cSDaniel Bristot de Oliveira if (!params->no_thread)
5796cc45f8cSTomas Glozar format_summary_value(trace->seq,
5806cc45f8cSTomas Glozar sum.thread_count,
5816cc45f8cSTomas Glozar sum.sum_thread,
5826cc45f8cSTomas Glozar true);
5831462501cSDaniel Bristot de Oliveira
584*20d6b075STomas Glozar if (params->user_data)
5856cc45f8cSTomas Glozar format_summary_value(trace->seq,
5866cc45f8cSTomas Glozar sum.user_count,
5876cc45f8cSTomas Glozar sum.sum_user,
5886cc45f8cSTomas Glozar true);
5891462501cSDaniel Bristot de Oliveira
5901462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
5911462501cSDaniel Bristot de Oliveira
5921462501cSDaniel Bristot de Oliveira if (!params->no_index)
5931462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "max: ");
5941462501cSDaniel Bristot de Oliveira
5951462501cSDaniel Bristot de Oliveira if (!params->no_irq)
5966cc45f8cSTomas Glozar format_summary_value(trace->seq,
5976cc45f8cSTomas Glozar sum.irq_count,
5986cc45f8cSTomas Glozar sum.max_irq,
5996cc45f8cSTomas Glozar false);
6001462501cSDaniel Bristot de Oliveira
6011462501cSDaniel Bristot de Oliveira if (!params->no_thread)
6026cc45f8cSTomas Glozar format_summary_value(trace->seq,
6036cc45f8cSTomas Glozar sum.thread_count,
6046cc45f8cSTomas Glozar sum.max_thread,
6056cc45f8cSTomas Glozar false);
6061462501cSDaniel Bristot de Oliveira
607*20d6b075STomas Glozar if (params->user_data)
6086cc45f8cSTomas Glozar format_summary_value(trace->seq,
6096cc45f8cSTomas Glozar sum.user_count,
6106cc45f8cSTomas Glozar sum.max_user,
6116cc45f8cSTomas Glozar false);
6121462501cSDaniel Bristot de Oliveira
6131462501cSDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
6141462501cSDaniel Bristot de Oliveira trace_seq_do_printf(trace->seq);
6151462501cSDaniel Bristot de Oliveira trace_seq_reset(trace->seq);
6161462501cSDaniel Bristot de Oliveira }
6171462501cSDaniel Bristot de Oliveira
6181eeb6328SDaniel Bristot de Oliveira /*
6191462501cSDaniel Bristot de Oliveira * timerlat_print_stats - print data for each CPUs
6201eeb6328SDaniel Bristot de Oliveira */
6211eeb6328SDaniel Bristot de Oliveira static void
timerlat_print_stats(struct timerlat_params * params,struct osnoise_tool * tool)6226fa5e3a8STomas Glozar timerlat_print_stats(struct timerlat_params *params, struct osnoise_tool *tool)
6231eeb6328SDaniel Bristot de Oliveira {
6241eeb6328SDaniel Bristot de Oliveira struct timerlat_hist_data *data = tool->data;
6251eeb6328SDaniel Bristot de Oliveira struct trace_instance *trace = &tool->trace;
6261eeb6328SDaniel Bristot de Oliveira int bucket, cpu;
6271eeb6328SDaniel Bristot de Oliveira int total;
6281eeb6328SDaniel Bristot de Oliveira
6291eeb6328SDaniel Bristot de Oliveira timerlat_hist_header(tool);
6301eeb6328SDaniel Bristot de Oliveira
6311eeb6328SDaniel Bristot de Oliveira for (bucket = 0; bucket < data->entries; bucket++) {
6321eeb6328SDaniel Bristot de Oliveira total = 0;
6331eeb6328SDaniel Bristot de Oliveira
6341eeb6328SDaniel Bristot de Oliveira if (!params->no_index)
6351eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%-6d",
6361eeb6328SDaniel Bristot de Oliveira bucket * data->bucket_size);
6371eeb6328SDaniel Bristot de Oliveira
6381eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) {
639894c29c7SDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
6401eeb6328SDaniel Bristot de Oliveira continue;
6411eeb6328SDaniel Bristot de Oliveira
6421eeb6328SDaniel Bristot de Oliveira if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
6431eeb6328SDaniel Bristot de Oliveira continue;
6441eeb6328SDaniel Bristot de Oliveira
6451eeb6328SDaniel Bristot de Oliveira if (!params->no_irq) {
6461eeb6328SDaniel Bristot de Oliveira total += data->hist[cpu].irq[bucket];
6471eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9d ",
6481eeb6328SDaniel Bristot de Oliveira data->hist[cpu].irq[bucket]);
6491eeb6328SDaniel Bristot de Oliveira }
6501eeb6328SDaniel Bristot de Oliveira
6511eeb6328SDaniel Bristot de Oliveira if (!params->no_thread) {
6521eeb6328SDaniel Bristot de Oliveira total += data->hist[cpu].thread[bucket];
6531eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9d ",
6541eeb6328SDaniel Bristot de Oliveira data->hist[cpu].thread[bucket]);
6551eeb6328SDaniel Bristot de Oliveira }
6561eeb6328SDaniel Bristot de Oliveira
657*20d6b075STomas Glozar if (params->user_data) {
658ed774f74SDaniel Bristot de Oliveira total += data->hist[cpu].user[bucket];
659ed774f74SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9d ",
660ed774f74SDaniel Bristot de Oliveira data->hist[cpu].user[bucket]);
661ed774f74SDaniel Bristot de Oliveira }
662ed774f74SDaniel Bristot de Oliveira
6631eeb6328SDaniel Bristot de Oliveira }
6641eeb6328SDaniel Bristot de Oliveira
6651eeb6328SDaniel Bristot de Oliveira if (total == 0 && !params->with_zeros) {
6661eeb6328SDaniel Bristot de Oliveira trace_seq_reset(trace->seq);
6671eeb6328SDaniel Bristot de Oliveira continue;
6681eeb6328SDaniel Bristot de Oliveira }
6691eeb6328SDaniel Bristot de Oliveira
6701eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
6711eeb6328SDaniel Bristot de Oliveira trace_seq_do_printf(trace->seq);
6721eeb6328SDaniel Bristot de Oliveira trace_seq_reset(trace->seq);
6731eeb6328SDaniel Bristot de Oliveira }
6741eeb6328SDaniel Bristot de Oliveira
6751eeb6328SDaniel Bristot de Oliveira if (!params->no_index)
6761eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "over: ");
6771eeb6328SDaniel Bristot de Oliveira
6781eeb6328SDaniel Bristot de Oliveira for (cpu = 0; cpu < data->nr_cpus; cpu++) {
679894c29c7SDaniel Bristot de Oliveira if (params->cpus && !CPU_ISSET(cpu, ¶ms->monitored_cpus))
6801eeb6328SDaniel Bristot de Oliveira continue;
6811eeb6328SDaniel Bristot de Oliveira
6821eeb6328SDaniel Bristot de Oliveira if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
6831eeb6328SDaniel Bristot de Oliveira continue;
6841eeb6328SDaniel Bristot de Oliveira
6851eeb6328SDaniel Bristot de Oliveira if (!params->no_irq)
6861eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9d ",
6871eeb6328SDaniel Bristot de Oliveira data->hist[cpu].irq[data->entries]);
6881eeb6328SDaniel Bristot de Oliveira
6891eeb6328SDaniel Bristot de Oliveira if (!params->no_thread)
6901eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9d ",
6911eeb6328SDaniel Bristot de Oliveira data->hist[cpu].thread[data->entries]);
692ed774f74SDaniel Bristot de Oliveira
693*20d6b075STomas Glozar if (params->user_data)
694ed774f74SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "%9d ",
695ed774f74SDaniel Bristot de Oliveira data->hist[cpu].user[data->entries]);
6961eeb6328SDaniel Bristot de Oliveira }
6971eeb6328SDaniel Bristot de Oliveira trace_seq_printf(trace->seq, "\n");
6981eeb6328SDaniel Bristot de Oliveira trace_seq_do_printf(trace->seq);
6991eeb6328SDaniel Bristot de Oliveira trace_seq_reset(trace->seq);
7001eeb6328SDaniel Bristot de Oliveira
7011eeb6328SDaniel Bristot de Oliveira timerlat_print_summary(params, trace, data);
7021462501cSDaniel Bristot de Oliveira timerlat_print_stats_all(params, trace, data);
703cf186201STomas Glozar osnoise_report_missed_events(tool);
7041eeb6328SDaniel Bristot de Oliveira }
7051eeb6328SDaniel Bristot de Oliveira
7061eeb6328SDaniel Bristot de Oliveira /*
7071eeb6328SDaniel Bristot de Oliveira * timerlat_hist_usage - prints timerlat top usage message
7081eeb6328SDaniel Bristot de Oliveira */
timerlat_hist_usage(char * usage)7091eeb6328SDaniel Bristot de Oliveira static void timerlat_hist_usage(char *usage)
7101eeb6328SDaniel Bristot de Oliveira {
7111eeb6328SDaniel Bristot de Oliveira int i;
7121eeb6328SDaniel Bristot de Oliveira
7131eeb6328SDaniel Bristot de Oliveira char *msg[] = {
7141eeb6328SDaniel Bristot de Oliveira "",
715173a3b01SDaniel Bristot de Oliveira " usage: [rtla] timerlat hist [-h] [-q] [-d s] [-D] [-n] [-a us] [-p us] [-i us] [-T us] [-s us] \\",
716842fc5b8SJohn Kacur " [-t[file]] [-e sys[:event]] [--filter <filter>] [--trigger <trigger>] [-c cpu-list] [-H cpu-list]\\",
71744f3a37dSDaniel Bristot de Oliveira " [-P priority] [-E N] [-b N] [--no-irq] [--no-thread] [--no-header] [--no-summary] \\",
718fb9e90a6SDaniel Bristot de Oliveira " [--no-index] [--with-zeros] [--dma-latency us] [-C[=cgroup_name]] [--no-aa] [--dump-task] [-u|-k]",
719cfbfbfc9STomas Glozar " [--warm-up s] [--deepest-idle-state n]",
7201eeb6328SDaniel Bristot de Oliveira "",
7211eeb6328SDaniel Bristot de Oliveira " -h/--help: print this menu",
722173a3b01SDaniel Bristot de Oliveira " -a/--auto: set automatic trace mode, stopping the session if argument in us latency is hit",
7231eeb6328SDaniel Bristot de Oliveira " -p/--period us: timerlat period in us",
7241eeb6328SDaniel Bristot de Oliveira " -i/--irq us: stop trace if the irq latency is higher than the argument in us",
7251eeb6328SDaniel Bristot de Oliveira " -T/--thread us: stop trace if the thread latency is higher than the argument in us",
7261eeb6328SDaniel Bristot de Oliveira " -s/--stack us: save the stack trace at the IRQ if a thread latency is higher than the argument in us",
7271eeb6328SDaniel Bristot de Oliveira " -c/--cpus cpus: run the tracer only on the given cpus",
728272ced25SDaniel Bristot de Oliveira " -H/--house-keeping cpus: run rtla control threads only on the given cpus",
729a957cbc0SDaniel Bristot de Oliveira " -C/--cgroup[=cgroup_name]: set cgroup, if no cgroup_name is passed, the rtla's cgroup will be inherited",
7301eeb6328SDaniel Bristot de Oliveira " -d/--duration time[m|h|d]: duration of the session in seconds",
7312091336bSDaniel Bristot de Oliveira " --dump-tasks: prints the task running on all CPUs if stop conditions are met (depends on !--no-aa)",
7321eeb6328SDaniel Bristot de Oliveira " -D/--debug: print debug info",
733842fc5b8SJohn Kacur " -t/--trace[file]: save the stopped trace to [file|timerlat_trace.txt]",
73451d64c3aSDaniel Bristot de Oliveira " -e/--event <sys:event>: enable the <sys:event> in the trace instance, multiple -e are allowed",
73544f3a37dSDaniel Bristot de Oliveira " --filter <filter>: enable a trace event filter to the previous -e event",
7361a754893SDaniel Bristot de Oliveira " --trigger <trigger>: enable a trace event trigger to the previous -e event",
7371eeb6328SDaniel Bristot de Oliveira " -n/--nano: display data in nanoseconds",
7382091336bSDaniel Bristot de Oliveira " --no-aa: disable auto-analysis, reducing rtla timerlat cpu usage",
7391eeb6328SDaniel Bristot de Oliveira " -b/--bucket-size N: set the histogram bucket size (default 1)",
740dd48f316SDaniel Bristot de Oliveira " -E/--entries N: set the number of entries of the histogram (default 256)",
7411eeb6328SDaniel Bristot de Oliveira " --no-irq: ignore IRQ latencies",
7421eeb6328SDaniel Bristot de Oliveira " --no-thread: ignore thread latencies",
7431eeb6328SDaniel Bristot de Oliveira " --no-header: do not print header",
7441eeb6328SDaniel Bristot de Oliveira " --no-summary: do not print summary",
7451eeb6328SDaniel Bristot de Oliveira " --no-index: do not print index",
7461eeb6328SDaniel Bristot de Oliveira " --with-zeros: print zero only entries",
7477d0dc957SDaniel Bristot de Oliveira " --dma-latency us: set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency",
7481eeb6328SDaniel Bristot de Oliveira " -P/--priority o:prio|r:prio|f:prio|d:runtime:period : set scheduling parameters",
7491eeb6328SDaniel Bristot de Oliveira " o:prio - use SCHED_OTHER with prio",
7501eeb6328SDaniel Bristot de Oliveira " r:prio - use SCHED_RR with prio",
7511eeb6328SDaniel Bristot de Oliveira " f:prio - use SCHED_FIFO with prio",
7521eeb6328SDaniel Bristot de Oliveira " d:runtime[us|ms|s]:period[us|ms|s] - use SCHED_DEADLINE with runtime and period",
7531eeb6328SDaniel Bristot de Oliveira " in nanoseconds",
754fb9e90a6SDaniel Bristot de Oliveira " -u/--user-threads: use rtla user-space threads instead of kernel-space timerlat threads",
755fb9e90a6SDaniel Bristot de Oliveira " -k/--kernel-threads: use timerlat kernel-space threads instead of rtla user-space threads",
756a23c05fdSDaniel Bristot de Oliveira " -U/--user-load: enable timerlat for user-defined user-space workload",
757cdbf7196SDaniel Bristot de Oliveira " --warm-up s: let the workload run for s seconds before collecting data",
758e9a4062eSDaniel Bristot de Oliveira " --trace-buffer-size kB: set the per-cpu trace buffer size in kB",
759cfbfbfc9STomas Glozar " --deepest-idle-state n: only go down to idle state n on cpus used by timerlat to reduce exit from idle latency",
7601eeb6328SDaniel Bristot de Oliveira NULL,
7611eeb6328SDaniel Bristot de Oliveira };
7621eeb6328SDaniel Bristot de Oliveira
7631eeb6328SDaniel Bristot de Oliveira if (usage)
7641eeb6328SDaniel Bristot de Oliveira fprintf(stderr, "%s\n", usage);
7651eeb6328SDaniel Bristot de Oliveira
7661eeb6328SDaniel Bristot de Oliveira fprintf(stderr, "rtla timerlat hist: a per-cpu histogram of the timer latency (version %s)\n",
7671eeb6328SDaniel Bristot de Oliveira VERSION);
7681eeb6328SDaniel Bristot de Oliveira
7691eeb6328SDaniel Bristot de Oliveira for (i = 0; msg[i]; i++)
7701eeb6328SDaniel Bristot de Oliveira fprintf(stderr, "%s\n", msg[i]);
771b5f31936SJohn Kacur
772b5f31936SJohn Kacur if (usage)
773b5f31936SJohn Kacur exit(EXIT_FAILURE);
774b5f31936SJohn Kacur
775b5f31936SJohn Kacur exit(EXIT_SUCCESS);
7761eeb6328SDaniel Bristot de Oliveira }
7771eeb6328SDaniel Bristot de Oliveira
7781eeb6328SDaniel Bristot de Oliveira /*
7791eeb6328SDaniel Bristot de Oliveira * timerlat_hist_parse_args - allocs, parse and fill the cmd line parameters
7801eeb6328SDaniel Bristot de Oliveira */
7816fa5e3a8STomas Glozar static struct timerlat_params
timerlat_hist_parse_args(int argc,char * argv[])7821eeb6328SDaniel Bristot de Oliveira *timerlat_hist_parse_args(int argc, char *argv[])
7831eeb6328SDaniel Bristot de Oliveira {
7846fa5e3a8STomas Glozar struct timerlat_params *params;
78551d64c3aSDaniel Bristot de Oliveira struct trace_events *tevent;
786173a3b01SDaniel Bristot de Oliveira int auto_thresh;
7871eeb6328SDaniel Bristot de Oliveira int retval;
7881eeb6328SDaniel Bristot de Oliveira int c;
7891eeb6328SDaniel Bristot de Oliveira
7901eeb6328SDaniel Bristot de Oliveira params = calloc(1, sizeof(*params));
7911eeb6328SDaniel Bristot de Oliveira if (!params)
7921eeb6328SDaniel Bristot de Oliveira exit(1);
7931eeb6328SDaniel Bristot de Oliveira
7947d0dc957SDaniel Bristot de Oliveira /* disabled by default */
7957d0dc957SDaniel Bristot de Oliveira params->dma_latency = -1;
7967d0dc957SDaniel Bristot de Oliveira
797cfbfbfc9STomas Glozar /* disabled by default */
798cfbfbfc9STomas Glozar params->deepest_idle_state = -2;
799cfbfbfc9STomas Glozar
8001eeb6328SDaniel Bristot de Oliveira /* display data in microseconds */
8011eeb6328SDaniel Bristot de Oliveira params->output_divisor = 1000;
8021eeb6328SDaniel Bristot de Oliveira params->bucket_size = 1;
8031eeb6328SDaniel Bristot de Oliveira params->entries = 256;
8041eeb6328SDaniel Bristot de Oliveira
8051eeb6328SDaniel Bristot de Oliveira while (1) {
8061eeb6328SDaniel Bristot de Oliveira static struct option long_options[] = {
807173a3b01SDaniel Bristot de Oliveira {"auto", required_argument, 0, 'a'},
8081eeb6328SDaniel Bristot de Oliveira {"cpus", required_argument, 0, 'c'},
809a957cbc0SDaniel Bristot de Oliveira {"cgroup", optional_argument, 0, 'C'},
8101eeb6328SDaniel Bristot de Oliveira {"bucket-size", required_argument, 0, 'b'},
8111eeb6328SDaniel Bristot de Oliveira {"debug", no_argument, 0, 'D'},
812dd48f316SDaniel Bristot de Oliveira {"entries", required_argument, 0, 'E'},
8131eeb6328SDaniel Bristot de Oliveira {"duration", required_argument, 0, 'd'},
814272ced25SDaniel Bristot de Oliveira {"house-keeping", required_argument, 0, 'H'},
8151eeb6328SDaniel Bristot de Oliveira {"help", no_argument, 0, 'h'},
8161eeb6328SDaniel Bristot de Oliveira {"irq", required_argument, 0, 'i'},
8171eeb6328SDaniel Bristot de Oliveira {"nano", no_argument, 0, 'n'},
8181eeb6328SDaniel Bristot de Oliveira {"period", required_argument, 0, 'p'},
8191eeb6328SDaniel Bristot de Oliveira {"priority", required_argument, 0, 'P'},
8201eeb6328SDaniel Bristot de Oliveira {"stack", required_argument, 0, 's'},
8211eeb6328SDaniel Bristot de Oliveira {"thread", required_argument, 0, 'T'},
8221eeb6328SDaniel Bristot de Oliveira {"trace", optional_argument, 0, 't'},
823ed774f74SDaniel Bristot de Oliveira {"user-threads", no_argument, 0, 'u'},
824fb9e90a6SDaniel Bristot de Oliveira {"kernel-threads", no_argument, 0, 'k'},
825a23c05fdSDaniel Bristot de Oliveira {"user-load", no_argument, 0, 'U'},
82651d64c3aSDaniel Bristot de Oliveira {"event", required_argument, 0, 'e'},
8271eeb6328SDaniel Bristot de Oliveira {"no-irq", no_argument, 0, '0'},
8281eeb6328SDaniel Bristot de Oliveira {"no-thread", no_argument, 0, '1'},
8291eeb6328SDaniel Bristot de Oliveira {"no-header", no_argument, 0, '2'},
8301eeb6328SDaniel Bristot de Oliveira {"no-summary", no_argument, 0, '3'},
8311eeb6328SDaniel Bristot de Oliveira {"no-index", no_argument, 0, '4'},
8321eeb6328SDaniel Bristot de Oliveira {"with-zeros", no_argument, 0, '5'},
8331a754893SDaniel Bristot de Oliveira {"trigger", required_argument, 0, '6'},
83444f3a37dSDaniel Bristot de Oliveira {"filter", required_argument, 0, '7'},
8357d0dc957SDaniel Bristot de Oliveira {"dma-latency", required_argument, 0, '8'},
8362091336bSDaniel Bristot de Oliveira {"no-aa", no_argument, 0, '9'},
8372091336bSDaniel Bristot de Oliveira {"dump-task", no_argument, 0, '\1'},
838cdbf7196SDaniel Bristot de Oliveira {"warm-up", required_argument, 0, '\2'},
839e9a4062eSDaniel Bristot de Oliveira {"trace-buffer-size", required_argument, 0, '\3'},
840cfbfbfc9STomas Glozar {"deepest-idle-state", required_argument, 0, '\4'},
8411eeb6328SDaniel Bristot de Oliveira {0, 0, 0, 0}
8421eeb6328SDaniel Bristot de Oliveira };
8431eeb6328SDaniel Bristot de Oliveira
8441eeb6328SDaniel Bristot de Oliveira /* getopt_long stores the option index here. */
8451eeb6328SDaniel Bristot de Oliveira int option_index = 0;
8461eeb6328SDaniel Bristot de Oliveira
847cfb1ea21SGabriele Monaco c = getopt_long(argc, argv, "a:c:C::b:d:e:E:DhH:i:knp:P:s:t::T:uU0123456:7:8:9\1\2:\3:",
8481eeb6328SDaniel Bristot de Oliveira long_options, &option_index);
8491eeb6328SDaniel Bristot de Oliveira
8501eeb6328SDaniel Bristot de Oliveira /* detect the end of the options. */
8511eeb6328SDaniel Bristot de Oliveira if (c == -1)
8521eeb6328SDaniel Bristot de Oliveira break;
8531eeb6328SDaniel Bristot de Oliveira
8541eeb6328SDaniel Bristot de Oliveira switch (c) {
855173a3b01SDaniel Bristot de Oliveira case 'a':
856173a3b01SDaniel Bristot de Oliveira auto_thresh = get_llong_from_str(optarg);
857173a3b01SDaniel Bristot de Oliveira
858173a3b01SDaniel Bristot de Oliveira /* set thread stop to auto_thresh */
859173a3b01SDaniel Bristot de Oliveira params->stop_total_us = auto_thresh;
8602091336bSDaniel Bristot de Oliveira params->stop_us = auto_thresh;
861173a3b01SDaniel Bristot de Oliveira
862173a3b01SDaniel Bristot de Oliveira /* get stack trace */
863173a3b01SDaniel Bristot de Oliveira params->print_stack = auto_thresh;
864173a3b01SDaniel Bristot de Oliveira
865173a3b01SDaniel Bristot de Oliveira /* set trace */
866173a3b01SDaniel Bristot de Oliveira params->trace_output = "timerlat_trace.txt";
867173a3b01SDaniel Bristot de Oliveira
868173a3b01SDaniel Bristot de Oliveira break;
8691eeb6328SDaniel Bristot de Oliveira case 'c':
870894c29c7SDaniel Bristot de Oliveira retval = parse_cpu_set(optarg, ¶ms->monitored_cpus);
8711eeb6328SDaniel Bristot de Oliveira if (retval)
8721eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage("\nInvalid -c cpu list\n");
8731eeb6328SDaniel Bristot de Oliveira params->cpus = optarg;
8741eeb6328SDaniel Bristot de Oliveira break;
875a957cbc0SDaniel Bristot de Oliveira case 'C':
876a957cbc0SDaniel Bristot de Oliveira params->cgroup = 1;
877a957cbc0SDaniel Bristot de Oliveira if (!optarg) {
878a957cbc0SDaniel Bristot de Oliveira /* will inherit this cgroup */
879a957cbc0SDaniel Bristot de Oliveira params->cgroup_name = NULL;
880a957cbc0SDaniel Bristot de Oliveira } else if (*optarg == '=') {
881a957cbc0SDaniel Bristot de Oliveira /* skip the = */
882a957cbc0SDaniel Bristot de Oliveira params->cgroup_name = ++optarg;
883a957cbc0SDaniel Bristot de Oliveira }
884a957cbc0SDaniel Bristot de Oliveira break;
8851eeb6328SDaniel Bristot de Oliveira case 'b':
8861eeb6328SDaniel Bristot de Oliveira params->bucket_size = get_llong_from_str(optarg);
8871eeb6328SDaniel Bristot de Oliveira if ((params->bucket_size == 0) || (params->bucket_size >= 1000000))
8881eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage("Bucket size needs to be > 0 and <= 1000000\n");
8891eeb6328SDaniel Bristot de Oliveira break;
8901eeb6328SDaniel Bristot de Oliveira case 'D':
8911eeb6328SDaniel Bristot de Oliveira config_debug = 1;
8921eeb6328SDaniel Bristot de Oliveira break;
8931eeb6328SDaniel Bristot de Oliveira case 'd':
8941eeb6328SDaniel Bristot de Oliveira params->duration = parse_seconds_duration(optarg);
8951eeb6328SDaniel Bristot de Oliveira if (!params->duration)
8961eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage("Invalid -D duration\n");
8971eeb6328SDaniel Bristot de Oliveira break;
89851d64c3aSDaniel Bristot de Oliveira case 'e':
89951d64c3aSDaniel Bristot de Oliveira tevent = trace_event_alloc(optarg);
90051d64c3aSDaniel Bristot de Oliveira if (!tevent) {
90151d64c3aSDaniel Bristot de Oliveira err_msg("Error alloc trace event");
90251d64c3aSDaniel Bristot de Oliveira exit(EXIT_FAILURE);
90351d64c3aSDaniel Bristot de Oliveira }
90451d64c3aSDaniel Bristot de Oliveira
90551d64c3aSDaniel Bristot de Oliveira if (params->events)
90651d64c3aSDaniel Bristot de Oliveira tevent->next = params->events;
90751d64c3aSDaniel Bristot de Oliveira
90851d64c3aSDaniel Bristot de Oliveira params->events = tevent;
90951d64c3aSDaniel Bristot de Oliveira break;
910dd48f316SDaniel Bristot de Oliveira case 'E':
9111eeb6328SDaniel Bristot de Oliveira params->entries = get_llong_from_str(optarg);
9121eeb6328SDaniel Bristot de Oliveira if ((params->entries < 10) || (params->entries > 9999999))
9131eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage("Entries must be > 10 and < 9999999\n");
9141eeb6328SDaniel Bristot de Oliveira break;
9151eeb6328SDaniel Bristot de Oliveira case 'h':
9161eeb6328SDaniel Bristot de Oliveira case '?':
9171eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage(NULL);
9181eeb6328SDaniel Bristot de Oliveira break;
919272ced25SDaniel Bristot de Oliveira case 'H':
920272ced25SDaniel Bristot de Oliveira params->hk_cpus = 1;
921272ced25SDaniel Bristot de Oliveira retval = parse_cpu_set(optarg, ¶ms->hk_cpu_set);
922272ced25SDaniel Bristot de Oliveira if (retval) {
923272ced25SDaniel Bristot de Oliveira err_msg("Error parsing house keeping CPUs\n");
924272ced25SDaniel Bristot de Oliveira exit(EXIT_FAILURE);
925272ced25SDaniel Bristot de Oliveira }
926272ced25SDaniel Bristot de Oliveira break;
9271eeb6328SDaniel Bristot de Oliveira case 'i':
9281eeb6328SDaniel Bristot de Oliveira params->stop_us = get_llong_from_str(optarg);
9291eeb6328SDaniel Bristot de Oliveira break;
930fb9e90a6SDaniel Bristot de Oliveira case 'k':
931fb9e90a6SDaniel Bristot de Oliveira params->kernel_workload = 1;
932fb9e90a6SDaniel Bristot de Oliveira break;
9331eeb6328SDaniel Bristot de Oliveira case 'n':
9341eeb6328SDaniel Bristot de Oliveira params->output_divisor = 1;
9351eeb6328SDaniel Bristot de Oliveira break;
9361eeb6328SDaniel Bristot de Oliveira case 'p':
9371eeb6328SDaniel Bristot de Oliveira params->timerlat_period_us = get_llong_from_str(optarg);
9381eeb6328SDaniel Bristot de Oliveira if (params->timerlat_period_us > 1000000)
9391eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage("Period longer than 1 s\n");
9401eeb6328SDaniel Bristot de Oliveira break;
9411eeb6328SDaniel Bristot de Oliveira case 'P':
9421eeb6328SDaniel Bristot de Oliveira retval = parse_prio(optarg, ¶ms->sched_param);
9431eeb6328SDaniel Bristot de Oliveira if (retval == -1)
9441eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage("Invalid -P priority");
9451eeb6328SDaniel Bristot de Oliveira params->set_sched = 1;
9461eeb6328SDaniel Bristot de Oliveira break;
9471eeb6328SDaniel Bristot de Oliveira case 's':
9481eeb6328SDaniel Bristot de Oliveira params->print_stack = get_llong_from_str(optarg);
9491eeb6328SDaniel Bristot de Oliveira break;
9501eeb6328SDaniel Bristot de Oliveira case 'T':
9511eeb6328SDaniel Bristot de Oliveira params->stop_total_us = get_llong_from_str(optarg);
9521eeb6328SDaniel Bristot de Oliveira break;
9531eeb6328SDaniel Bristot de Oliveira case 't':
954842fc5b8SJohn Kacur if (optarg) {
955842fc5b8SJohn Kacur if (optarg[0] == '=')
9561eeb6328SDaniel Bristot de Oliveira params->trace_output = &optarg[1];
9571eeb6328SDaniel Bristot de Oliveira else
958842fc5b8SJohn Kacur params->trace_output = &optarg[0];
959842fc5b8SJohn Kacur } else if (optind < argc && argv[optind][0] != '-')
960842fc5b8SJohn Kacur params->trace_output = argv[optind];
961842fc5b8SJohn Kacur else
9621eeb6328SDaniel Bristot de Oliveira params->trace_output = "timerlat_trace.txt";
9631eeb6328SDaniel Bristot de Oliveira break;
964ed774f74SDaniel Bristot de Oliveira case 'u':
965a23c05fdSDaniel Bristot de Oliveira params->user_workload = 1;
966a23c05fdSDaniel Bristot de Oliveira /* fallback: -u implies in -U */
967a23c05fdSDaniel Bristot de Oliveira case 'U':
968*20d6b075STomas Glozar params->user_data = 1;
969ed774f74SDaniel Bristot de Oliveira break;
9701eeb6328SDaniel Bristot de Oliveira case '0': /* no irq */
9711eeb6328SDaniel Bristot de Oliveira params->no_irq = 1;
9721eeb6328SDaniel Bristot de Oliveira break;
9731eeb6328SDaniel Bristot de Oliveira case '1': /* no thread */
9741eeb6328SDaniel Bristot de Oliveira params->no_thread = 1;
9751eeb6328SDaniel Bristot de Oliveira break;
9761eeb6328SDaniel Bristot de Oliveira case '2': /* no header */
9771eeb6328SDaniel Bristot de Oliveira params->no_header = 1;
9781eeb6328SDaniel Bristot de Oliveira break;
9791eeb6328SDaniel Bristot de Oliveira case '3': /* no summary */
9801eeb6328SDaniel Bristot de Oliveira params->no_summary = 1;
9811eeb6328SDaniel Bristot de Oliveira break;
9821eeb6328SDaniel Bristot de Oliveira case '4': /* no index */
9831eeb6328SDaniel Bristot de Oliveira params->no_index = 1;
9841eeb6328SDaniel Bristot de Oliveira break;
9851eeb6328SDaniel Bristot de Oliveira case '5': /* with zeros */
9861eeb6328SDaniel Bristot de Oliveira params->with_zeros = 1;
9871eeb6328SDaniel Bristot de Oliveira break;
9881a754893SDaniel Bristot de Oliveira case '6': /* trigger */
9891a754893SDaniel Bristot de Oliveira if (params->events) {
9901a754893SDaniel Bristot de Oliveira retval = trace_event_add_trigger(params->events, optarg);
9911a754893SDaniel Bristot de Oliveira if (retval) {
9921a754893SDaniel Bristot de Oliveira err_msg("Error adding trigger %s\n", optarg);
9931a754893SDaniel Bristot de Oliveira exit(EXIT_FAILURE);
9941a754893SDaniel Bristot de Oliveira }
9951a754893SDaniel Bristot de Oliveira } else {
9961a754893SDaniel Bristot de Oliveira timerlat_hist_usage("--trigger requires a previous -e\n");
9971a754893SDaniel Bristot de Oliveira }
9981a754893SDaniel Bristot de Oliveira break;
99944f3a37dSDaniel Bristot de Oliveira case '7': /* filter */
100044f3a37dSDaniel Bristot de Oliveira if (params->events) {
100144f3a37dSDaniel Bristot de Oliveira retval = trace_event_add_filter(params->events, optarg);
100244f3a37dSDaniel Bristot de Oliveira if (retval) {
100344f3a37dSDaniel Bristot de Oliveira err_msg("Error adding filter %s\n", optarg);
100444f3a37dSDaniel Bristot de Oliveira exit(EXIT_FAILURE);
100544f3a37dSDaniel Bristot de Oliveira }
100644f3a37dSDaniel Bristot de Oliveira } else {
100744f3a37dSDaniel Bristot de Oliveira timerlat_hist_usage("--filter requires a previous -e\n");
100844f3a37dSDaniel Bristot de Oliveira }
100944f3a37dSDaniel Bristot de Oliveira break;
10107d0dc957SDaniel Bristot de Oliveira case '8':
10117d0dc957SDaniel Bristot de Oliveira params->dma_latency = get_llong_from_str(optarg);
10127d0dc957SDaniel Bristot de Oliveira if (params->dma_latency < 0 || params->dma_latency > 10000) {
10137d0dc957SDaniel Bristot de Oliveira err_msg("--dma-latency needs to be >= 0 and < 10000");
10147d0dc957SDaniel Bristot de Oliveira exit(EXIT_FAILURE);
10157d0dc957SDaniel Bristot de Oliveira }
10167d0dc957SDaniel Bristot de Oliveira break;
10172091336bSDaniel Bristot de Oliveira case '9':
10182091336bSDaniel Bristot de Oliveira params->no_aa = 1;
10192091336bSDaniel Bristot de Oliveira break;
10202091336bSDaniel Bristot de Oliveira case '\1':
10212091336bSDaniel Bristot de Oliveira params->dump_tasks = 1;
10222091336bSDaniel Bristot de Oliveira break;
1023cdbf7196SDaniel Bristot de Oliveira case '\2':
1024cdbf7196SDaniel Bristot de Oliveira params->warmup = get_llong_from_str(optarg);
1025cdbf7196SDaniel Bristot de Oliveira break;
1026e9a4062eSDaniel Bristot de Oliveira case '\3':
1027e9a4062eSDaniel Bristot de Oliveira params->buffer_size = get_llong_from_str(optarg);
1028e9a4062eSDaniel Bristot de Oliveira break;
1029cfbfbfc9STomas Glozar case '\4':
1030cfbfbfc9STomas Glozar params->deepest_idle_state = get_llong_from_str(optarg);
1031cfbfbfc9STomas Glozar break;
10321eeb6328SDaniel Bristot de Oliveira default:
10331eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage("Invalid option");
10341eeb6328SDaniel Bristot de Oliveira }
10351eeb6328SDaniel Bristot de Oliveira }
10361eeb6328SDaniel Bristot de Oliveira
10371eeb6328SDaniel Bristot de Oliveira if (geteuid()) {
10381eeb6328SDaniel Bristot de Oliveira err_msg("rtla needs root permission\n");
10391eeb6328SDaniel Bristot de Oliveira exit(EXIT_FAILURE);
10401eeb6328SDaniel Bristot de Oliveira }
10411eeb6328SDaniel Bristot de Oliveira
10421eeb6328SDaniel Bristot de Oliveira if (params->no_irq && params->no_thread)
10431eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage("no-irq and no-thread set, there is nothing to do here");
10441eeb6328SDaniel Bristot de Oliveira
10451eeb6328SDaniel Bristot de Oliveira if (params->no_index && !params->with_zeros)
10461eeb6328SDaniel Bristot de Oliveira timerlat_hist_usage("no-index set with with-zeros is not set - it does not make sense");
10471eeb6328SDaniel Bristot de Oliveira
10482091336bSDaniel Bristot de Oliveira /*
10492091336bSDaniel Bristot de Oliveira * Auto analysis only happens if stop tracing, thus:
10502091336bSDaniel Bristot de Oliveira */
10512091336bSDaniel Bristot de Oliveira if (!params->stop_us && !params->stop_total_us)
10522091336bSDaniel Bristot de Oliveira params->no_aa = 1;
10532091336bSDaniel Bristot de Oliveira
1054fb9e90a6SDaniel Bristot de Oliveira if (params->kernel_workload && params->user_workload)
1055fb9e90a6SDaniel Bristot de Oliveira timerlat_hist_usage("--kernel-threads and --user-threads are mutually exclusive!");
1056fb9e90a6SDaniel Bristot de Oliveira
10571eeb6328SDaniel Bristot de Oliveira return params;
10581eeb6328SDaniel Bristot de Oliveira }
10591eeb6328SDaniel Bristot de Oliveira
10601eeb6328SDaniel Bristot de Oliveira /*
10611eeb6328SDaniel Bristot de Oliveira * timerlat_hist_apply_config - apply the hist configs to the initialized tool
10621eeb6328SDaniel Bristot de Oliveira */
10631eeb6328SDaniel Bristot de Oliveira static int
timerlat_hist_apply_config(struct osnoise_tool * tool,struct timerlat_params * params)10646fa5e3a8STomas Glozar timerlat_hist_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
10651eeb6328SDaniel Bristot de Oliveira {
1066*20d6b075STomas Glozar int retval;
10671eeb6328SDaniel Bristot de Oliveira
1068*20d6b075STomas Glozar retval = timerlat_apply_config(tool, params);
1069*20d6b075STomas Glozar if (retval)
10701eeb6328SDaniel Bristot de Oliveira goto out_err;
1071ed774f74SDaniel Bristot de Oliveira
10721eeb6328SDaniel Bristot de Oliveira return 0;
10731eeb6328SDaniel Bristot de Oliveira
10741eeb6328SDaniel Bristot de Oliveira out_err:
10751eeb6328SDaniel Bristot de Oliveira return -1;
10761eeb6328SDaniel Bristot de Oliveira }
10771eeb6328SDaniel Bristot de Oliveira
10781eeb6328SDaniel Bristot de Oliveira /*
10791eeb6328SDaniel Bristot de Oliveira * timerlat_init_hist - initialize a timerlat hist tool with parameters
10801eeb6328SDaniel Bristot de Oliveira */
10811eeb6328SDaniel Bristot de Oliveira static struct osnoise_tool
timerlat_init_hist(struct timerlat_params * params)10826fa5e3a8STomas Glozar *timerlat_init_hist(struct timerlat_params *params)
10831eeb6328SDaniel Bristot de Oliveira {
10841eeb6328SDaniel Bristot de Oliveira struct osnoise_tool *tool;
10851eeb6328SDaniel Bristot de Oliveira int nr_cpus;
10861eeb6328SDaniel Bristot de Oliveira
10871eeb6328SDaniel Bristot de Oliveira nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
10881eeb6328SDaniel Bristot de Oliveira
10891eeb6328SDaniel Bristot de Oliveira tool = osnoise_init_tool("timerlat_hist");
10901eeb6328SDaniel Bristot de Oliveira if (!tool)
10911eeb6328SDaniel Bristot de Oliveira return NULL;
10921eeb6328SDaniel Bristot de Oliveira
10931eeb6328SDaniel Bristot de Oliveira tool->data = timerlat_alloc_histogram(nr_cpus, params->entries, params->bucket_size);
10941eeb6328SDaniel Bristot de Oliveira if (!tool->data)
10951eeb6328SDaniel Bristot de Oliveira goto out_err;
10961eeb6328SDaniel Bristot de Oliveira
10971eeb6328SDaniel Bristot de Oliveira tool->params = params;
10981eeb6328SDaniel Bristot de Oliveira
10991eeb6328SDaniel Bristot de Oliveira tep_register_event_handler(tool->trace.tep, -1, "ftrace", "timerlat",
11001eeb6328SDaniel Bristot de Oliveira timerlat_hist_handler, tool);
11011eeb6328SDaniel Bristot de Oliveira
11021eeb6328SDaniel Bristot de Oliveira return tool;
11031eeb6328SDaniel Bristot de Oliveira
11041eeb6328SDaniel Bristot de Oliveira out_err:
11051eeb6328SDaniel Bristot de Oliveira osnoise_destroy_tool(tool);
11061eeb6328SDaniel Bristot de Oliveira return NULL;
11071eeb6328SDaniel Bristot de Oliveira }
11081eeb6328SDaniel Bristot de Oliveira
11091eeb6328SDaniel Bristot de Oliveira static int stop_tracing;
1110c73cab9dSTomas Glozar static struct trace_instance *hist_inst = NULL;
stop_hist(int sig)11111eeb6328SDaniel Bristot de Oliveira static void stop_hist(int sig)
11121eeb6328SDaniel Bristot de Oliveira {
1113d6899e56STomas Glozar if (stop_tracing) {
1114d6899e56STomas Glozar /*
1115d6899e56STomas Glozar * Stop requested twice in a row; abort event processing and
1116d6899e56STomas Glozar * exit immediately
1117d6899e56STomas Glozar */
1118d6899e56STomas Glozar tracefs_iterate_stop(hist_inst->inst);
1119d6899e56STomas Glozar return;
1120d6899e56STomas Glozar }
11211eeb6328SDaniel Bristot de Oliveira stop_tracing = 1;
1122c73cab9dSTomas Glozar if (hist_inst)
1123c73cab9dSTomas Glozar trace_instance_stop(hist_inst);
11241eeb6328SDaniel Bristot de Oliveira }
11251eeb6328SDaniel Bristot de Oliveira
11261eeb6328SDaniel Bristot de Oliveira /*
11271eeb6328SDaniel Bristot de Oliveira * timerlat_hist_set_signals - handles the signal to stop the tool
11281eeb6328SDaniel Bristot de Oliveira */
11291eeb6328SDaniel Bristot de Oliveira static void
timerlat_hist_set_signals(struct timerlat_params * params)11306fa5e3a8STomas Glozar timerlat_hist_set_signals(struct timerlat_params *params)
11311eeb6328SDaniel Bristot de Oliveira {
11321eeb6328SDaniel Bristot de Oliveira signal(SIGINT, stop_hist);
11331eeb6328SDaniel Bristot de Oliveira if (params->duration) {
11341eeb6328SDaniel Bristot de Oliveira signal(SIGALRM, stop_hist);
11351eeb6328SDaniel Bristot de Oliveira alarm(params->duration);
11361eeb6328SDaniel Bristot de Oliveira }
11371eeb6328SDaniel Bristot de Oliveira }
11381eeb6328SDaniel Bristot de Oliveira
timerlat_hist_main(int argc,char * argv[])11391eeb6328SDaniel Bristot de Oliveira int timerlat_hist_main(int argc, char *argv[])
11401eeb6328SDaniel Bristot de Oliveira {
11416fa5e3a8STomas Glozar struct timerlat_params *params;
11424bbf59a9SDaniel Bristot de Oliveira struct osnoise_tool *record = NULL;
1143ed774f74SDaniel Bristot de Oliveira struct timerlat_u_params params_u;
11444bbf59a9SDaniel Bristot de Oliveira struct osnoise_tool *tool = NULL;
11452091336bSDaniel Bristot de Oliveira struct osnoise_tool *aa = NULL;
11461eeb6328SDaniel Bristot de Oliveira struct trace_instance *trace;
11477d0dc957SDaniel Bristot de Oliveira int dma_latency_fd = -1;
11481eeb6328SDaniel Bristot de Oliveira int return_value = 1;
1149ed774f74SDaniel Bristot de Oliveira pthread_t timerlat_u;
11501eeb6328SDaniel Bristot de Oliveira int retval;
1151cfbfbfc9STomas Glozar int nr_cpus, i;
1152fd7925cbSTomas Glozar bool no_bpf = false;
11531eeb6328SDaniel Bristot de Oliveira
11541eeb6328SDaniel Bristot de Oliveira params = timerlat_hist_parse_args(argc, argv);
11551eeb6328SDaniel Bristot de Oliveira if (!params)
11561eeb6328SDaniel Bristot de Oliveira exit(1);
11571eeb6328SDaniel Bristot de Oliveira
11581eeb6328SDaniel Bristot de Oliveira tool = timerlat_init_hist(params);
11591eeb6328SDaniel Bristot de Oliveira if (!tool) {
11601eeb6328SDaniel Bristot de Oliveira err_msg("Could not init osnoise hist\n");
11611eeb6328SDaniel Bristot de Oliveira goto out_exit;
11621eeb6328SDaniel Bristot de Oliveira }
11631eeb6328SDaniel Bristot de Oliveira
11641eeb6328SDaniel Bristot de Oliveira retval = timerlat_hist_apply_config(tool, params);
11651eeb6328SDaniel Bristot de Oliveira if (retval) {
11661eeb6328SDaniel Bristot de Oliveira err_msg("Could not apply config\n");
11672a6b52edSWan Jiabing goto out_free;
11681eeb6328SDaniel Bristot de Oliveira }
11691eeb6328SDaniel Bristot de Oliveira
11701eeb6328SDaniel Bristot de Oliveira trace = &tool->trace;
1171c73cab9dSTomas Glozar /*
1172c73cab9dSTomas Glozar * Save trace instance into global variable so that SIGINT can stop
1173c73cab9dSTomas Glozar * the timerlat tracer.
1174c73cab9dSTomas Glozar * Otherwise, rtla could loop indefinitely when overloaded.
1175c73cab9dSTomas Glozar */
1176c73cab9dSTomas Glozar hist_inst = trace;
11771eeb6328SDaniel Bristot de Oliveira
1178fd7925cbSTomas Glozar if (getenv("RTLA_NO_BPF") && strncmp(getenv("RTLA_NO_BPF"), "1", 2) == 0) {
1179fd7925cbSTomas Glozar debug_msg("RTLA_NO_BPF set, disabling BPF\n");
1180fd7925cbSTomas Glozar no_bpf = true;
1181fd7925cbSTomas Glozar }
1182fd7925cbSTomas Glozar
1183fd7925cbSTomas Glozar if (!no_bpf && !tep_find_event_by_name(trace->tep, "osnoise", "timerlat_sample")) {
1184fd7925cbSTomas Glozar debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
1185fd7925cbSTomas Glozar no_bpf = true;
1186fd7925cbSTomas Glozar }
1187fd7925cbSTomas Glozar
1188fd7925cbSTomas Glozar if (!no_bpf) {
1189fd7925cbSTomas Glozar retval = timerlat_bpf_init(params);
1190fd7925cbSTomas Glozar if (retval) {
1191fd7925cbSTomas Glozar debug_msg("Could not enable BPF\n");
1192fd7925cbSTomas Glozar no_bpf = true;
1193fd7925cbSTomas Glozar }
1194fd7925cbSTomas Glozar }
1195fd7925cbSTomas Glozar
11961eeb6328SDaniel Bristot de Oliveira retval = enable_timerlat(trace);
11971eeb6328SDaniel Bristot de Oliveira if (retval) {
11981eeb6328SDaniel Bristot de Oliveira err_msg("Failed to enable timerlat tracer\n");
11992a6b52edSWan Jiabing goto out_free;
12001eeb6328SDaniel Bristot de Oliveira }
12011eeb6328SDaniel Bristot de Oliveira
12021eeb6328SDaniel Bristot de Oliveira if (params->set_sched) {
12031eeb6328SDaniel Bristot de Oliveira retval = set_comm_sched_attr("timerlat/", ¶ms->sched_param);
12041eeb6328SDaniel Bristot de Oliveira if (retval) {
12051eeb6328SDaniel Bristot de Oliveira err_msg("Failed to set sched parameters\n");
12062a6b52edSWan Jiabing goto out_free;
12071eeb6328SDaniel Bristot de Oliveira }
12081eeb6328SDaniel Bristot de Oliveira }
12091eeb6328SDaniel Bristot de Oliveira
1210a23c05fdSDaniel Bristot de Oliveira if (params->cgroup && !params->user_workload) {
1211a957cbc0SDaniel Bristot de Oliveira retval = set_comm_cgroup("timerlat/", params->cgroup_name);
1212a957cbc0SDaniel Bristot de Oliveira if (!retval) {
1213a957cbc0SDaniel Bristot de Oliveira err_msg("Failed to move threads to cgroup\n");
1214a957cbc0SDaniel Bristot de Oliveira goto out_free;
1215a957cbc0SDaniel Bristot de Oliveira }
1216a957cbc0SDaniel Bristot de Oliveira }
1217a957cbc0SDaniel Bristot de Oliveira
12187d0dc957SDaniel Bristot de Oliveira if (params->dma_latency >= 0) {
12197d0dc957SDaniel Bristot de Oliveira dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
12207d0dc957SDaniel Bristot de Oliveira if (dma_latency_fd < 0) {
12217d0dc957SDaniel Bristot de Oliveira err_msg("Could not set /dev/cpu_dma_latency.\n");
12222a6b52edSWan Jiabing goto out_free;
12237d0dc957SDaniel Bristot de Oliveira }
12247d0dc957SDaniel Bristot de Oliveira }
12257d0dc957SDaniel Bristot de Oliveira
1226cfbfbfc9STomas Glozar if (params->deepest_idle_state >= -1) {
1227cfbfbfc9STomas Glozar if (!have_libcpupower_support()) {
1228cfbfbfc9STomas Glozar err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
1229cfbfbfc9STomas Glozar goto out_free;
1230cfbfbfc9STomas Glozar }
1231cfbfbfc9STomas Glozar
1232cfbfbfc9STomas Glozar nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
1233cfbfbfc9STomas Glozar
1234cfbfbfc9STomas Glozar for (i = 0; i < nr_cpus; i++) {
1235cfbfbfc9STomas Glozar if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
1236cfbfbfc9STomas Glozar continue;
1237cfbfbfc9STomas Glozar if (save_cpu_idle_disable_state(i) < 0) {
1238cfbfbfc9STomas Glozar err_msg("Could not save cpu idle state.\n");
1239cfbfbfc9STomas Glozar goto out_free;
1240cfbfbfc9STomas Glozar }
1241cfbfbfc9STomas Glozar if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
1242cfbfbfc9STomas Glozar err_msg("Could not set deepest cpu idle state.\n");
1243cfbfbfc9STomas Glozar goto out_free;
1244cfbfbfc9STomas Glozar }
1245cfbfbfc9STomas Glozar }
1246cfbfbfc9STomas Glozar }
1247cfbfbfc9STomas Glozar
12481eeb6328SDaniel Bristot de Oliveira if (params->trace_output) {
12491eeb6328SDaniel Bristot de Oliveira record = osnoise_init_trace_tool("timerlat");
12501eeb6328SDaniel Bristot de Oliveira if (!record) {
12511eeb6328SDaniel Bristot de Oliveira err_msg("Failed to enable the trace instance\n");
12522a6b52edSWan Jiabing goto out_free;
12531eeb6328SDaniel Bristot de Oliveira }
125451d64c3aSDaniel Bristot de Oliveira
125551d64c3aSDaniel Bristot de Oliveira if (params->events) {
125651d64c3aSDaniel Bristot de Oliveira retval = trace_events_enable(&record->trace, params->events);
125751d64c3aSDaniel Bristot de Oliveira if (retval)
125851d64c3aSDaniel Bristot de Oliveira goto out_hist;
125951d64c3aSDaniel Bristot de Oliveira }
1260e9a4062eSDaniel Bristot de Oliveira
1261e9a4062eSDaniel Bristot de Oliveira if (params->buffer_size > 0) {
1262e9a4062eSDaniel Bristot de Oliveira retval = trace_set_buffer_size(&record->trace, params->buffer_size);
1263e9a4062eSDaniel Bristot de Oliveira if (retval)
1264e9a4062eSDaniel Bristot de Oliveira goto out_hist;
1265e9a4062eSDaniel Bristot de Oliveira }
12661eeb6328SDaniel Bristot de Oliveira }
12671eeb6328SDaniel Bristot de Oliveira
12682091336bSDaniel Bristot de Oliveira if (!params->no_aa) {
12692091336bSDaniel Bristot de Oliveira aa = osnoise_init_tool("timerlat_aa");
12702091336bSDaniel Bristot de Oliveira if (!aa)
12712091336bSDaniel Bristot de Oliveira goto out_hist;
12722091336bSDaniel Bristot de Oliveira
12732091336bSDaniel Bristot de Oliveira retval = timerlat_aa_init(aa, params->dump_tasks);
12742091336bSDaniel Bristot de Oliveira if (retval) {
12752091336bSDaniel Bristot de Oliveira err_msg("Failed to enable the auto analysis instance\n");
12762091336bSDaniel Bristot de Oliveira goto out_hist;
12772091336bSDaniel Bristot de Oliveira }
12782091336bSDaniel Bristot de Oliveira
12792091336bSDaniel Bristot de Oliveira retval = enable_timerlat(&aa->trace);
12802091336bSDaniel Bristot de Oliveira if (retval) {
12812091336bSDaniel Bristot de Oliveira err_msg("Failed to enable timerlat tracer\n");
12822091336bSDaniel Bristot de Oliveira goto out_hist;
12832091336bSDaniel Bristot de Oliveira }
12842091336bSDaniel Bristot de Oliveira }
12852091336bSDaniel Bristot de Oliveira
1286a23c05fdSDaniel Bristot de Oliveira if (params->user_workload) {
1287ed774f74SDaniel Bristot de Oliveira /* rtla asked to stop */
1288ed774f74SDaniel Bristot de Oliveira params_u.should_run = 1;
1289ed774f74SDaniel Bristot de Oliveira /* all threads left */
1290ed774f74SDaniel Bristot de Oliveira params_u.stopped_running = 0;
1291ed774f74SDaniel Bristot de Oliveira
1292ed774f74SDaniel Bristot de Oliveira params_u.set = ¶ms->monitored_cpus;
1293ed774f74SDaniel Bristot de Oliveira if (params->set_sched)
1294ed774f74SDaniel Bristot de Oliveira params_u.sched_param = ¶ms->sched_param;
1295ed774f74SDaniel Bristot de Oliveira else
1296ed774f74SDaniel Bristot de Oliveira params_u.sched_param = NULL;
1297ed774f74SDaniel Bristot de Oliveira
1298ed774f74SDaniel Bristot de Oliveira params_u.cgroup_name = params->cgroup_name;
1299ed774f74SDaniel Bristot de Oliveira
1300ed774f74SDaniel Bristot de Oliveira retval = pthread_create(&timerlat_u, NULL, timerlat_u_dispatcher, ¶ms_u);
1301ed774f74SDaniel Bristot de Oliveira if (retval)
1302ed774f74SDaniel Bristot de Oliveira err_msg("Error creating timerlat user-space threads\n");
1303ed774f74SDaniel Bristot de Oliveira }
1304ed774f74SDaniel Bristot de Oliveira
1305cdbf7196SDaniel Bristot de Oliveira if (params->warmup > 0) {
1306cdbf7196SDaniel Bristot de Oliveira debug_msg("Warming up for %d seconds\n", params->warmup);
1307cdbf7196SDaniel Bristot de Oliveira sleep(params->warmup);
1308cdbf7196SDaniel Bristot de Oliveira if (stop_tracing)
1309cdbf7196SDaniel Bristot de Oliveira goto out_hist;
1310cdbf7196SDaniel Bristot de Oliveira }
1311cdbf7196SDaniel Bristot de Oliveira
1312cdbf7196SDaniel Bristot de Oliveira /*
1313cdbf7196SDaniel Bristot de Oliveira * Start the tracers here, after having set all instances.
1314cdbf7196SDaniel Bristot de Oliveira *
1315cdbf7196SDaniel Bristot de Oliveira * Let the trace instance start first for the case of hitting a stop
1316cdbf7196SDaniel Bristot de Oliveira * tracing while enabling other instances. The trace instance is the
1317cdbf7196SDaniel Bristot de Oliveira * one with most valuable information.
1318cdbf7196SDaniel Bristot de Oliveira */
1319cdbf7196SDaniel Bristot de Oliveira if (params->trace_output)
1320cdbf7196SDaniel Bristot de Oliveira trace_instance_start(&record->trace);
1321cdbf7196SDaniel Bristot de Oliveira if (!params->no_aa)
1322cdbf7196SDaniel Bristot de Oliveira trace_instance_start(&aa->trace);
1323fd7925cbSTomas Glozar if (no_bpf) {
1324cdbf7196SDaniel Bristot de Oliveira trace_instance_start(trace);
1325fd7925cbSTomas Glozar } else {
1326fd7925cbSTomas Glozar retval = timerlat_bpf_attach();
1327fd7925cbSTomas Glozar if (retval) {
1328fd7925cbSTomas Glozar err_msg("Error attaching BPF program\n");
1329fd7925cbSTomas Glozar goto out_hist;
1330fd7925cbSTomas Glozar }
1331fd7925cbSTomas Glozar }
1332cdbf7196SDaniel Bristot de Oliveira
1333cdbf7196SDaniel Bristot de Oliveira tool->start_time = time(NULL);
1334cdbf7196SDaniel Bristot de Oliveira timerlat_hist_set_signals(params);
1335cdbf7196SDaniel Bristot de Oliveira
1336fd7925cbSTomas Glozar if (no_bpf) {
13371eeb6328SDaniel Bristot de Oliveira while (!stop_tracing) {
13381eeb6328SDaniel Bristot de Oliveira sleep(params->sleep_time);
13391eeb6328SDaniel Bristot de Oliveira
13401eeb6328SDaniel Bristot de Oliveira retval = tracefs_iterate_raw_events(trace->tep,
13411eeb6328SDaniel Bristot de Oliveira trace->inst,
13421eeb6328SDaniel Bristot de Oliveira NULL,
13431eeb6328SDaniel Bristot de Oliveira 0,
13441eeb6328SDaniel Bristot de Oliveira collect_registered_events,
13451eeb6328SDaniel Bristot de Oliveira trace);
13461eeb6328SDaniel Bristot de Oliveira if (retval < 0) {
13471eeb6328SDaniel Bristot de Oliveira err_msg("Error iterating on events\n");
13481eeb6328SDaniel Bristot de Oliveira goto out_hist;
13491eeb6328SDaniel Bristot de Oliveira }
13501eeb6328SDaniel Bristot de Oliveira
1351b91cfd9fSCosta Shulyupin if (osnoise_trace_is_off(tool, record))
13521eeb6328SDaniel Bristot de Oliveira break;
1353ed774f74SDaniel Bristot de Oliveira
1354ed774f74SDaniel Bristot de Oliveira /* is there still any user-threads ? */
1355a23c05fdSDaniel Bristot de Oliveira if (params->user_workload) {
1356ed774f74SDaniel Bristot de Oliveira if (params_u.stopped_running) {
1357ed774f74SDaniel Bristot de Oliveira debug_msg("timerlat user-space threads stopped!\n");
1358ed774f74SDaniel Bristot de Oliveira break;
1359ed774f74SDaniel Bristot de Oliveira }
1360ed774f74SDaniel Bristot de Oliveira }
1361ed774f74SDaniel Bristot de Oliveira }
1362fd7925cbSTomas Glozar } else
1363fd7925cbSTomas Glozar timerlat_bpf_wait(-1);
1364fd7925cbSTomas Glozar
1365fd7925cbSTomas Glozar if (!no_bpf) {
1366fd7925cbSTomas Glozar timerlat_bpf_detach();
1367fd7925cbSTomas Glozar retval = timerlat_hist_bpf_pull_data(tool);
1368fd7925cbSTomas Glozar if (retval) {
1369fd7925cbSTomas Glozar err_msg("Error pulling BPF data\n");
1370fd7925cbSTomas Glozar goto out_hist;
1371fd7925cbSTomas Glozar }
1372fd7925cbSTomas Glozar }
1373cdbf7196SDaniel Bristot de Oliveira
1374a23c05fdSDaniel Bristot de Oliveira if (params->user_workload && !params_u.stopped_running) {
1375ed774f74SDaniel Bristot de Oliveira params_u.should_run = 0;
1376ed774f74SDaniel Bristot de Oliveira sleep(1);
137775016ca3SDaniel Bristot de Oliveira }
13781eeb6328SDaniel Bristot de Oliveira
13791eeb6328SDaniel Bristot de Oliveira timerlat_print_stats(params, tool);
13801eeb6328SDaniel Bristot de Oliveira
13811eeb6328SDaniel Bristot de Oliveira return_value = 0;
13821eeb6328SDaniel Bristot de Oliveira
1383b91cfd9fSCosta Shulyupin if (osnoise_trace_is_off(tool, record) && !stop_tracing) {
1384f1432cd2SAlexandre Vicenzi printf("rtla timerlat hit stop tracing\n");
13852091336bSDaniel Bristot de Oliveira
13862091336bSDaniel Bristot de Oliveira if (!params->no_aa)
13872091336bSDaniel Bristot de Oliveira timerlat_auto_analysis(params->stop_us, params->stop_total_us);
13882091336bSDaniel Bristot de Oliveira
1389c57c58a6STomas Glozar save_trace_to_file(record ? record->trace.inst : NULL,
1390c57c58a6STomas Glozar params->trace_output);
13911eeb6328SDaniel Bristot de Oliveira }
13921eeb6328SDaniel Bristot de Oliveira
13931eeb6328SDaniel Bristot de Oliveira out_hist:
13942091336bSDaniel Bristot de Oliveira timerlat_aa_destroy();
13957d0dc957SDaniel Bristot de Oliveira if (dma_latency_fd >= 0)
13967d0dc957SDaniel Bristot de Oliveira close(dma_latency_fd);
1397cfbfbfc9STomas Glozar if (params->deepest_idle_state >= -1) {
1398cfbfbfc9STomas Glozar for (i = 0; i < nr_cpus; i++) {
1399cfbfbfc9STomas Glozar if (params->cpus && !CPU_ISSET(i, ¶ms->monitored_cpus))
1400cfbfbfc9STomas Glozar continue;
1401cfbfbfc9STomas Glozar restore_cpu_idle_disable_state(i);
1402cfbfbfc9STomas Glozar }
1403cfbfbfc9STomas Glozar }
140451d64c3aSDaniel Bristot de Oliveira trace_events_destroy(&record->trace, params->events);
140551d64c3aSDaniel Bristot de Oliveira params->events = NULL;
14062a6b52edSWan Jiabing out_free:
14071eeb6328SDaniel Bristot de Oliveira timerlat_free_histogram(tool->data);
14082091336bSDaniel Bristot de Oliveira osnoise_destroy_tool(aa);
14091eeb6328SDaniel Bristot de Oliveira osnoise_destroy_tool(record);
14104bbf59a9SDaniel Bristot de Oliveira osnoise_destroy_tool(tool);
14111eeb6328SDaniel Bristot de Oliveira free(params);
1412cfbfbfc9STomas Glozar free_cpu_idle_disable_states();
1413fd7925cbSTomas Glozar if (!no_bpf)
1414fd7925cbSTomas Glozar timerlat_bpf_destroy();
14151eeb6328SDaniel Bristot de Oliveira out_exit:
14161eeb6328SDaniel Bristot de Oliveira exit(return_value);
14171eeb6328SDaniel Bristot de Oliveira }
1418