Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
0122938
Documentation
LICENSES
arch
block
certs
crypto
drivers
fs
include
init
io_uring
ipc
kernel
lib
mm
net
rust
samples
scripts
security
sound
tools
accounting
arch
bootconfig
bpf
build
certs
cgroup
counter
crypto
debugging
firewire
firmware
gpio
hv
iio
include
kvm
laptop
leds
lib
memory-model
mm
net
objtool
pcmcia
perf
power
rcu
sched_ext
scripts
sound
spi
testing
thermal
time
tracing
latency
rtla
sample
src
Build
osnoise.c
osnoise.h
osnoise_hist.c
osnoise_top.c
rtla.c
timerlat.bpf.c
timerlat.c
timerlat.h
timerlat_aa.c
timerlat_aa.h
timerlat_bpf.c
timerlat_bpf.h
timerlat_hist.c
timerlat_top.c
timerlat_u.c
timerlat_u.h
trace.c
trace.h
utils.c
utils.h
tests
.gitignore
Build
Makefile
Makefile.config
Makefile.rtla
Makefile.standalone
README.txt
Makefile
usb
verification
virtio
wmi
workqueue
writeback
Makefile
usr
virt
.clang-format
.clippy.toml
.cocciconfig
.editorconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
.rustfmt.toml
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
tools
/
tracing
/
rtla
/
src
/
osnoise.c
Blame
Blame
Latest commit
History
History
1262 lines (993 loc) · 29 KB
Breadcrumbs
linux
/
tools
/
tracing
/
rtla
/
src
/
osnoise.c
Top
File metadata and controls
Code
Blame
1262 lines (993 loc) · 29 KB
Raw
// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> */ #define _GNU_SOURCE #include <sys/types.h> #include <sys/stat.h> #include <pthread.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <sched.h> #include "osnoise.h" #define DEFAULT_SAMPLE_PERIOD 1000000 /* 1s */ #define DEFAULT_SAMPLE_RUNTIME 1000000 /* 1s */ /* * osnoise_get_cpus - return the original "osnoise/cpus" content * * It also saves the value to be restored. */ char *osnoise_get_cpus(struct osnoise_context *context) { if (context->curr_cpus) return context->curr_cpus; if (context->orig_cpus) return context->orig_cpus; context->orig_cpus = tracefs_instance_file_read(NULL, "osnoise/cpus", NULL); /* * The error value (NULL) is the same for tracefs_instance_file_read() * and this functions, so: */ return context->orig_cpus; } /* * osnoise_set_cpus - configure osnoise to run on *cpus * * "osnoise/cpus" file is used to set the cpus in which osnoise/timerlat * will run. This function opens this file, saves the current value, * and set the cpus passed as argument. */ int osnoise_set_cpus(struct osnoise_context *context, char *cpus) { char *orig_cpus = osnoise_get_cpus(context); char buffer[1024]; int retval; if (!orig_cpus) return -1; context->curr_cpus = strdup(cpus); if (!context->curr_cpus) return -1; snprintf(buffer, 1024, "%s\n", cpus); debug_msg("setting cpus to %s from %s", cpus, context->orig_cpus); retval = tracefs_instance_file_write(NULL, "osnoise/cpus", buffer); if (retval < 0) { free(context->curr_cpus); context->curr_cpus = NULL; return -1; } return 0; } /* * osnoise_restore_cpus - restore the original "osnoise/cpus" * * osnoise_set_cpus() saves the original data for the "osnoise/cpus" * file. This function restore the original config it was previously * modified. */ void osnoise_restore_cpus(struct osnoise_context *context) { int retval; if (!context->orig_cpus) return; if (!context->curr_cpus) return; /* nothing to do? */ if (!strcmp(context->orig_cpus, context->curr_cpus)) goto out_done; debug_msg("restoring cpus to %s", context->orig_cpus); retval = tracefs_instance_file_write(NULL, "osnoise/cpus", context->orig_cpus); if (retval < 0) err_msg("could not restore original osnoise cpus\n"); out_done: free(context->curr_cpus); context->curr_cpus = NULL; } /* * osnoise_put_cpus - restore cpus config and cleanup data */ void osnoise_put_cpus(struct osnoise_context *context) { osnoise_restore_cpus(context); if (!context->orig_cpus) return; free(context->orig_cpus); context->orig_cpus = NULL; } /* * osnoise_read_ll_config - read a long long value from a config * * returns -1 on error. */ static long long osnoise_read_ll_config(char *rel_path) { long long retval; char *buffer; buffer = tracefs_instance_file_read(NULL, rel_path, NULL); if (!buffer) return -1; /* get_llong_from_str returns -1 on error */ retval = get_llong_from_str(buffer); debug_msg("reading %s returned %lld\n", rel_path, retval); free(buffer); return retval; } /* * osnoise_write_ll_config - write a long long value to a config in rel_path * * returns -1 on error. */ static long long osnoise_write_ll_config(char *rel_path, long long value) { char buffer[BUFF_U64_STR_SIZE]; long long retval; snprintf(buffer, sizeof(buffer), "%lld\n", value); debug_msg("setting %s to %lld\n", rel_path, value); retval = tracefs_instance_file_write(NULL, rel_path, buffer); return retval; } /* * osnoise_get_runtime - return the original "osnoise/runtime_us" value * * It also saves the value to be restored. */ unsigned long long osnoise_get_runtime(struct osnoise_context *context) { long long runtime_us; if (context->runtime_us != OSNOISE_TIME_INIT_VAL) return context->runtime_us; if (context->orig_runtime_us != OSNOISE_TIME_INIT_VAL) return context->orig_runtime_us; runtime_us = osnoise_read_ll_config("osnoise/runtime_us"); if (runtime_us < 0) goto out_err; context->orig_runtime_us = runtime_us; return runtime_us; out_err: return OSNOISE_TIME_INIT_VAL; } /* * osnoise_get_period - return the original "osnoise/period_us" value * * It also saves the value to be restored. */ unsigned long long osnoise_get_period(struct osnoise_context *context) { long long period_us; if (context->period_us != OSNOISE_TIME_INIT_VAL) return context->period_us; if (context->orig_period_us != OSNOISE_TIME_INIT_VAL) return context->orig_period_us; period_us = osnoise_read_ll_config("osnoise/period_us"); if (period_us < 0) goto out_err; context->orig_period_us = period_us; return period_us; out_err: return OSNOISE_TIME_INIT_VAL; } static int __osnoise_write_runtime(struct osnoise_context *context, unsigned long long runtime) { int retval; if (context->orig_runtime_us == OSNOISE_TIME_INIT_VAL) return -1; retval = osnoise_write_ll_config("osnoise/runtime_us", runtime); if (retval < 0) return -1; context->runtime_us = runtime; return 0; } static int __osnoise_write_period(struct osnoise_context *context, unsigned long long period) { int retval; if (context->orig_period_us == OSNOISE_TIME_INIT_VAL) return -1; retval = osnoise_write_ll_config("osnoise/period_us", period); if (retval < 0) return -1; context->period_us = period; return 0; } /* * osnoise_set_runtime_period - set osnoise runtime and period * * Osnoise's runtime and period are related as runtime <= period. * Thus, this function saves the original values, and then tries * to set the runtime and period if they are != 0. */ int osnoise_set_runtime_period(struct osnoise_context *context, unsigned long long runtime, unsigned long long period) { unsigned long long curr_runtime_us; unsigned long long curr_period_us; int retval; if (!period && !runtime) return 0; curr_runtime_us = osnoise_get_runtime(context); curr_period_us = osnoise_get_period(context); /* error getting any value? */ if (curr_period_us == OSNOISE_TIME_INIT_VAL || curr_runtime_us == OSNOISE_TIME_INIT_VAL) return -1; if (!period) { if (runtime > curr_period_us) return -1; return __osnoise_write_runtime(context, runtime); } else if (!runtime) { if (period < curr_runtime_us) return -1; return __osnoise_write_period(context, period); } if (runtime > curr_period_us) { retval = __osnoise_write_period(context, period); if (retval) return -1; retval = __osnoise_write_runtime(context, runtime); if (retval) return -1; } else { retval = __osnoise_write_runtime(context, runtime); if (retval) return -1; retval = __osnoise_write_period(context, period); if (retval) return -1; } return 0; } /* * osnoise_restore_runtime_period - restore the original runtime and period */ void osnoise_restore_runtime_period(struct osnoise_context *context) { unsigned long long orig_runtime = context->orig_runtime_us; unsigned long long orig_period = context->orig_period_us; unsigned long long curr_runtime = context->runtime_us; unsigned long long curr_period = context->period_us; int retval; if ((orig_runtime == OSNOISE_TIME_INIT_VAL) && (orig_period == OSNOISE_TIME_INIT_VAL)) return; if ((orig_period == curr_period) && (orig_runtime == curr_runtime)) goto out_done; retval = osnoise_set_runtime_period(context, orig_runtime, orig_period); if (retval) err_msg("Could not restore original osnoise runtime/period\n"); out_done: context->runtime_us = OSNOISE_TIME_INIT_VAL; context->period_us = OSNOISE_TIME_INIT_VAL; } /* * osnoise_put_runtime_period - restore original values and cleanup data */ void osnoise_put_runtime_period(struct osnoise_context *context) { osnoise_restore_runtime_period(context); if (context->orig_runtime_us != OSNOISE_TIME_INIT_VAL) context->orig_runtime_us = OSNOISE_TIME_INIT_VAL; if (context->orig_period_us != OSNOISE_TIME_INIT_VAL) context->orig_period_us = OSNOISE_TIME_INIT_VAL; } /* * osnoise_get_timerlat_period_us - read and save the original "timerlat_period_us" */ static long long osnoise_get_timerlat_period_us(struct osnoise_context *context) { long long timerlat_period_us; if (context->timerlat_period_us != OSNOISE_TIME_INIT_VAL) return context->timerlat_period_us; if (context->orig_timerlat_period_us != OSNOISE_TIME_INIT_VAL) return context->orig_timerlat_period_us; timerlat_period_us = osnoise_read_ll_config("osnoise/timerlat_period_us"); if (timerlat_period_us < 0) goto out_err; context->orig_timerlat_period_us = timerlat_period_us; return timerlat_period_us; out_err: return OSNOISE_TIME_INIT_VAL; } /* * osnoise_set_timerlat_period_us - set "timerlat_period_us" */ int osnoise_set_timerlat_period_us(struct osnoise_context *context, long long timerlat_period_us) { long long curr_timerlat_period_us = osnoise_get_timerlat_period_us(context); int retval; if (curr_timerlat_period_us == OSNOISE_TIME_INIT_VAL) return -1; retval = osnoise_write_ll_config("osnoise/timerlat_period_us", timerlat_period_us); if (retval < 0) return -1; context->timerlat_period_us = timerlat_period_us; return 0; } /* * osnoise_restore_timerlat_period_us - restore "timerlat_period_us" */ void osnoise_restore_timerlat_period_us(struct osnoise_context *context) { int retval; if (context->orig_timerlat_period_us == OSNOISE_TIME_INIT_VAL) return; if (context->orig_timerlat_period_us == context->timerlat_period_us) goto out_done; retval = osnoise_write_ll_config("osnoise/timerlat_period_us", context->orig_timerlat_period_us); if (retval < 0) err_msg("Could not restore original osnoise timerlat_period_us\n"); out_done: context->timerlat_period_us = OSNOISE_TIME_INIT_VAL; } /* * osnoise_put_timerlat_period_us - restore original values and cleanup data */ void osnoise_put_timerlat_period_us(struct osnoise_context *context) { osnoise_restore_timerlat_period_us(context); if (context->orig_timerlat_period_us == OSNOISE_TIME_INIT_VAL) return; context->orig_timerlat_period_us = OSNOISE_TIME_INIT_VAL; } /* * osnoise_get_stop_us - read and save the original "stop_tracing_us" */ static long long osnoise_get_stop_us(struct osnoise_context *context) { long long stop_us; if (context->stop_us != OSNOISE_OPTION_INIT_VAL) return context->stop_us; if (context->orig_stop_us != OSNOISE_OPTION_INIT_VAL) return context->orig_stop_us; stop_us = osnoise_read_ll_config("osnoise/stop_tracing_us"); if (stop_us < 0) goto out_err; context->orig_stop_us = stop_us; return stop_us; out_err: return OSNOISE_OPTION_INIT_VAL; } /* * osnoise_set_stop_us - set "stop_tracing_us" */ int osnoise_set_stop_us(struct osnoise_context *context, long long stop_us) { long long curr_stop_us = osnoise_get_stop_us(context); int retval; if (curr_stop_us == OSNOISE_OPTION_INIT_VAL) return -1; retval = osnoise_write_ll_config("osnoise/stop_tracing_us", stop_us); if (retval < 0) return -1; context->stop_us = stop_us; return 0; } /* * osnoise_restore_stop_us - restore the original "stop_tracing_us" */ void osnoise_restore_stop_us(struct osnoise_context *context) { int retval; if (context->orig_stop_us == OSNOISE_OPTION_INIT_VAL) return; if (context->orig_stop_us == context->stop_us) goto out_done; retval = osnoise_write_ll_config("osnoise/stop_tracing_us", context->orig_stop_us); if (retval < 0) err_msg("Could not restore original osnoise stop_us\n"); out_done: context->stop_us = OSNOISE_OPTION_INIT_VAL; } /* * osnoise_put_stop_us - restore original values and cleanup data */ void osnoise_put_stop_us(struct osnoise_context *context) { osnoise_restore_stop_us(context); if (context->orig_stop_us == OSNOISE_OPTION_INIT_VAL) return; context->orig_stop_us = OSNOISE_OPTION_INIT_VAL; } /* * osnoise_get_stop_total_us - read and save the original "stop_tracing_total_us" */ static long long osnoise_get_stop_total_us(struct osnoise_context *context) { long long stop_total_us; if (context->stop_total_us != OSNOISE_OPTION_INIT_VAL) return context->stop_total_us; if (context->orig_stop_total_us != OSNOISE_OPTION_INIT_VAL) return context->orig_stop_total_us; stop_total_us = osnoise_read_ll_config("osnoise/stop_tracing_total_us"); if (stop_total_us < 0) goto out_err; context->orig_stop_total_us = stop_total_us; return stop_total_us; out_err: return OSNOISE_OPTION_INIT_VAL; } /* * osnoise_set_stop_total_us - set "stop_tracing_total_us" */ int osnoise_set_stop_total_us(struct osnoise_context *context, long long stop_total_us) { long long curr_stop_total_us = osnoise_get_stop_total_us(context); int retval; if (curr_stop_total_us == OSNOISE_OPTION_INIT_VAL) return -1; retval = osnoise_write_ll_config("osnoise/stop_tracing_total_us", stop_total_us); if (retval < 0) return -1; context->stop_total_us = stop_total_us; return 0; } /* * osnoise_restore_stop_total_us - restore the original "stop_tracing_total_us" */ void osnoise_restore_stop_total_us(struct osnoise_context *context) { int retval; if (context->orig_stop_total_us == OSNOISE_OPTION_INIT_VAL) return; if (context->orig_stop_total_us == context->stop_total_us) goto out_done; retval = osnoise_write_ll_config("osnoise/stop_tracing_total_us", context->orig_stop_total_us); if (retval < 0) err_msg("Could not restore original osnoise stop_total_us\n"); out_done: context->stop_total_us = OSNOISE_OPTION_INIT_VAL; } /* * osnoise_put_stop_total_us - restore original values and cleanup data */ void osnoise_put_stop_total_us(struct osnoise_context *context) { osnoise_restore_stop_total_us(context); if (context->orig_stop_total_us == OSNOISE_OPTION_INIT_VAL) return; context->orig_stop_total_us = OSNOISE_OPTION_INIT_VAL; } /* * osnoise_get_print_stack - read and save the original "print_stack" */ static long long osnoise_get_print_stack(struct osnoise_context *context) { long long print_stack; if (context->print_stack != OSNOISE_OPTION_INIT_VAL) return context->print_stack; if (context->orig_print_stack != OSNOISE_OPTION_INIT_VAL) return context->orig_print_stack; print_stack = osnoise_read_ll_config("osnoise/print_stack"); if (print_stack < 0) goto out_err; context->orig_print_stack = print_stack; return print_stack; out_err: return OSNOISE_OPTION_INIT_VAL; } /* * osnoise_set_print_stack - set "print_stack" */ int osnoise_set_print_stack(struct osnoise_context *context, long long print_stack) { long long curr_print_stack = osnoise_get_print_stack(context); int retval; if (curr_print_stack == OSNOISE_OPTION_INIT_VAL) return -1; retval = osnoise_write_ll_config("osnoise/print_stack", print_stack); if (retval < 0) return -1; context->print_stack = print_stack; return 0; } /* * osnoise_restore_print_stack - restore the original "print_stack" */ void osnoise_restore_print_stack(struct osnoise_context *context) { int retval; if (context->orig_print_stack == OSNOISE_OPTION_INIT_VAL) return; if (context->orig_print_stack == context->print_stack) goto out_done; retval = osnoise_write_ll_config("osnoise/print_stack", context->orig_print_stack); if (retval < 0) err_msg("Could not restore original osnoise print_stack\n"); out_done: context->print_stack = OSNOISE_OPTION_INIT_VAL; } /* * osnoise_put_print_stack - restore original values and cleanup data */ void osnoise_put_print_stack(struct osnoise_context *context) { osnoise_restore_print_stack(context); if (context->orig_print_stack == OSNOISE_OPTION_INIT_VAL) return; context->orig_print_stack = OSNOISE_OPTION_INIT_VAL; } /* * osnoise_get_tracing_thresh - read and save the original "tracing_thresh" */ static long long osnoise_get_tracing_thresh(struct osnoise_context *context) { long long tracing_thresh; if (context->tracing_thresh != OSNOISE_OPTION_INIT_VAL) return context->tracing_thresh; if (context->orig_tracing_thresh != OSNOISE_OPTION_INIT_VAL) return context->orig_tracing_thresh; tracing_thresh = osnoise_read_ll_config("tracing_thresh"); if (tracing_thresh < 0) goto out_err; context->orig_tracing_thresh = tracing_thresh; return tracing_thresh; out_err: return OSNOISE_OPTION_INIT_VAL; } /* * osnoise_set_tracing_thresh - set "tracing_thresh" */ int osnoise_set_tracing_thresh(struct osnoise_context *context, long long tracing_thresh) { long long curr_tracing_thresh = osnoise_get_tracing_thresh(context); int retval; if (curr_tracing_thresh == OSNOISE_OPTION_INIT_VAL) return -1; retval = osnoise_write_ll_config("tracing_thresh", tracing_thresh); if (retval < 0) return -1; context->tracing_thresh = tracing_thresh; return 0; } /* * osnoise_restore_tracing_thresh - restore the original "tracing_thresh" */ void osnoise_restore_tracing_thresh(struct osnoise_context *context) { int retval; if (context->orig_tracing_thresh == OSNOISE_OPTION_INIT_VAL) return; if (context->orig_tracing_thresh == context->tracing_thresh) goto out_done; retval = osnoise_write_ll_config("tracing_thresh", context->orig_tracing_thresh); if (retval < 0) err_msg("Could not restore original tracing_thresh\n"); out_done: context->tracing_thresh = OSNOISE_OPTION_INIT_VAL; } /* * osnoise_put_tracing_thresh - restore original values and cleanup data */ void osnoise_put_tracing_thresh(struct osnoise_context *context) { osnoise_restore_tracing_thresh(context); if (context->orig_tracing_thresh == OSNOISE_OPTION_INIT_VAL) return; context->orig_tracing_thresh = OSNOISE_OPTION_INIT_VAL; } static int osnoise_options_get_option(char *option) { char *options = tracefs_instance_file_read(NULL, "osnoise/options", NULL); char no_option[128]; int retval = 0; char *opt; if (!options) return OSNOISE_OPTION_INIT_VAL; /* * Check first if the option is disabled. */ snprintf(no_option, sizeof(no_option), "NO_%s", option); opt = strstr(options, no_option); if (opt) goto out_free; /* * Now that it is not disabled, if the string is there, it is * enabled. If the string is not there, the option does not exist. */ opt = strstr(options, option); if (opt) retval = 1; else retval = OSNOISE_OPTION_INIT_VAL; out_free: free(options); return retval; } static int osnoise_options_set_option(char *option, bool onoff) { char no_option[128]; if (onoff) return tracefs_instance_file_write(NULL, "osnoise/options", option); snprintf(no_option, sizeof(no_option), "NO_%s", option); return tracefs_instance_file_write(NULL, "osnoise/options", no_option); } static int osnoise_get_irq_disable(struct osnoise_context *context) { if (context->opt_irq_disable != OSNOISE_OPTION_INIT_VAL) return context->opt_irq_disable; if (context->orig_opt_irq_disable != OSNOISE_OPTION_INIT_VAL) return context->orig_opt_irq_disable; context->orig_opt_irq_disable = osnoise_options_get_option("OSNOISE_IRQ_DISABLE"); return context->orig_opt_irq_disable; } int osnoise_set_irq_disable(struct osnoise_context *context, bool onoff) { int opt_irq_disable = osnoise_get_irq_disable(context); int retval; if (opt_irq_disable == OSNOISE_OPTION_INIT_VAL) return -1; if (opt_irq_disable == onoff) return 0; retval = osnoise_options_set_option("OSNOISE_IRQ_DISABLE", onoff); if (retval < 0) return -1; context->opt_irq_disable = onoff; return 0; } static void osnoise_restore_irq_disable(struct osnoise_context *context) { int retval; if (context->orig_opt_irq_disable == OSNOISE_OPTION_INIT_VAL) return; if (context->orig_opt_irq_disable == context->opt_irq_disable) goto out_done; retval = osnoise_options_set_option("OSNOISE_IRQ_DISABLE", context->orig_opt_irq_disable); if (retval < 0) err_msg("Could not restore original OSNOISE_IRQ_DISABLE option\n"); out_done: context->orig_opt_irq_disable = OSNOISE_OPTION_INIT_VAL; } static void osnoise_put_irq_disable(struct osnoise_context *context) { osnoise_restore_irq_disable(context); if (context->orig_opt_irq_disable == OSNOISE_OPTION_INIT_VAL) return; context->orig_opt_irq_disable = OSNOISE_OPTION_INIT_VAL; } static int osnoise_get_workload(struct osnoise_context *context) { if (context->opt_workload != OSNOISE_OPTION_INIT_VAL) return context->opt_workload; if (context->orig_opt_workload != OSNOISE_OPTION_INIT_VAL) return context->orig_opt_workload; context->orig_opt_workload = osnoise_options_get_option("OSNOISE_WORKLOAD"); return context->orig_opt_workload; } int osnoise_set_workload(struct osnoise_context *context, bool onoff) { int opt_workload = osnoise_get_workload(context); int retval; if (opt_workload == OSNOISE_OPTION_INIT_VAL) return -1; if (opt_workload == onoff) return 0; retval = osnoise_options_set_option("OSNOISE_WORKLOAD", onoff); if (retval < 0) return -2; context->opt_workload = onoff; return 0; } static void osnoise_restore_workload(struct osnoise_context *context) { int retval; if (context->orig_opt_workload == OSNOISE_OPTION_INIT_VAL) return; if (context->orig_opt_workload == context->opt_workload) goto out_done; retval = osnoise_options_set_option("OSNOISE_WORKLOAD", context->orig_opt_workload); if (retval < 0) err_msg("Could not restore original OSNOISE_WORKLOAD option\n"); out_done: context->orig_opt_workload = OSNOISE_OPTION_INIT_VAL; } static void osnoise_put_workload(struct osnoise_context *context) { osnoise_restore_workload(context); if (context->orig_opt_workload == OSNOISE_OPTION_INIT_VAL) return; context->orig_opt_workload = OSNOISE_OPTION_INIT_VAL; } /* * enable_osnoise - enable osnoise tracer in the trace_instance */ int enable_osnoise(struct trace_instance *trace) { return enable_tracer_by_name(trace->inst, "osnoise"); } /* * enable_timerlat - enable timerlat tracer in the trace_instance */ int enable_timerlat(struct trace_instance *trace) { return enable_tracer_by_name(trace->inst, "timerlat"); } enum { FLAG_CONTEXT_NEWLY_CREATED = (1 << 0), FLAG_CONTEXT_DELETED = (1 << 1), }; /* * osnoise_get_context - increase the usage of a context and return it */ int osnoise_get_context(struct osnoise_context *context) { int ret; if (context->flags & FLAG_CONTEXT_DELETED) { ret = -1; } else { context->ref++; ret = 0; } return ret; } /* * osnoise_context_alloc - alloc an osnoise_context * * The osnoise context contains the information of the "osnoise/" configs. * It is used to set and restore the config. */ struct osnoise_context *osnoise_context_alloc(void) { struct osnoise_context *context; context = calloc(1, sizeof(*context)); if (!context) return NULL; context->orig_stop_us = OSNOISE_OPTION_INIT_VAL; context->stop_us = OSNOISE_OPTION_INIT_VAL; context->orig_stop_total_us = OSNOISE_OPTION_INIT_VAL; context->stop_total_us = OSNOISE_OPTION_INIT_VAL; context->orig_print_stack = OSNOISE_OPTION_INIT_VAL; context->print_stack = OSNOISE_OPTION_INIT_VAL; context->orig_tracing_thresh = OSNOISE_OPTION_INIT_VAL; context->tracing_thresh = OSNOISE_OPTION_INIT_VAL; context->orig_opt_irq_disable = OSNOISE_OPTION_INIT_VAL; context->opt_irq_disable = OSNOISE_OPTION_INIT_VAL; context->orig_opt_workload = OSNOISE_OPTION_INIT_VAL; context->opt_workload = OSNOISE_OPTION_INIT_VAL; osnoise_get_context(context); return context; } /* * osnoise_put_context - put the osnoise_put_context * * If there is no other user for the context, the original data * is restored. */ void osnoise_put_context(struct osnoise_context *context) { if (--context->ref < 1) context->flags |= FLAG_CONTEXT_DELETED; if (!(context->flags & FLAG_CONTEXT_DELETED)) return; osnoise_put_cpus(context); osnoise_put_runtime_period(context); osnoise_put_stop_us(context); osnoise_put_stop_total_us(context); osnoise_put_timerlat_period_us(context); osnoise_put_print_stack(context); osnoise_put_tracing_thresh(context); osnoise_put_irq_disable(context); osnoise_put_workload(context); free(context); } /* * osnoise_destroy_tool - disable trace, restore configs and free data */ void osnoise_destroy_tool(struct osnoise_tool *top) { if (!top) return; trace_instance_destroy(&top->trace); if (top->context) osnoise_put_context(top->context); free(top); } /* * osnoise_init_tool - init an osnoise tool * * It allocs data, create a context to store data and * creates a new trace instance for the tool. */ struct osnoise_tool *osnoise_init_tool(char *tool_name) { struct osnoise_tool *top; int retval; top = calloc(1, sizeof(*top)); if (!top) return NULL; top->context = osnoise_context_alloc(); if (!top->context) goto out_err; retval = trace_instance_init(&top->trace, tool_name); if (retval) goto out_err; return top; out_err: osnoise_destroy_tool(top); return NULL; } /* * osnoise_init_trace_tool - init a tracer instance to trace osnoise events */ struct osnoise_tool *osnoise_init_trace_tool(char *tracer) { struct osnoise_tool *trace; int retval; trace = osnoise_init_tool("osnoise_trace"); if (!trace) return NULL; retval = tracefs_event_enable(trace->trace.inst, "osnoise", NULL); if (retval < 0 && !errno) { err_msg("Could not find osnoise events\n"); goto out_err; } retval = enable_tracer_by_name(trace->trace.inst, tracer); if (retval) { err_msg("Could not enable %s tracer for tracing\n", tracer); goto out_err; } return trace; out_err: osnoise_destroy_tool(trace); return NULL; } bool osnoise_trace_is_off(struct osnoise_tool *tool, struct osnoise_tool *record) { /* * The tool instance is always present, it is the one used to collect * data. */ if (!tracefs_trace_is_on(tool->trace.inst)) return true; /* * The trace record instance is only enabled when -t is set. IOW, when the system * is tracing. */ return record && !tracefs_trace_is_on(record->trace.inst); } /* * osnoise_report_missed_events - report number of events dropped by trace * buffer */ void osnoise_report_missed_events(struct osnoise_tool *tool) { unsigned long long total_events; if (tool->trace.missed_events == UINT64_MAX) printf("unknown number of events missed, results might not be accurate\n"); else if (tool->trace.missed_events > 0) { total_events = tool->trace.processed_events + tool->trace.missed_events; printf("%lld (%.2f%%) events missed, results might not be accurate\n", tool->trace.missed_events, (double) tool->trace.missed_events / total_events * 100.0); } } /* * osnoise_apply_config - apply common configs to the initialized tool */ int osnoise_apply_config(struct osnoise_tool *tool, struct osnoise_params *params) { int retval; if (!params->sleep_time) params->sleep_time = 1; retval = osnoise_set_cpus(tool->context, params->cpus ? params->cpus : "all"); if (retval) { err_msg("Failed to apply CPUs config\n"); goto out_err; } if (params->runtime || params->period) { retval = osnoise_set_runtime_period(tool->context, params->runtime, params->period); } else { retval = osnoise_set_runtime_period(tool->context, DEFAULT_SAMPLE_PERIOD, DEFAULT_SAMPLE_RUNTIME); } if (retval) { err_msg("Failed to set runtime and/or period\n"); goto out_err; } retval = osnoise_set_stop_us(tool->context, params->stop_us); if (retval) { err_msg("Failed to set stop us\n"); goto out_err; } retval = osnoise_set_stop_total_us(tool->context, params->stop_total_us); if (retval) { err_msg("Failed to set stop total us\n"); goto out_err; } retval = osnoise_set_tracing_thresh(tool->context, params->threshold); if (retval) { err_msg("Failed to set tracing_thresh\n"); goto out_err; } if (params->hk_cpus) { retval = sched_setaffinity(getpid(), sizeof(params->hk_cpu_set), ¶ms->hk_cpu_set); if (retval == -1) { err_msg("Failed to set rtla to the house keeping CPUs\n"); goto out_err; } } else if (params->cpus) { /* * Even if the user do not set a house-keeping CPU, try to * move rtla to a CPU set different to the one where the user * set the workload to run. * * No need to check results as this is an automatic attempt. */ auto_house_keeping(¶ms->monitored_cpus); } retval = osnoise_set_workload(tool->context, true); if (retval < -1) { err_msg("Failed to set OSNOISE_WORKLOAD option\n"); goto out_err; } return 0; out_err: return -1; } static void osnoise_usage(int err) { int i; static const char *msg[] = { "", "osnoise version " VERSION, "", " usage: [rtla] osnoise [MODE] ...", "", " modes:", " top - prints the summary from osnoise tracer", " hist - prints a histogram of osnoise samples", "", "if no MODE is given, the top mode is called, passing the arguments", NULL, }; for (i = 0; msg[i]; i++) fprintf(stderr, "%s\n", msg[i]); exit(err); } int osnoise_main(int argc, char *argv[]) { if (argc == 0) goto usage; /* * if osnoise was called without any argument, run the * default cmdline. */ if (argc == 1) { osnoise_top_main(argc, argv); exit(0); } if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { osnoise_usage(0); } else if (strncmp(argv[1], "-", 1) == 0) { /* the user skipped the tool, call the default one */ osnoise_top_main(argc, argv); exit(0); } else if (strcmp(argv[1], "top") == 0) { osnoise_top_main(argc-1, &argv[1]); exit(0); } else if (strcmp(argv[1], "hist") == 0) { osnoise_hist_main(argc-1, &argv[1]); exit(0); } usage: osnoise_usage(1); exit(1); } int hwnoise_main(int argc, char *argv[]) { osnoise_top_main(argc, argv); exit(0); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
You can’t perform that action at this time.