xref: /linux/tools/tracing/rtla/src/cli_p.h (revision deaec85cd8bad3841412ff8cefec463f2688806b)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #pragma once
3 
4 #ifndef RTLA_ALLOW_CLI_P_H
5 #error "Private header file included outside of cli.c module"
6 #endif
7 
8 #include <linux/kernel.h>
9 #include <subcmd/parse-options.h>
10 
11 #include "cli.h"
12 #include "osnoise.h"
13 #include "timerlat.h"
14 
15 struct osnoise_cb_data {
16 	struct osnoise_params *params;
17 	char *trace_output;
18 };
19 
20 struct timerlat_cb_data {
21 	struct timerlat_params *params;
22 	char *trace_output;
23 };
24 
25 /*
26  * Non-zero default values for parameters
27  */
28 static const int default_dma_latency = -1; /* -1 = unset */
29 static const int default_deepest_idle_state = -2; /* -1 = disable all, -2 = unset */
30 static const int default_output_divisor = 1000;
31 static const int default_bucket_size = 1;
32 static const int default_entries = 256;
33 static const enum stack_format default_stack_format = STACK_FORMAT_TRUNCATE;
34 
35 /*
36  * Shorthand macros for integer/long long command line options using
37  * opt_int_callback/opt_llong_callback, with variants that set defval.
38  *
39  * Note: defval's type is intptr_t. opt_int_callback interprets it directly as
40  * an int, opt_llong_callback interprets it as a pointer to a long long, as
41  * long long does not fit into intptr_t on 32-bit architectures.
42  */
43 #define RTLA_OPT_LLONG(s, l, v, a, h) \
44 	OPT_CALLBACK(s, l, v, a, h, opt_llong_callback)
45 
46 #define RTLA_OPT_LLONG_DEFVAL(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
47 	.short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
48 	.help = (h), .callback = opt_llong_callback, .defval = (intptr_t)(d) }
49 
50 #define RTLA_OPT_INT(s, l, v, a, h) \
51 	OPT_CALLBACK(s, l, v, a, h, opt_int_callback)
52 
53 #define RTLA_OPT_INT_DEFVAL(s, l, v, a, h, d) { .type = OPTION_CALLBACK, \
54 	.short_name = (s), .long_name = (l), .value = (v), .argh = (a), \
55 	.help = (h), .callback = opt_int_callback, .defval = (intptr_t)(d) }
56 
57 /*
58  * Macros for command line options common to all tools
59  *
60  * Note: Some of the options are common to both timerlat and osnoise, but
61  * have a slightly different meaning. Such options take additional arguments
62  * that have to be provided by the *_parse_args() function of the corresponding
63  * tool.
64  *
65  * All macros defined here assume the presence of a params variable of
66  * the corresponding tool type (i.e struct timerlat_params or struct osnoise_params)
67  * and a cb_data variable of the matching type.
68  */
69 
70  #define RTLA_OPT_STOP(short, long, name) OPT_CALLBACK_FLAG(short, long, \
71 	&params->common.stop_us, \
72 	"us", \
73 	"stop trace if " name " is higher than the argument in us", \
74 	opt_llong_callback, PARSE_OPT_NOAUTONEG)
75 
76 #define RTLA_OPT_STOP_TOTAL(short, long, name) OPT_CALLBACK_FLAG(short, long, \
77 	&params->common.stop_total_us, \
78 	"us", \
79 	"stop trace if " name " is higher than the argument in us", \
80 	opt_llong_callback, PARSE_OPT_NOAUTONEG)
81 
82 #define RTLA_OPT_TRACE_OUTPUT(tracer, cb) OPT_CALLBACK_OPTARG('t', "trace", \
83 	(const char **)&cb_data.trace_output, \
84 	tracer "_trace.txt", \
85 	"[file]", \
86 	"save the stopped trace to [file|" tracer "_trace.txt]", \
87 	cb)
88 
89 #define RTLA_OPT_CPUS OPT_CALLBACK('c', "cpus", &params->common, \
90 	"cpu-list", \
91 	"run the tracer only on the given cpus", \
92 	opt_cpus_cb)
93 
94 #define RTLA_OPT_CGROUP OPT_CALLBACK_OPTARG('C', "cgroup", &params->common, \
95 	"[cgroup_name]", NULL, \
96 	"set cgroup, no argument means rtla's cgroup will be inherited", \
97 	opt_cgroup_cb)
98 
99 #define RTLA_OPT_USER_THREADS OPT_CALLBACK_NOOPT('u', "user-threads", params, NULL, \
100 	"use rtla user-space threads instead of kernel-space timerlat threads", \
101 	opt_user_threads_cb)
102 
103 #define RTLA_OPT_KERNEL_THREADS OPT_BOOLEAN('k', "kernel-threads", \
104 	&params->common.kernel_workload, \
105 	"use timerlat kernel-space threads instead of rtla user-space threads")
106 
107 #define RTLA_OPT_USER_LOAD OPT_BOOLEAN('U', "user-load", &params->common.user_data, \
108 	"enable timerlat for user-defined user-space workload")
109 
110 #define RTLA_OPT_DURATION OPT_CALLBACK('d', "duration", &params->common, \
111 	"time[s|m|h|d]", \
112 	"set the duration of the session", \
113 	opt_duration_cb)
114 
115 #define RTLA_OPT_EVENT OPT_CALLBACK('e', "event", &params->common.events, \
116 	"sys:event", \
117 	"enable the <sys:event> in the trace instance, multiple -e are allowed", \
118 	opt_event_cb)
119 
120 #define RTLA_OPT_HOUSEKEEPING OPT_CALLBACK('H', "house-keeping", &params->common, \
121 	"cpu-list", \
122 	"run rtla control threads only on the given cpus", \
123 	opt_housekeeping_cb)
124 
125 #define RTLA_OPT_PRIORITY OPT_CALLBACK('P', "priority", &params->common, \
126 	"o:prio|r:prio|f:prio|d:runtime:period", \
127 	"set scheduling parameters", \
128 	opt_priority_cb)
129 
130 #define RTLA_OPT_TRIGGER OPT_CALLBACK(0, "trigger", &params->common.events, \
131 	"trigger", \
132 	"enable a trace event trigger to the previous -e event", \
133 	opt_trigger_cb)
134 
135 #define RTLA_OPT_FILTER OPT_CALLBACK(0, "filter", &params->common.events, \
136 	"filter", \
137 	"enable a trace event filter to the previous -e event", \
138 	opt_filter_cb)
139 
140 #define RTLA_OPT_QUIET OPT_BOOLEAN('q', "quiet", &params->common.quiet, \
141 	"print only a summary at the end")
142 
143 #define RTLA_OPT_TRACE_BUFFER_SIZE RTLA_OPT_INT(0, "trace-buffer-size", \
144 	&params->common.buffer_size, "kB", \
145 	"set the per-cpu trace buffer size in kB")
146 
147 #define RTLA_OPT_WARM_UP RTLA_OPT_INT(0, "warm-up", &params->common.warmup, "s", \
148 	"let the workload run for s seconds before collecting data")
149 
150 #define RTLA_OPT_AUTO(cb) OPT_CALLBACK('a', "auto", &cb_data, "us", \
151 	"set automatic trace mode, stopping the session if argument in us sample is hit", \
152 	cb)
153 
154 #define RTLA_OPT_ON_THRESHOLD(threshold, cb) OPT_CALLBACK(0, "on-threshold", \
155 	&params->common.threshold_actions, \
156 	"action", \
157 	"define action to be executed at " threshold " threshold, multiple are allowed", \
158 	cb)
159 
160 #define RTLA_OPT_ON_END(cb) OPT_CALLBACK(0, "on-end", &params->common.end_actions, \
161 	"action", \
162 	"define action to be executed at measurement end, multiple are allowed", \
163 	cb)
164 
165 #define RTLA_OPT_DEBUG OPT_BOOLEAN('D', "debug", &config_debug, \
166 	"print debug info")
167 
168 /*
169  * Common callback functions for command line options
170  */
171 
172 static int opt_llong_callback(const struct option *opt, const char *arg, int unset)
173 {
174 	long long *value = opt->value;
175 
176 	if (unset) {
177 		*value = opt->defval ? *(long long *)opt->defval : 0;
178 		return 0;
179 	}
180 
181 	if (!arg)
182 		return -1;
183 
184 	*value = get_llong_from_str((char *)arg);
185 	return 0;
186 }
187 
188 static int opt_int_callback(const struct option *opt, const char *arg, int unset)
189 {
190 	int *value = opt->value;
191 
192 	if (unset) {
193 		*value = (int)opt->defval;
194 		return 0;
195 	}
196 
197 	if (!arg)
198 		return -1;
199 
200 	if (strtoi(arg, value))
201 		return -1;
202 
203 	return 0;
204 }
205 
206 static int opt_cpus_cb(const struct option *opt, const char *arg, int unset)
207 {
208 	struct common_params *params = opt->value;
209 	int retval;
210 
211 	if (unset) {
212 		CPU_ZERO(&params->monitored_cpus);
213 		params->cpus = NULL;
214 		return 0;
215 	}
216 
217 	if (!arg)
218 		return -1;
219 
220 	retval = parse_cpu_set((char *)arg, &params->monitored_cpus);
221 	if (retval)
222 		fatal("Invalid -c cpu list");
223 	params->cpus = (char *)arg;
224 
225 	return 0;
226 }
227 
228 static int opt_cgroup_cb(const struct option *opt, const char *arg, int unset)
229 {
230 	struct common_params *params = opt->value;
231 
232 	if (unset) {
233 		params->cgroup = 0;
234 		params->cgroup_name = NULL;
235 		return 0;
236 	}
237 
238 	params->cgroup = 1;
239 	params->cgroup_name = (char *)arg;
240 	if (params->cgroup_name && params->cgroup_name[0] == '=')
241 		/* Allow -C=<cgroup_name> next to -C[ ]<cgroup_name> */
242 		++params->cgroup_name;
243 
244 	return 0;
245 }
246 
247 static int opt_duration_cb(const struct option *opt, const char *arg, int unset)
248 {
249 	struct common_params *params = opt->value;
250 
251 	if (unset) {
252 		params->duration = 0;
253 		return 0;
254 	}
255 
256 	if (!arg)
257 		return -1;
258 
259 	params->duration = parse_seconds_duration((char *)arg);
260 	if (!params->duration)
261 		fatal("Invalid -d duration");
262 
263 	return 0;
264 }
265 
266 static int opt_event_cb(const struct option *opt, const char *arg, int unset)
267 {
268 	struct trace_events **events = opt->value;
269 	struct trace_events *tevent;
270 
271 	if (unset || !arg)
272 		return -1;
273 
274 	tevent = trace_event_alloc((char *)arg);
275 	if (!tevent)
276 		fatal("Error alloc trace event");
277 
278 	if (*events)
279 		tevent->next = *events;
280 	*events = tevent;
281 
282 	return 0;
283 }
284 
285 static int opt_housekeeping_cb(const struct option *opt, const char *arg, int unset)
286 {
287 	struct common_params *params = opt->value;
288 	int retval;
289 
290 	if (unset) {
291 		params->hk_cpus = 0;
292 		CPU_ZERO(&params->hk_cpu_set);
293 		return 0;
294 	}
295 
296 	if (!arg)
297 		return -1;
298 
299 	params->hk_cpus = 1;
300 	retval = parse_cpu_set((char *)arg, &params->hk_cpu_set);
301 	if (retval)
302 		fatal("Error parsing house keeping CPUs");
303 
304 	return 0;
305 }
306 
307 static int opt_priority_cb(const struct option *opt, const char *arg, int unset)
308 {
309 	struct common_params *params = opt->value;
310 	int retval;
311 
312 	if (unset) {
313 		memset(&params->sched_param, 0, sizeof(params->sched_param));
314 		params->set_sched = 0;
315 		return 0;
316 	}
317 
318 	if (!arg)
319 		return -1;
320 
321 	retval = parse_prio((char *)arg, &params->sched_param);
322 	if (retval == -1)
323 		fatal("Invalid -P priority");
324 	params->set_sched = 1;
325 
326 	return 0;
327 }
328 
329 static int opt_trigger_cb(const struct option *opt, const char *arg, int unset)
330 {
331 	struct trace_events **events = opt->value;
332 
333 	if (unset || !arg)
334 		return -1;
335 
336 	if (!*events)
337 		fatal("--trigger requires a previous -e");
338 
339 	trace_event_add_trigger(*events, (char *)arg);
340 
341 	return 0;
342 }
343 
344 static int opt_filter_cb(const struct option *opt, const char *arg, int unset)
345 {
346 	struct trace_events **events = opt->value;
347 
348 	if (unset || !arg)
349 		return -1;
350 
351 	if (!*events)
352 		fatal("--filter requires a previous -e");
353 
354 	trace_event_add_filter(*events, (char *)arg);
355 
356 	return 0;
357 }
358 
359 /*
360  * Macros for command line options specific to osnoise
361  */
362 #define OSNOISE_OPT_PERIOD OPT_CALLBACK('p', "period", &params->period, "us", \
363 	"osnoise period in us", \
364 	opt_osnoise_period_cb)
365 
366 #define OSNOISE_OPT_RUNTIME OPT_CALLBACK('r', "runtime", &params->runtime, "us", \
367 	"osnoise runtime in us", \
368 	opt_osnoise_runtime_cb)
369 
370 #define OSNOISE_OPT_THRESHOLD RTLA_OPT_LLONG('T', "threshold", &params->threshold, "us", \
371 	"the minimum delta to be considered a noise")
372 
373 /*
374  * Callback functions for command line options for osnoise tools
375  */
376 
377 static int opt_osnoise_auto_cb(const struct option *opt, const char *arg, int unset)
378 {
379 	struct osnoise_cb_data *cb_data = opt->value;
380 	struct osnoise_params *params = cb_data->params;
381 	long long auto_thresh;
382 
383 	if (unset) {
384 		params->common.stop_us = 0;
385 		params->threshold = 0;
386 		cb_data->trace_output = NULL;
387 		return 0;
388 	}
389 
390 	if (!arg)
391 		return -1;
392 
393 	auto_thresh = get_llong_from_str((char *)arg);
394 	params->common.stop_us = auto_thresh;
395 	params->threshold = 1;
396 
397 	if (!cb_data->trace_output)
398 		cb_data->trace_output = "osnoise_trace.txt";
399 
400 	return 0;
401 }
402 
403 static int opt_osnoise_period_cb(const struct option *opt, const char *arg, int unset)
404 {
405 	unsigned long long *period = opt->value;
406 
407 	if (unset) {
408 		*period = 0;
409 		return 0;
410 	}
411 
412 	if (!arg)
413 		return -1;
414 
415 	*period = get_llong_from_str((char *)arg);
416 	if (*period > 10000000)
417 		fatal("Period longer than 10 s");
418 
419 	return 0;
420 }
421 
422 static int opt_osnoise_runtime_cb(const struct option *opt, const char *arg, int unset)
423 {
424 	unsigned long long *runtime = opt->value;
425 
426 	if (unset) {
427 		*runtime = 0;
428 		return 0;
429 	}
430 
431 	if (!arg)
432 		return -1;
433 
434 	*runtime = get_llong_from_str((char *)arg);
435 	if (*runtime < 100)
436 		fatal("Runtime shorter than 100 us");
437 
438 	return 0;
439 }
440 
441 static int opt_osnoise_trace_output_cb(const struct option *opt, const char *arg, int unset)
442 {
443 	const char **trace_output = opt->value;
444 
445 	if (unset) {
446 		*trace_output = NULL;
447 		return 0;
448 	}
449 
450 	if (!arg) {
451 		*trace_output = "osnoise_trace.txt";
452 	} else {
453 		*trace_output = (char *)arg;
454 		if (*trace_output && (*trace_output)[0] == '=')
455 			/* Allow -t=<trace_output> next to -t[ ]<trace_output> */
456 			++*trace_output;
457 	}
458 
459 	return 0;
460 }
461 
462 static int opt_osnoise_on_threshold_cb(const struct option *opt, const char *arg, int unset)
463 {
464 	struct actions *actions = opt->value;
465 	int retval;
466 
467 	if (unset || !arg)
468 		return -1;
469 
470 	retval = actions_parse(actions, (char *)arg, "osnoise_trace.txt");
471 	if (retval)
472 		fatal("Invalid action %s", arg);
473 
474 	return 0;
475 }
476 
477 static int opt_osnoise_on_end_cb(const struct option *opt, const char *arg, int unset)
478 {
479 	struct actions *actions = opt->value;
480 	int retval;
481 
482 	if (unset || !arg)
483 		return -1;
484 
485 	retval = actions_parse(actions, (char *)arg, "osnoise_trace.txt");
486 	if (retval)
487 		fatal("Invalid action %s", arg);
488 
489 	return 0;
490 }
491 
492 /*
493  * Macros for command line options specific to timerlat
494  */
495 #define TIMERLAT_OPT_PERIOD OPT_CALLBACK('p', "period", &params->timerlat_period_us, "us", \
496 	"timerlat period in us", \
497 	opt_timerlat_period_cb)
498 
499 #define TIMERLAT_OPT_STACK RTLA_OPT_LLONG('s', "stack", &params->print_stack, "us", \
500 	"save the stack trace at the IRQ if a thread latency is higher than the argument in us")
501 
502 #define TIMERLAT_OPT_NANO OPT_CALLBACK_NOOPT('n', "nano", params, NULL, \
503 	"display data in nanoseconds", \
504 	opt_nano_cb)
505 
506 #define TIMERLAT_OPT_DMA_LATENCY OPT_CALLBACK(0, "dma-latency", &params->dma_latency, "us", \
507 	"set /dev/cpu_dma_latency latency <us> to reduce exit from idle latency", \
508 	opt_dma_latency_cb)
509 
510 #define TIMERLAT_OPT_DEEPEST_IDLE_STATE RTLA_OPT_INT_DEFVAL(0, "deepest-idle-state", \
511 	&params->deepest_idle_state, "n", \
512 	"only go down to idle state n on cpus used by timerlat to reduce exit from idle latency", \
513 	default_deepest_idle_state)
514 
515 #define TIMERLAT_OPT_AA_ONLY OPT_CALLBACK(0, "aa-only", params, "us", \
516 	"stop if <us> latency is hit, only printing the auto analysis (reduces CPU usage)", \
517 	opt_aa_only_cb)
518 
519 #define TIMERLAT_OPT_NO_AA OPT_BOOLEAN(0, "no-aa", &params->no_aa, \
520 	"disable auto-analysis, reducing rtla timerlat cpu usage")
521 
522 #define TIMERLAT_OPT_DUMPS_TASKS OPT_BOOLEAN(0, "dump-tasks", &params->dump_tasks, \
523 	"prints the task running on all CPUs if stop conditions are met (depends on !--no-aa)")
524 
525 #define TIMERLAT_OPT_BPF_ACTION OPT_STRING(0, "bpf-action", &params->bpf_action_program, \
526 	"program", \
527 	"load and execute BPF program when latency threshold is exceeded")
528 
529 #define TIMERLAT_OPT_STACK_FORMAT OPT_CALLBACK(0, "stack-format", &params->stack_format, "format", \
530 	"set the stack format (truncate, skip, full)", \
531 	opt_stack_format_cb)
532 
533 #define TIMERLAT_OPT_ALIGNED OPT_CALLBACK('A', "aligned", params, "us", \
534 	"align thread wakeups to a specific offset", \
535 	opt_timerlat_align_cb)
536 
537 /*
538  * Callback functions for command line options for timerlat tools
539  */
540 
541 static int opt_timerlat_period_cb(const struct option *opt, const char *arg, int unset)
542 {
543 	long long *period = opt->value;
544 
545 	if (unset) {
546 		*period = 0;
547 		return 0;
548 	}
549 
550 	if (!arg)
551 		return -1;
552 
553 	*period = get_llong_from_str((char *)arg);
554 	if (*period > 1000000)
555 		fatal("Period longer than 1 s");
556 
557 	return 0;
558 }
559 
560 static int opt_timerlat_auto_cb(const struct option *opt, const char *arg, int unset)
561 {
562 	struct timerlat_cb_data *cb_data = opt->value;
563 	struct timerlat_params *params = cb_data->params;
564 	long long auto_thresh;
565 
566 	if (unset) {
567 		params->common.stop_total_us = 0;
568 		params->common.stop_us = 0;
569 		params->print_stack = 0;
570 		cb_data->trace_output = NULL;
571 		return 0;
572 	}
573 
574 	if (!arg)
575 		return -1;
576 
577 	auto_thresh = get_llong_from_str((char *)arg);
578 	params->common.stop_total_us = auto_thresh;
579 	params->common.stop_us = auto_thresh;
580 	params->print_stack = auto_thresh;
581 
582 	if (!cb_data->trace_output)
583 		cb_data->trace_output = "timerlat_trace.txt";
584 
585 	return 0;
586 }
587 
588 static int opt_dma_latency_cb(const struct option *opt, const char *arg, int unset)
589 {
590 	int *dma_latency = opt->value;
591 	int retval;
592 
593 	if (unset) {
594 		*dma_latency = default_dma_latency;
595 		return 0;
596 	}
597 
598 	if (!arg)
599 		return -1;
600 
601 	retval = strtoi((char *)arg, dma_latency);
602 	if (retval)
603 		fatal("Invalid -dma-latency %s", arg);
604 	if (*dma_latency < 0 || *dma_latency > 10000)
605 		fatal("--dma-latency needs to be >= 0 and <= 10000");
606 
607 	return 0;
608 }
609 
610 static int opt_aa_only_cb(const struct option *opt, const char *arg, int unset)
611 {
612 	struct timerlat_params *params = opt->value;
613 	long long auto_thresh;
614 
615 	if (unset) {
616 		params->common.stop_total_us = 0;
617 		params->common.stop_us = 0;
618 		params->print_stack = 0;
619 		params->common.aa_only = 0;
620 		return 0;
621 	}
622 
623 	if (!arg)
624 		return -1;
625 
626 	auto_thresh = get_llong_from_str((char *)arg);
627 	params->common.stop_total_us = auto_thresh;
628 	params->common.stop_us = auto_thresh;
629 	params->print_stack = auto_thresh;
630 	params->common.aa_only = 1;
631 
632 	return 0;
633 }
634 
635 static int opt_timerlat_trace_output_cb(const struct option *opt, const char *arg, int unset)
636 {
637 	const char **trace_output = opt->value;
638 
639 	if (unset) {
640 		*trace_output = NULL;
641 		return 0;
642 	}
643 
644 	if (!arg) {
645 		*trace_output = "timerlat_trace.txt";
646 	} else {
647 		*trace_output = (char *)arg;
648 		if (*trace_output && (*trace_output)[0] == '=')
649 			/* Allow -t=<trace_output> next to -t[ ]<trace_output> */
650 			++*trace_output;
651 	}
652 
653 	return 0;
654 }
655 
656 static int opt_timerlat_on_threshold_cb(const struct option *opt, const char *arg, int unset)
657 {
658 	struct actions *actions = opt->value;
659 	int retval;
660 
661 	if (unset || !arg)
662 		return -1;
663 
664 	retval = actions_parse(actions, (char *)arg, "timerlat_trace.txt");
665 	if (retval)
666 		fatal("Invalid action %s", arg);
667 
668 	return 0;
669 }
670 
671 static int opt_timerlat_on_end_cb(const struct option *opt, const char *arg, int unset)
672 {
673 	struct actions *actions = opt->value;
674 	int retval;
675 
676 	if (unset || !arg)
677 		return -1;
678 
679 	retval = actions_parse(actions, (char *)arg, "timerlat_trace.txt");
680 	if (retval)
681 		fatal("Invalid action %s", arg);
682 
683 	return 0;
684 }
685 
686 static int opt_user_threads_cb(const struct option *opt, const char *arg, int unset)
687 {
688 	struct timerlat_params *params = opt->value;
689 
690 	if (unset) {
691 		params->common.user_workload = false;
692 		params->common.user_data = false;
693 		return 0;
694 	}
695 
696 	params->common.user_workload = true;
697 	params->common.user_data = true;
698 
699 	return 0;
700 }
701 
702 static int opt_nano_cb(const struct option *opt, const char *arg, int unset)
703 {
704 	struct timerlat_params *params = opt->value;
705 
706 	if (unset) {
707 		params->common.output_divisor = default_output_divisor;
708 		return 0;
709 	}
710 
711 	params->common.output_divisor = 1;
712 
713 	return 0;
714 }
715 
716 static int opt_stack_format_cb(const struct option *opt, const char *arg, int unset)
717 {
718 	int *format = opt->value;
719 
720 	if (unset) {
721 		*format = default_stack_format;
722 		return 0;
723 	}
724 
725 	if (!arg)
726 		return -1;
727 
728 	*format = parse_stack_format((char *)arg);
729 
730 	if (*format == -1)
731 		fatal("Invalid --stack-format option");
732 
733 	return 0;
734 }
735 
736 static int opt_timerlat_align_cb(const struct option *opt, const char *arg, int unset)
737 {
738 	struct timerlat_params *params = opt->value;
739 
740 	if (unset) {
741 		params->timerlat_align = false;
742 		params->timerlat_align_us = 0;
743 		return 0;
744 	}
745 
746 	if (!arg)
747 		return -1;
748 
749 	params->timerlat_align = true;
750 	params->timerlat_align_us = get_llong_from_str((char *)arg);
751 
752 	return 0;
753 }
754 
755 /*
756  * Macros for command line options specific to histogram-based tools
757  */
758 
759 #define HIST_OPT_BUCKET_SIZE OPT_CALLBACK('b', "bucket-size", \
760 	&params->common.hist.bucket_size, "N", \
761 	"set the histogram bucket size (default 1)", \
762 	opt_bucket_size_cb)
763 
764 #define HIST_OPT_ENTRIES OPT_CALLBACK('E', "entries", &params->common.hist.entries, "N", \
765 	"set the number of entries of the histogram (default 256)", \
766 	opt_entries_cb)
767 
768 #define HIST_OPT_NO_IRQ OPT_BOOLEAN_FLAG(0, "no-irq", &params->common.hist.no_irq, \
769 	"ignore IRQ latencies", PARSE_OPT_NOAUTONEG)
770 
771 #define HIST_OPT_NO_THREAD OPT_BOOLEAN_FLAG(0, "no-thread", &params->common.hist.no_thread, \
772 	"ignore thread latencies", PARSE_OPT_NOAUTONEG)
773 
774 #define HIST_OPT_NO_HEADER OPT_BOOLEAN(0, "no-header", &params->common.hist.no_header, \
775 	"do not print header")
776 
777 #define HIST_OPT_NO_SUMMARY OPT_BOOLEAN(0, "no-summary", &params->common.hist.no_summary, \
778 	"do not print summary")
779 
780 #define HIST_OPT_NO_INDEX OPT_BOOLEAN(0, "no-index", &params->common.hist.no_index, \
781 	"do not print index")
782 
783 #define HIST_OPT_WITH_ZEROS OPT_BOOLEAN(0, "with-zeros", &params->common.hist.with_zeros, \
784 	"print zero only entries")
785 
786 /* Histogram-specific callbacks */
787 
788 static int opt_bucket_size_cb(const struct option *opt, const char *arg, int unset)
789 {
790 	int *bucket_size = opt->value;
791 
792 	if (unset) {
793 		*bucket_size = default_bucket_size;
794 		return 0;
795 	}
796 
797 	if (!arg)
798 		return -1;
799 
800 	*bucket_size = get_llong_from_str((char *)arg);
801 	if (*bucket_size == 0 || *bucket_size >= 1000000)
802 		fatal("Bucket size needs to be > 0 and <= 1000000");
803 
804 	return 0;
805 }
806 
807 static int opt_entries_cb(const struct option *opt, const char *arg, int unset)
808 {
809 	int *entries = opt->value;
810 
811 	if (unset) {
812 		*entries = default_entries;
813 		return 0;
814 	}
815 
816 	if (!arg)
817 		return -1;
818 
819 	*entries = get_llong_from_str((char *)arg);
820 	if (*entries < 10 || *entries > 9999999)
821 		fatal("Entries must be > 10 and < 10000000");
822 
823 	return 0;
824 }
825