1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
20 * osnoise_get_cpus - return the original "osnoise/cpus" content
22 * It also saves the value to be restored.
24 char *osnoise_get_cpus(struct osnoise_context *context)
26 if (context->curr_cpus)
27 return context->curr_cpus;
29 if (context->orig_cpus)
30 return context->orig_cpus;
32 context->orig_cpus = tracefs_instance_file_read(NULL, "osnoise/cpus", NULL);
35 * The error value (NULL) is the same for tracefs_instance_file_read()
36 * and this functions, so:
38 return context->orig_cpus;
42 * osnoise_set_cpus - configure osnoise to run on *cpus
44 * "osnoise/cpus" file is used to set the cpus in which osnoise/timerlat
45 * will run. This function opens this file, saves the current value,
46 * and set the cpus passed as argument.
48 int osnoise_set_cpus(struct osnoise_context *context, char *cpus)
50 char *orig_cpus = osnoise_get_cpus(context);
57 context->curr_cpus = strdup(cpus);
58 if (!context->curr_cpus)
61 snprintf(buffer, 1024, "%s\n", cpus);
63 debug_msg("setting cpus to %s from %s", cpus, context->orig_cpus);
65 retval = tracefs_instance_file_write(NULL, "osnoise/cpus", buffer);
67 free(context->curr_cpus);
68 context->curr_cpus = NULL;
76 * osnoise_restore_cpus - restore the original "osnoise/cpus"
78 * osnoise_set_cpus() saves the original data for the "osnoise/cpus"
79 * file. This function restore the original config it was previously
82 void osnoise_restore_cpus(struct osnoise_context *context)
86 if (!context->orig_cpus)
89 if (!context->curr_cpus)
93 if (!strcmp(context->orig_cpus, context->curr_cpus))
96 debug_msg("restoring cpus to %s", context->orig_cpus);
98 retval = tracefs_instance_file_write(NULL, "osnoise/cpus", context->orig_cpus);
100 err_msg("could not restore original osnoise cpus\n");
103 free(context->curr_cpus);
104 context->curr_cpus = NULL;
108 * osnoise_put_cpus - restore cpus config and cleanup data
110 void osnoise_put_cpus(struct osnoise_context *context)
112 osnoise_restore_cpus(context);
114 if (!context->orig_cpus)
117 free(context->orig_cpus);
118 context->orig_cpus = NULL;
122 * osnoise_read_ll_config - read a long long value from a config
124 * returns -1 on error.
126 static long long osnoise_read_ll_config(char *rel_path)
131 buffer = tracefs_instance_file_read(NULL, rel_path, NULL);
135 /* get_llong_from_str returns -1 on error */
136 retval = get_llong_from_str(buffer);
138 debug_msg("reading %s returned %lld\n", rel_path, retval);
146 * osnoise_write_ll_config - write a long long value to a config in rel_path
148 * returns -1 on error.
150 static long long osnoise_write_ll_config(char *rel_path, long long value)
152 char buffer[BUFF_U64_STR_SIZE];
155 snprintf(buffer, sizeof(buffer), "%lld\n", value);
157 debug_msg("setting %s to %lld\n", rel_path, value);
159 retval = tracefs_instance_file_write(NULL, rel_path, buffer);
164 * osnoise_get_runtime - return the original "osnoise/runtime_us" value
166 * It also saves the value to be restored.
168 unsigned long long osnoise_get_runtime(struct osnoise_context *context)
170 long long runtime_us;
172 if (context->runtime_us != OSNOISE_TIME_INIT_VAL)
173 return context->runtime_us;
175 if (context->orig_runtime_us != OSNOISE_TIME_INIT_VAL)
176 return context->orig_runtime_us;
178 runtime_us = osnoise_read_ll_config("osnoise/runtime_us");
182 context->orig_runtime_us = runtime_us;
186 return OSNOISE_TIME_INIT_VAL;
190 * osnoise_get_period - return the original "osnoise/period_us" value
192 * It also saves the value to be restored.
194 unsigned long long osnoise_get_period(struct osnoise_context *context)
198 if (context->period_us != OSNOISE_TIME_INIT_VAL)
199 return context->period_us;
201 if (context->orig_period_us != OSNOISE_TIME_INIT_VAL)
202 return context->orig_period_us;
204 period_us = osnoise_read_ll_config("osnoise/period_us");
208 context->orig_period_us = period_us;
212 return OSNOISE_TIME_INIT_VAL;
215 static int __osnoise_write_runtime(struct osnoise_context *context,
216 unsigned long long runtime)
220 if (context->orig_runtime_us == OSNOISE_TIME_INIT_VAL)
223 retval = osnoise_write_ll_config("osnoise/runtime_us", runtime);
227 context->runtime_us = runtime;
231 static int __osnoise_write_period(struct osnoise_context *context,
232 unsigned long long period)
236 if (context->orig_period_us == OSNOISE_TIME_INIT_VAL)
239 retval = osnoise_write_ll_config("osnoise/period_us", period);
243 context->period_us = period;
248 * osnoise_set_runtime_period - set osnoise runtime and period
250 * Osnoise's runtime and period are related as runtime <= period.
251 * Thus, this function saves the original values, and then tries
252 * to set the runtime and period if they are != 0.
254 int osnoise_set_runtime_period(struct osnoise_context *context,
255 unsigned long long runtime,
256 unsigned long long period)
258 unsigned long long curr_runtime_us;
259 unsigned long long curr_period_us;
262 if (!period && !runtime)
265 curr_runtime_us = osnoise_get_runtime(context);
266 curr_period_us = osnoise_get_period(context);
268 /* error getting any value? */
269 if (curr_period_us == OSNOISE_TIME_INIT_VAL || curr_runtime_us == OSNOISE_TIME_INIT_VAL)
273 if (runtime > curr_period_us)
275 return __osnoise_write_runtime(context, runtime);
276 } else if (!runtime) {
277 if (period < curr_runtime_us)
279 return __osnoise_write_period(context, period);
282 if (runtime > curr_period_us) {
283 retval = __osnoise_write_period(context, period);
286 retval = __osnoise_write_runtime(context, runtime);
290 retval = __osnoise_write_runtime(context, runtime);
293 retval = __osnoise_write_period(context, period);
302 * osnoise_restore_runtime_period - restore the original runtime and period
304 void osnoise_restore_runtime_period(struct osnoise_context *context)
306 unsigned long long orig_runtime = context->orig_runtime_us;
307 unsigned long long orig_period = context->orig_period_us;
308 unsigned long long curr_runtime = context->runtime_us;
309 unsigned long long curr_period = context->period_us;
312 if ((orig_runtime == OSNOISE_TIME_INIT_VAL) && (orig_period == OSNOISE_TIME_INIT_VAL))
315 if ((orig_period == curr_period) && (orig_runtime == curr_runtime))
318 retval = osnoise_set_runtime_period(context, orig_runtime, orig_period);
320 err_msg("Could not restore original osnoise runtime/period\n");
323 context->runtime_us = OSNOISE_TIME_INIT_VAL;
324 context->period_us = OSNOISE_TIME_INIT_VAL;
328 * osnoise_put_runtime_period - restore original values and cleanup data
330 void osnoise_put_runtime_period(struct osnoise_context *context)
332 osnoise_restore_runtime_period(context);
334 if (context->orig_runtime_us != OSNOISE_TIME_INIT_VAL)
335 context->orig_runtime_us = OSNOISE_TIME_INIT_VAL;
337 if (context->orig_period_us != OSNOISE_TIME_INIT_VAL)
338 context->orig_period_us = OSNOISE_TIME_INIT_VAL;
342 * osnoise_get_timerlat_period_us - read and save the original "timerlat_period_us"
345 osnoise_get_timerlat_period_us(struct osnoise_context *context)
347 long long timerlat_period_us;
349 if (context->timerlat_period_us != OSNOISE_TIME_INIT_VAL)
350 return context->timerlat_period_us;
352 if (context->orig_timerlat_period_us != OSNOISE_TIME_INIT_VAL)
353 return context->orig_timerlat_period_us;
355 timerlat_period_us = osnoise_read_ll_config("osnoise/timerlat_period_us");
356 if (timerlat_period_us < 0)
359 context->orig_timerlat_period_us = timerlat_period_us;
360 return timerlat_period_us;
363 return OSNOISE_TIME_INIT_VAL;
367 * osnoise_set_timerlat_period_us - set "timerlat_period_us"
369 int osnoise_set_timerlat_period_us(struct osnoise_context *context, long long timerlat_period_us)
371 long long curr_timerlat_period_us = osnoise_get_timerlat_period_us(context);
374 if (curr_timerlat_period_us == OSNOISE_TIME_INIT_VAL)
377 retval = osnoise_write_ll_config("osnoise/timerlat_period_us", timerlat_period_us);
381 context->timerlat_period_us = timerlat_period_us;
387 * osnoise_restore_timerlat_period_us - restore "timerlat_period_us"
389 void osnoise_restore_timerlat_period_us(struct osnoise_context *context)
393 if (context->orig_timerlat_period_us == OSNOISE_TIME_INIT_VAL)
396 if (context->orig_timerlat_period_us == context->timerlat_period_us)
399 retval = osnoise_write_ll_config("osnoise/timerlat_period_us", context->orig_timerlat_period_us);
401 err_msg("Could not restore original osnoise timerlat_period_us\n");
404 context->timerlat_period_us = OSNOISE_TIME_INIT_VAL;
408 * osnoise_put_timerlat_period_us - restore original values and cleanup data
410 void osnoise_put_timerlat_period_us(struct osnoise_context *context)
412 osnoise_restore_timerlat_period_us(context);
414 if (context->orig_timerlat_period_us == OSNOISE_TIME_INIT_VAL)
417 context->orig_timerlat_period_us = OSNOISE_TIME_INIT_VAL;
421 * osnoise_get_stop_us - read and save the original "stop_tracing_us"
424 osnoise_get_stop_us(struct osnoise_context *context)
428 if (context->stop_us != OSNOISE_OPTION_INIT_VAL)
429 return context->stop_us;
431 if (context->orig_stop_us != OSNOISE_OPTION_INIT_VAL)
432 return context->orig_stop_us;
434 stop_us = osnoise_read_ll_config("osnoise/stop_tracing_us");
438 context->orig_stop_us = stop_us;
442 return OSNOISE_OPTION_INIT_VAL;
446 * osnoise_set_stop_us - set "stop_tracing_us"
448 int osnoise_set_stop_us(struct osnoise_context *context, long long stop_us)
450 long long curr_stop_us = osnoise_get_stop_us(context);
453 if (curr_stop_us == OSNOISE_OPTION_INIT_VAL)
456 retval = osnoise_write_ll_config("osnoise/stop_tracing_us", stop_us);
460 context->stop_us = stop_us;
466 * osnoise_restore_stop_us - restore the original "stop_tracing_us"
468 void osnoise_restore_stop_us(struct osnoise_context *context)
472 if (context->orig_stop_us == OSNOISE_OPTION_INIT_VAL)
475 if (context->orig_stop_us == context->stop_us)
478 retval = osnoise_write_ll_config("osnoise/stop_tracing_us", context->orig_stop_us);
480 err_msg("Could not restore original osnoise stop_us\n");
483 context->stop_us = OSNOISE_OPTION_INIT_VAL;
487 * osnoise_put_stop_us - restore original values and cleanup data
489 void osnoise_put_stop_us(struct osnoise_context *context)
491 osnoise_restore_stop_us(context);
493 if (context->orig_stop_us == OSNOISE_OPTION_INIT_VAL)
496 context->orig_stop_us = OSNOISE_OPTION_INIT_VAL;
500 * osnoise_get_stop_total_us - read and save the original "stop_tracing_total_us"
503 osnoise_get_stop_total_us(struct osnoise_context *context)
505 long long stop_total_us;
507 if (context->stop_total_us != OSNOISE_OPTION_INIT_VAL)
508 return context->stop_total_us;
510 if (context->orig_stop_total_us != OSNOISE_OPTION_INIT_VAL)
511 return context->orig_stop_total_us;
513 stop_total_us = osnoise_read_ll_config("osnoise/stop_tracing_total_us");
514 if (stop_total_us < 0)
517 context->orig_stop_total_us = stop_total_us;
518 return stop_total_us;
521 return OSNOISE_OPTION_INIT_VAL;
525 * osnoise_set_stop_total_us - set "stop_tracing_total_us"
527 int osnoise_set_stop_total_us(struct osnoise_context *context, long long stop_total_us)
529 long long curr_stop_total_us = osnoise_get_stop_total_us(context);
532 if (curr_stop_total_us == OSNOISE_OPTION_INIT_VAL)
535 retval = osnoise_write_ll_config("osnoise/stop_tracing_total_us", stop_total_us);
539 context->stop_total_us = stop_total_us;
545 * osnoise_restore_stop_total_us - restore the original "stop_tracing_total_us"
547 void osnoise_restore_stop_total_us(struct osnoise_context *context)
551 if (context->orig_stop_total_us == OSNOISE_OPTION_INIT_VAL)
554 if (context->orig_stop_total_us == context->stop_total_us)
557 retval = osnoise_write_ll_config("osnoise/stop_tracing_total_us",
558 context->orig_stop_total_us);
560 err_msg("Could not restore original osnoise stop_total_us\n");
563 context->stop_total_us = OSNOISE_OPTION_INIT_VAL;
567 * osnoise_put_stop_total_us - restore original values and cleanup data
569 void osnoise_put_stop_total_us(struct osnoise_context *context)
571 osnoise_restore_stop_total_us(context);
573 if (context->orig_stop_total_us == OSNOISE_OPTION_INIT_VAL)
576 context->orig_stop_total_us = OSNOISE_OPTION_INIT_VAL;
580 * osnoise_get_print_stack - read and save the original "print_stack"
583 osnoise_get_print_stack(struct osnoise_context *context)
585 long long print_stack;
587 if (context->print_stack != OSNOISE_OPTION_INIT_VAL)
588 return context->print_stack;
590 if (context->orig_print_stack != OSNOISE_OPTION_INIT_VAL)
591 return context->orig_print_stack;
593 print_stack = osnoise_read_ll_config("osnoise/print_stack");
597 context->orig_print_stack = print_stack;
601 return OSNOISE_OPTION_INIT_VAL;
605 * osnoise_set_print_stack - set "print_stack"
607 int osnoise_set_print_stack(struct osnoise_context *context, long long print_stack)
609 long long curr_print_stack = osnoise_get_print_stack(context);
612 if (curr_print_stack == OSNOISE_OPTION_INIT_VAL)
615 retval = osnoise_write_ll_config("osnoise/print_stack", print_stack);
619 context->print_stack = print_stack;
625 * osnoise_restore_print_stack - restore the original "print_stack"
627 void osnoise_restore_print_stack(struct osnoise_context *context)
631 if (context->orig_print_stack == OSNOISE_OPTION_INIT_VAL)
634 if (context->orig_print_stack == context->print_stack)
637 retval = osnoise_write_ll_config("osnoise/print_stack", context->orig_print_stack);
639 err_msg("Could not restore original osnoise print_stack\n");
642 context->print_stack = OSNOISE_OPTION_INIT_VAL;
646 * osnoise_put_print_stack - restore original values and cleanup data
648 void osnoise_put_print_stack(struct osnoise_context *context)
650 osnoise_restore_print_stack(context);
652 if (context->orig_print_stack == OSNOISE_OPTION_INIT_VAL)
655 context->orig_print_stack = OSNOISE_OPTION_INIT_VAL;
659 * enable_osnoise - enable osnoise tracer in the trace_instance
661 int enable_osnoise(struct trace_instance *trace)
663 return enable_tracer_by_name(trace->inst, "osnoise");
667 * enable_timerlat - enable timerlat tracer in the trace_instance
669 int enable_timerlat(struct trace_instance *trace)
671 return enable_tracer_by_name(trace->inst, "timerlat");
675 FLAG_CONTEXT_NEWLY_CREATED = (1 << 0),
676 FLAG_CONTEXT_DELETED = (1 << 1),
680 * osnoise_get_context - increase the usage of a context and return it
682 int osnoise_get_context(struct osnoise_context *context)
686 if (context->flags & FLAG_CONTEXT_DELETED) {
697 * osnoise_context_alloc - alloc an osnoise_context
699 * The osnoise context contains the information of the "osnoise/" configs.
700 * It is used to set and restore the config.
702 struct osnoise_context *osnoise_context_alloc(void)
704 struct osnoise_context *context;
706 context = calloc(1, sizeof(*context));
710 context->orig_stop_us = OSNOISE_OPTION_INIT_VAL;
711 context->stop_us = OSNOISE_OPTION_INIT_VAL;
713 context->orig_stop_total_us = OSNOISE_OPTION_INIT_VAL;
714 context->stop_total_us = OSNOISE_OPTION_INIT_VAL;
716 context->orig_print_stack = OSNOISE_OPTION_INIT_VAL;
717 context->print_stack = OSNOISE_OPTION_INIT_VAL;
719 osnoise_get_context(context);
725 * osnoise_put_context - put the osnoise_put_context
727 * If there is no other user for the context, the original data
730 void osnoise_put_context(struct osnoise_context *context)
732 if (--context->ref < 1)
733 context->flags |= FLAG_CONTEXT_DELETED;
735 if (!(context->flags & FLAG_CONTEXT_DELETED))
738 osnoise_put_cpus(context);
739 osnoise_put_runtime_period(context);
740 osnoise_put_stop_us(context);
741 osnoise_put_stop_total_us(context);
742 osnoise_put_timerlat_period_us(context);
743 osnoise_put_print_stack(context);
749 * osnoise_destroy_tool - disable trace, restore configs and free data
751 void osnoise_destroy_tool(struct osnoise_tool *top)
753 trace_instance_destroy(&top->trace);
756 osnoise_put_context(top->context);
762 * osnoise_init_tool - init an osnoise tool
764 * It allocs data, create a context to store data and
765 * creates a new trace instance for the tool.
767 struct osnoise_tool *osnoise_init_tool(char *tool_name)
769 struct osnoise_tool *top;
772 top = calloc(1, sizeof(*top));
776 top->context = osnoise_context_alloc();
780 retval = trace_instance_init(&top->trace, tool_name);
786 osnoise_destroy_tool(top);
791 * osnoise_init_trace_tool - init a tracer instance to trace osnoise events
793 struct osnoise_tool *osnoise_init_trace_tool(char *tracer)
795 struct osnoise_tool *trace;
798 trace = osnoise_init_tool("osnoise_trace");
802 retval = tracefs_event_enable(trace->trace.inst, "osnoise", NULL);
803 if (retval < 0 && !errno) {
804 err_msg("Could not find osnoise events\n");
808 retval = enable_tracer_by_name(trace->trace.inst, tracer);
810 err_msg("Could not enable osnoiser tracer for tracing\n");
816 osnoise_destroy_tool(trace);
820 static void osnoise_usage(void)
824 static const char *msg[] = {
826 "osnoise version " VERSION,
828 " usage: [rtla] osnoise [MODE] ...",
831 " top - prints the summary from osnoise tracer",
832 " hist - prints a histogram of osnoise samples",
834 "if no MODE is given, the top mode is called, passing the arguments",
838 for (i = 0; msg[i]; i++)
839 fprintf(stderr, "%s\n", msg[i]);
843 int osnoise_main(int argc, char *argv[])
849 * if osnoise was called without any argument, run the
853 osnoise_top_main(argc, argv);
857 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
860 } else if (strncmp(argv[1], "-", 1) == 0) {
861 /* the user skipped the tool, call the default one */
862 osnoise_top_main(argc, argv);
864 } else if (strcmp(argv[1], "top") == 0) {
865 osnoise_top_main(argc-1, &argv[1]);
867 } else if (strcmp(argv[1], "hist") == 0) {
868 osnoise_hist_main(argc-1, &argv[1]);