RTLA: An interface for osnoise/timerlat tracers
v3 cover RTLA: An interface for osnoise/timerlat tracers
The rtla(1) is a meta-tool that includes a set of commands that aims to analyze the real-time properties of Linux. But instead of testing Linux as a black box, rtla leverages kernel tracing capabilities to provide precise information about the properties and root causes of unexpected results.
To start, it presents an interface to the osnoise and timerlat tracers. In the future, it will also serve as home to the rtsl [1] and other latency/noise tracers.
The first five patches are a re-send of [2] that enable multiple instances for osnoise/timerlat tracers. They are required to run the -T option - to save a trace with osnoise: events for debugging.
The next seven patches are rtla, rtla osnoise, and rtla timerlat.
The following patches are the man pages for the tools.
To compile rtla on fedora you need:
$ git clone git://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git $ cd libtraceevent/ $ make $ sudo make install $ cd .. $ git clone git://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git $ cd libtracefs/ $ make $ sudo make install $ cd .. $ sudo dnf install asciidoc xmlto procps-devel $ cd $linux/tools/tracing/rtla/ $ make $ sudo make install
This tool was be discussed at the RT-MC during LPC2021.
[1] rtsl: https://github.com/bristot/rtsl/
[2] https://lore.kernel.org/lkml/[email protected]/
[3] https://youtu.be/cZUzc0U1jJ4
Changes from v2:
- Fix the miss conception of the "size" for kernel histograms (Steven/Tom)
- Change the --skip-zeros to --with-zeros option as the former is better for humans (and the latter for computers to plot charts).
- A lot of checkpatch fixes for the user-space part.
Changes from v1:
- Fixes -t options on osnoise tracers (-t means --trace for all tools now)
- Fixes --bucket-size references (not --bucket_size)
Daniel Bristot de Oliveira (19):
trace/osnoise: Do not follow tracing_cpumask trace/osnoise: Split workload start from the tracer start trace/osnoise: Use start/stop_per_cpu_kthreads() on
osnoise_cpus_write()
trace/osnoise: Support a list of trace_array *tr trace/osnoise: Allow multiple instances of the same tracer
rtla: Real-Time Linux Analysis tool
rtla: Helper functions for rtla
rtla: Add osnoise tool
rtla/osnoise: Add osnoise top mode
rtla/osnoise: Add the hist mode
rtla: Add timerlat tool and timelart top mode rtla/timerlat: Add timerlat hist mode
rtla: Add Documentation
rtla: Add rtla osnoise man page
rtla: Add rtla osnoise top documentation
rtla: Add rtla osnoise hist documentation
rtla: Add rtla timerlat documentation
rtla: Add rtla timerlat top documentation
rtla: Add rtla timerlat hist documentation
kernel/trace/trace_osnoise.c | 410 ++++++--- tools/tracing/rtla/Documentation/Makefile | 223 +++++ .../tracing/rtla/Documentation/asciidoc.conf | 118 +++ .../rtla/Documentation/manpage-base.xsl | 35 + .../rtla/Documentation/manpage-normal.xsl | 13 + .../rtla/Documentation/rtla-osnoise-hist.txt | 117 +++ .../rtla/Documentation/rtla-osnoise-top.txt | 98 ++ .../rtla/Documentation/rtla-osnoise.txt | 68 ++ .../rtla/Documentation/rtla-timerlat-hist.txt | 162 ++++ .../rtla/Documentation/rtla-timerlat-top.txt | 181 ++++ .../rtla/Documentation/rtla-timerlat.txt | 65 ++ tools/tracing/rtla/Documentation/rtla.txt | 56 ++ tools/tracing/rtla/Documentation/utils.mk | 144 +++ tools/tracing/rtla/Makefile | 71 ++ tools/tracing/rtla/src/osnoise.c | 837 ++++++++++++++++++ tools/tracing/rtla/src/osnoise.h | 87 ++ tools/tracing/rtla/src/osnoise_hist.c | 783 ++++++++++++++++ tools/tracing/rtla/src/osnoise_top.c | 567 ++++++++++++ tools/tracing/rtla/src/rtla.c | 87 ++ tools/tracing/rtla/src/timerlat.c | 72 ++ tools/tracing/rtla/src/timerlat.h | 4 + tools/tracing/rtla/src/timerlat_hist.c | 780 ++++++++++++++++ tools/tracing/rtla/src/timerlat_top.c | 581 ++++++++++++ tools/tracing/rtla/src/trace.c | 219 +++++ tools/tracing/rtla/src/trace.h | 27 + tools/tracing/rtla/src/utils.c | 433 +++++++++ tools/tracing/rtla/src/utils.h | 56 ++ 27 files changed, 6173 insertions(+), 121 deletions(-) create mode 100644 tools/tracing/rtla/Documentation/Makefile create mode 100644 tools/tracing/rtla/Documentation/asciidoc.conf create mode 100644 tools/tracing/rtla/Documentation/manpage-base.xsl create mode 100644 tools/tracing/rtla/Documentation/manpage-normal.xsl create mode 100644 tools/tracing/rtla/Documentation/rtla-osnoise-hist.txt create mode 100644 tools/tracing/rtla/Documentation/rtla-osnoise-top.txt create mode 100644 tools/tracing/rtla/Documentation/rtla-osnoise.txt create mode 100644 tools/tracing/rtla/Documentation/rtla-timerlat-hist.txt create mode 100644 tools/tracing/rtla/Documentation/rtla-timerlat-top.txt create mode 100644 tools/tracing/rtla/Documentation/rtla-timerlat.txt create mode 100644 tools/tracing/rtla/Documentation/rtla.txt create mode 100644 tools/tracing/rtla/Documentation/utils.mk create mode 100644 tools/tracing/rtla/Makefile create mode 100644 tools/tracing/rtla/src/osnoise.c create mode 100644 tools/tracing/rtla/src/osnoise.h create mode 100644 tools/tracing/rtla/src/osnoise_hist.c create mode 100644 tools/tracing/rtla/src/osnoise_top.c create mode 100644 tools/tracing/rtla/src/rtla.c create mode 100644 tools/tracing/rtla/src/timerlat.c create mode 100644 tools/tracing/rtla/src/timerlat.h create mode 100644 tools/tracing/rtla/src/timerlat_hist.c create mode 100644 tools/tracing/rtla/src/timerlat_top.c create mode 100644 tools/tracing/rtla/src/trace.c create mode 100644 tools/tracing/rtla/src/trace.h create mode 100644 tools/tracing/rtla/src/utils.c create mode 100644 tools/tracing/rtla/src/utils.h
Signature · 1 line
2.31.1
PATCH v3 1/19 trace/osnoise: Do not follow tracing_cpumask
In preparation to support multiple instances, decople the osnoise/timelat workload from instance specific tracing_cpumask.
Different instances can have conflicing cpumasks, making osnoise workload management needlessly complex. Osnoise already have its global cpu mask.
I also thought about using the first instance mask, but the "first" instance could be removed before the others.
This also fixes the problem that changing the tracing_mask was not re-starting the trace.
--- kernel/trace/trace_osnoise.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-)
kernel/trace/trace_osnoise.c +7 -18
@@ -1553,13 +1553,10 @@ static int start_per_cpu_kthreads(struct trace_array *tr)cpus_read_lock ();/* -* Run only on CPUs in which trace and osnoise are allowed to run. +* Run only on online CPUs in which trace and osnoise are allowed to +* run. */ -cpumask_and (current_mask, tr->tracing_cpumask, &osnoise_cpumask); -/* -* And the CPU is online. -*/ -cpumask_and (current_mask, cpu_online_mask, current_mask); +cpumask_and (current_mask, cpu_online_mask, &osnoise_cpumask);for_each_possible_cpu (cpu)per_cpu (per_cpu_osnoise_var, cpu).kthread =NULL ;
@@ -1580,10 +1577,8 @@ static int start_per_cpu_kthreads(struct trace_array *tr)#ifdef CONFIG_HOTPLUG_CPU static void osnoise_hotplug_workfn (struct work_struct *dummy) { -struct trace_array *tr = osnoise_trace;unsigned int cpu =smp_processor_id (); -mutex_lock (&trace_types_lock);if (!osnoise_busy)
@@ -1595,9 +1590,6 @@ static void osnoise_hotplug_workfn(struct work_struct *dummy)if (!cpumask_test_cpu (cpu, &osnoise_cpumask)) goto out_unlock; -if (!cpumask_test_cpu (cpu, tr->tracing_cpumask)) - goto out_unlock; -start_kthread (cpu); out_unlock:
@@ -1700,13 +1692,10 @@ static void osnoise_tracer_stop(struct trace_array *tr);* interface to the osnoise trace. By default, it lists all CPUs, * in this way, allowing osnoise threads to run on any online CPU * of the system. It serves to restrict the execution of osnoise to the -* set of CPUs writing via this interface. Note that osnoise also -* respects the "tracing_cpumask." Hence, osnoise threads will run only -* on the set of CPUs allowed here AND on "tracing_cpumask." Why not -* have just "tracing_cpumask?" Because the user might be interested -* in tracing what is running on other CPUs. For instance, one might -* run osnoise in one HT CPU while observing what is running on the -* sibling HT CPU. +* set of CPUs writing via this interface. Why not use "tracing_cpumask"? +* Because the user might be interested in tracing what is running on +* other CPUs. For instance, one might run osnoise in one HT CPU +* while observing what is running on the sibling HT CPU. */ static ssize_t osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,
Signature · 1 line
2.31.1
PATCH v3 2/19 trace/osnoise: Split workload start from the tracer start
In reply to Daniel Bristot de OliveiraIn preparation from supporting multiple trace instances, create workload start/stop specific functions.
No functional change.
--- kernel/trace/trace_osnoise.c | 53 ++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 20 deletions(-)
kernel/trace/trace_osnoise.c +33 -20
@@ -1545,7 +1545,7 @@ static int start_kthread(unsigned int cpu)* This starts the kernel thread that will look for osnoise on many * cpus. */ -static int start_per_cpu_kthreads (struct trace_array *tr) +static int start_per_cpu_kthreads (void ) {struct cpumask *current_mask = &save_cpumask;int retval =0 ;
@@ -1678,8 +1678,8 @@ osnoise_cpus_read(struct file *filp, char __user *ubuf, size_t count,return count; } -static void osnoise_tracer_start (struct trace_array *tr); -static void osnoise_tracer_stop (struct trace_array *tr); +static int osnoise_workload_start (void ); +static void osnoise_workload_stop (void );/* * osnoise_cpus_write - Write function for "cpus" entry
@@ -1701,7 +1701,6 @@ static ssize_t osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count, loff_t *ppos) { - struct trace_array *tr = osnoise_trace; cpumask_var_t osnoise_cpumask_new;int running, err;char buf[256 ];
@@ -1726,7 +1725,7 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,mutex_lock (&trace_types_lock); running = osnoise_busy;if (running) -osnoise_tracer_stop (tr); +osnoise_workload_stop ();mutex_lock (&interface_lock);/*
@@ -1740,7 +1739,7 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,mutex_unlock (&interface_lock);if (running) -osnoise_tracer_start (tr); +osnoise_workload_start ();mutex_unlock (&trace_types_lock);free_cpumask_var (osnoise_cpumask_new);
@@ -1921,7 +1920,10 @@ static int osnoise_hook_events(void)return -EINVAL ; } -static int __osnoise_tracer_start (struct trace_array *tr) +/* +* osnoise_workload_start - start the workload and hook to events +*/ +static int osnoise_workload_start (void ) {int retval;
@@ -1936,7 +1938,7 @@ static int __osnoise_tracer_start(struct trace_array *tr)barrier (); trace_osnoise_callback_enabled = true; - retval =start_per_cpu_kthreads (tr); + retval =start_per_cpu_kthreads ();if (retval) {unhook_irq_events ();return retval;
@@ -1947,6 +1949,26 @@ static int __osnoise_tracer_start(struct trace_array *tr)return 0 ; } +/* +* osnoise_workload_stop - stop the workload and unhook the events +*/ +static void osnoise_workload_stop (void ) +{ +if (!osnoise_busy) +return ; + + trace_osnoise_callback_enabled = false; +barrier (); + +stop_per_cpu_kthreads (); + +unhook_irq_events (); +unhook_softirq_events (); +unhook_thread_events (); + + osnoise_busy = false; +} +static void osnoise_tracer_start (struct trace_array *tr) {int retval;
@@ -1954,7 +1976,7 @@ static void osnoise_tracer_start(struct trace_array *tr)if (osnoise_busy)return ; - retval =__osnoise_tracer_start (tr); + retval =osnoise_workload_start ();if (retval)pr_err (BANNER "Error starting osnoise tracer\n" );
@@ -1965,16 +1987,7 @@ static void osnoise_tracer_stop(struct trace_array *tr)if (!osnoise_busy)return ; - trace_osnoise_callback_enabled = false; -barrier (); - -stop_per_cpu_kthreads (); - -unhook_irq_events (); -unhook_softirq_events (); -unhook_thread_events (); - - osnoise_busy = false; +osnoise_workload_stop (); }static int osnoise_tracer_init (struct trace_array *tr)
@@ -2017,7 +2030,7 @@ static void timerlat_tracer_start(struct trace_array *tr) osnoise_data.timerlat_tracer =1 ; - retval =__osnoise_tracer_start (tr); + retval =osnoise_workload_start ();if (retval) goto out_err;
Signature · 1 line
2.31.1
PATCH v3 3/19 trace/osnoise: Use start/stop_per_cpu_kthreads() on osnoise_cpus_write()
In reply to Daniel Bristot de OliveiraWhen writing a new CPU mask via osnoise/cpus, if the tracer is running, the workload is restarted to follow the new cpumask. The restart is currently done using osnoise_workload_start/stop(), which disables the workload *and* the instrumentation. However, disabling the instrumentation is not necessary.
Calling start/stop_per_cpu_kthreads() is enough to apply the new osnoise/cpus config.
No functional change.
--- kernel/trace/trace_osnoise.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
kernel/trace/trace_osnoise.c +2 -5
@@ -1678,9 +1678,6 @@ osnoise_cpus_read(struct file *filp, char __user *ubuf, size_t count,return count; } -static int osnoise_workload_start (void ); -static void osnoise_workload_stop (void ); -/* * osnoise_cpus_write - Write function for "cpus" entry * @filp: The active open file structure
@@ -1725,7 +1722,7 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,mutex_lock (&trace_types_lock); running = osnoise_busy;if (running) -osnoise_workload_stop (); +stop_per_cpu_kthreads ();mutex_lock (&interface_lock);/*
@@ -1739,7 +1736,7 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,mutex_unlock (&interface_lock);if (running) -osnoise_workload_start (); +start_per_cpu_kthreads ();mutex_unlock (&trace_types_lock);free_cpumask_var (osnoise_cpumask_new);
Signature · 1 line
2.31.1
PATCH v3 4/19 trace/osnoise: Support a list of trace_array *tr
In reply to Daniel Bristot de Oliveiraosnoise/timerlat were built to run a single instance, and for this, a single variable is enough to store the current struct trace_array *tr with information about the tracing instance. This is done via the *osnoise_trace variable. A trace_array represents a trace instance.
In preparation to support multiple instances, replace the *osnoise_trace variable with an RCU protected list of instances.
The operations that refer to an instance now propagate to all elements of the list (all instances).
Also, replace the osnoise_busy variable with a check if the list has elements (busy).
No functional change is expected with this patch, i.e., only one instance is allowed yet.
--- kernel/trace/trace_osnoise.c | 253 +++++++++++++++++++++++++---------- 1 file changed, 184 insertions(+), 69 deletions(-)
kernel/trace/trace_osnoise.c +184 -69
@@ -38,8 +38,6 @@#define CREATE_TRACE_POINTS #include <trace/events/osnoise.h> -static struct trace_array *osnoise_trace; -/* * Default values. */
@@ -50,6 +48,73 @@ static struct trace_array *osnoise_trace;#define DEFAULT_TIMERLAT_PERIOD 1000/* 1ms */ #define DEFAULT_TIMERLAT_PRIO 95/* FIFO 95 */ +/* +* trace_array of the enabled osnoise/timerlat instances. +*/ +struct osnoise_instance { +struct list_head list; +struct trace_array *tr; +}; +struct list_head osnoise_instances; + +static bool osnoise_has_registered_instances (void ) +{ +return !!list_first_or_null_rcu (&osnoise_instances, + struct osnoise_instance, + list); +} + +/* +* osnoise_register_instance - register a new trace instance +* +* Register a trace_array *tr in the list of instances running +* osnoise/timerlat tracers. +*/ +static int osnoise_register_instance (struct trace_array *tr) +{ +struct osnoise_instance *inst; + + inst =kmalloc (sizeof (*inst),GFP_KERNEL ); +if (!inst) +return -ENOMEM ; + +INIT_LIST_HEAD_RCU (&inst->list); + inst->tr = tr; +list_add_tail_rcu (&inst->list, &osnoise_instances); + +return 0 ; +} + +/* +* osnoise_unregister_instance - unregister a registered trace instance +* +* Remove the trace_array *tr from the list of instances running +* osnoise/timerlat tracers. +*/ +static void osnoise_unregister_instance (struct trace_array *tr) +{ +struct osnoise_instance *inst; +int found =0 ; + +rcu_read_lock (); +list_for_each_entry_rcu (inst, &osnoise_instances, list) { +if (inst->tr == tr) { +list_del_rcu (&inst->list); + found =1 ; +break ; + } + } +rcu_read_unlock (); + +if (!found) { +WARN ("osnoise unregister did not find tr %s\n" , tr->name); +return ; + } + +synchronize_rcu (); +kfree (inst); +} +/* * NMI runtime info. */
@@ -248,11 +313,6 @@ static struct osnoise_data {#endif }; -/* -* Boolean variable used to inform that the tracer is currently sampling. -*/ -static bool osnoise_busy; -#ifdef CONFIG_PREEMPT_RT /* * Print the osnoise header info.
@@ -315,19 +375,24 @@ static void print_osnoise_headers(struct seq_file *s)* osnoise_taint - report an osnoise error. */ #define osnoise_taint (msg) ({ \ - struct trace_array *tr = osnoise_trace; \ + struct osnoise_instance *inst; \ + struct trace_buffer *buffer; \ \ - trace_array_printk_buf(tr->array_buffer.buffer, _THIS_IP_, msg); \ + rcu_read_lock(); \ + list_for_each_entry_rcu(inst, &osnoise_instances, list) { \ + buffer = inst->tr->array_buffer.buffer; \ + trace_array_printk_buf(buffer, _THIS_IP_, msg); \ + } \ + rcu_read_unlock(); \ osnoise_data.tainted = true; \ })/* * Record an osnoise_sample into the tracer buffer. */ -static void trace_osnoise_sample (struct osnoise_sample *sample) +static void +__trace_osnoise_sample (struct osnoise_sample *sample,struct trace_buffer *buffer) { -struct trace_array *tr = osnoise_trace; -struct trace_buffer *buffer = tr->array_buffer.buffer;struct trace_event_call *call = &event_osnoise;struct ring_buffer_event *event;struct osnoise_entry *entry;
@@ -350,6 +415,22 @@ static void trace_osnoise_sample(struct osnoise_sample *sample)trace_buffer_unlock_commit_nostack (buffer, event); } +/* +* Record an osnoise_sample on all osnoise instances. +*/ +static void trace_osnoise_sample (struct osnoise_sample *sample) +{ +struct osnoise_instance *inst; +struct trace_buffer *buffer; + +rcu_read_lock (); +list_for_each_entry_rcu (inst, &osnoise_instances, list) { + buffer = inst->tr->array_buffer.buffer; +__trace_osnoise_sample (sample, buffer); + } +rcu_read_unlock (); +} +#ifdef CONFIG_TIMERLAT_TRACER /* * Print the timerlat header info.
@@ -387,14 +468,10 @@ static void print_timerlat_headers(struct seq_file *s) }#endif /* CONFIG_PREEMPT_RT */ -/* -* Record an timerlat_sample into the tracer buffer. -*/ -static void trace_timerlat_sample (struct timerlat_sample *sample) +static void +__trace_timerlat_sample (struct timerlat_sample *sample,struct trace_buffer *buffer) { -struct trace_array *tr = osnoise_trace;struct trace_event_call *call = &event_osnoise; -struct trace_buffer *buffer = tr->array_buffer.buffer;struct ring_buffer_event *event;struct timerlat_entry *entry;
@@ -411,6 +488,22 @@ static void trace_timerlat_sample(struct timerlat_sample *sample)trace_buffer_unlock_commit_nostack (buffer, event); } +/* +* Record an timerlat_sample into the tracer buffer. +*/ +static void trace_timerlat_sample (struct timerlat_sample *sample) +{ +struct osnoise_instance *inst; +struct trace_buffer *buffer; + +rcu_read_lock (); +list_for_each_entry_rcu (inst, &osnoise_instances, list) { + buffer = inst->tr->array_buffer.buffer; +__trace_timerlat_sample (sample, buffer); + } +rcu_read_unlock (); +} +#ifdef CONFIG_STACKTRACE #define MAX_CALLS 256
@@ -450,29 +543,18 @@ static void timerlat_save_stack(int skip)return ; } -/* -* timerlat_dump_stack - dump a stack trace previously saved -* -* Dump a saved stack trace into the trace buffer. -*/ -static void timerlat_dump_stack (void ) + +static void +__timerlat_dump_stack (struct trace_buffer *buffer,struct trace_stack *fstack,unsigned int size) {struct trace_event_call *call = &event_osnoise; -struct trace_array *tr = osnoise_trace; -struct trace_buffer *buffer = tr->array_buffer.buffer;struct ring_buffer_event *event; -struct trace_stack *fstack;struct stack_entry *entry; -unsigned int size; - -preempt_disable_notrace (); - fstack =this_cpu_ptr (&trace_stack); - size = fstack->stack_size; event =trace_buffer_lock_reserve (buffer,TRACE_STACK ,sizeof (*entry) + size,tracing_gen_ctx ());if (!event) - goto out; +return ; entry =ring_buffer_event_data (event);
@@ -481,8 +563,29 @@ static void timerlat_dump_stack(void)if (!call_filter_check_discard (call, entry, buffer, event)) trace_buffer_unlock_commit_nostack(buffer, event); +} -out: +/* +* timerlat_dump_stack - dump a stack trace previously saved +*/ +static void timerlat_dump_stack (void ) +{ +struct osnoise_instance *inst; +struct trace_buffer *buffer; +struct trace_stack *fstack; +unsigned int size; + +preempt_disable_notrace (); + fstack =this_cpu_ptr (&trace_stack); + size = fstack->stack_size; + +rcu_read_lock (); +list_for_each_entry_rcu (inst, &osnoise_instances, list) { + buffer = inst->tr->array_buffer.buffer; +__timerlat_dump_stack (buffer, fstack, size); + + } +rcu_read_unlock ();preempt_enable_notrace (); }#else
@@ -1077,12 +1180,37 @@ diff_osn_sample_stats(struct osnoise_variables *osn_var, struct osnoise_sample **/ static __always_inline void osnoise_stop_tracing(void) { -struct trace_array *tr = osnoise_trace; +struct osnoise_instance *inst; +struct trace_array *tr; + +rcu_read_lock (); +list_for_each_entry_rcu (inst, &osnoise_instances, list) { + tr = inst->tr; +trace_array_printk_buf (tr->array_buffer.buffer, _THIS_IP_, +"stop tracing hit on cpu %d\n" ,smp_processor_id ()); + +tracer_tracing_off (tr); + } +rcu_read_unlock (); +} -trace_array_printk_buf (tr->array_buffer.buffer, _THIS_IP_, -"stop tracing hit on cpu %d\n" ,smp_processor_id ()); +/* +* notify_new_max_latency - Notify a new max latency via fsnotify interface. +*/ +void notify_new_max_latency (u64 latency) +{ +struct osnoise_instance *inst; +struct trace_array *tr; -tracer_tracing_off (tr); +rcu_read_lock (); +list_for_each_entry_rcu (inst, &osnoise_instances, list) { + tr = inst->tr; +if (tr->max_latency < latency) { + tr->max_latency = latency; +latency_fsnotify (tr); + } + } +rcu_read_unlock (); }/*
@@ -1096,7 +1224,6 @@ static __always_inline void osnoise_stop_tracing(void)static int run_osnoise (void ) {struct osnoise_variables *osn_var =this_cpu_osn_var (); -struct trace_array *tr = osnoise_trace;u64 start, sample, last_sample;u64 last_int_count, int_count;s64 noise =0 , max_noise =0 ;
@@ -1231,11 +1358,7 @@ static int run_osnoise(void)trace_osnoise_sample (&s); -/* Keep a running maximum ever recorded osnoise "latency" */ -if (max_noise > tr->max_latency) { - tr->max_latency = max_noise; -latency_fsnotify (tr); - } +notify_new_max_latency (max_noise);if (osnoise_data.stop_tracing_total)if (s.noise > osnoise_data.stop_tracing_total)
@@ -1293,7 +1416,6 @@ static int osnoise_main(void *data)static enum hrtimer_restart timerlat_irq (struct hrtimer *timer) {struct osnoise_variables *osn_var =this_cpu_osn_var (); -struct trace_array *tr = osnoise_trace;struct timerlat_variables *tlat;struct timerlat_sample s;u64 now;
@@ -1364,11 +1486,7 @@ static enum hrtimer_restart timerlat_irq(struct hrtimer *timer)trace_timerlat_sample (&s); -/* Keep a running maximum ever recorded os noise "latency" */ -if (diff > tr->max_latency) { - tr->max_latency = diff; -latency_fsnotify (tr); - } +notify_new_max_latency (diff);if (osnoise_data.stop_tracing)if (time_to_us (diff) >= osnoise_data.stop_tracing)
@@ -1581,7 +1699,7 @@ static void osnoise_hotplug_workfn(struct work_struct *dummy)mutex_lock (&trace_types_lock); -if (!osnoise_busy) +if (!osnoise_has_registered_instances ()) goto out_unlock_trace;mutex_lock (&interface_lock);
@@ -1716,11 +1834,10 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count, goto err_free;/* -* trace_types_lock is taken to avoid concurrency on start/stop -* and osnoise_busy. +* trace_types_lock is taken to avoid concurrency on start/stop. */ mutex_lock (&trace_types_lock); - running = osnoise_busy; + running =osnoise_has_registered_instances ();if (running)stop_per_cpu_kthreads ();
@@ -1941,8 +2058,6 @@ static int osnoise_workload_start(void)return retval; } - osnoise_busy = true; -return 0 ; }
@@ -1951,7 +2066,7 @@ static int osnoise_workload_start(void)*/ static void osnoise_workload_stop (void ) { -if (!osnoise_busy) +if (osnoise_has_registered_instances ())return ; trace_osnoise_callback_enabled = false;
@@ -1962,28 +2077,28 @@ static void osnoise_workload_stop(void)unhook_irq_events ();unhook_softirq_events ();unhook_thread_events (); - - osnoise_busy = false; }static void osnoise_tracer_start (struct trace_array *tr) {int retval; -if (osnoise_busy) +if (osnoise_has_registered_instances ())return ; retval =osnoise_workload_start ();if (retval)pr_err (BANNER "Error starting osnoise tracer\n" ); +osnoise_register_instance (tr); }static void osnoise_tracer_stop (struct trace_array *tr) { -if (!osnoise_busy) +if (!osnoise_has_registered_instances ())return ; +osnoise_unregister_instance (tr);osnoise_workload_stop (); }
@@ -1991,14 +2106,12 @@ static int osnoise_tracer_init(struct trace_array *tr) {/* Only allow one instance to enable this */ -if (osnoise_busy) +if (osnoise_has_registered_instances ())return -EBUSY ; - osnoise_trace = tr; tr->max_latency =0 ;osnoise_tracer_start (tr); -return 0 ; }
@@ -2022,7 +2135,7 @@ static void timerlat_tracer_start(struct trace_array *tr) {int retval; -if (osnoise_busy) +if (osnoise_has_registered_instances ())return ; osnoise_data.timerlat_tracer =1 ;
@@ -2031,6 +2144,8 @@ static void timerlat_tracer_start(struct trace_array *tr)if (retval) goto out_err; +osnoise_register_instance (tr); +return ; out_err:pr_err (BANNER "Error starting timerlat tracer\n" );
@@ -2040,7 +2155,7 @@ static void timerlat_tracer_stop(struct trace_array *tr) {int cpu; -if (!osnoise_busy) +if (!osnoise_has_registered_instances ())return ;for_each_online_cpu (cpu)
@@ -2054,11 +2169,9 @@ static void timerlat_tracer_stop(struct trace_array *tr)static int timerlat_tracer_init (struct trace_array *tr) {/* Only allow one instance to enable this */ -if (osnoise_busy) +if (osnoise_has_registered_instances ())return -EBUSY ; - osnoise_trace = tr; - tr->max_latency =0 ;timerlat_tracer_start (tr);
@@ -2105,6 +2218,8 @@ __init static int init_osnoise_tracer(void)#endif osnoise_init_hotplug_support (); +INIT_LIST_HEAD_RCU (&osnoise_instances); +init_tracefs ();return 0 ;
Signature · 1 line
2.31.1
PATCH v3 5/19 trace/osnoise: Allow multiple instances of the same tracer
In reply to Daniel Bristot de OliveiraAllow more than one instance of the same tracer. The workload will start when the first trace_array (instance) is registered and will stop when the last instance is unregistered.
Osnoise and timerlat are still mutually exclusive because of the different behavior of the osnoise: tracepoints.
--- kernel/trace/trace_osnoise.c | 106 ++++++++++++++++++++++++++--------- 1 file changed, 80 insertions(+), 26 deletions(-)
kernel/trace/trace_osnoise.c +80 -26
@@ -64,6 +64,24 @@ static bool osnoise_has_registered_instances(void) list); } +/* +* osnoise_instance_registered - check if a tr is already registered +*/ +static int osnoise_instance_registered (struct trace_array *tr) +{ +struct osnoise_instance *inst; +int found =0 ; + +rcu_read_lock (); +list_for_each_entry_rcu (inst, &osnoise_instances, list) { +if (inst->tr == tr) + found =1 ; + } +rcu_read_unlock (); + +return found; +} +/* * osnoise_register_instance - register a new trace instance *
@@ -106,10 +124,8 @@ static void osnoise_unregister_instance(struct trace_array *tr) }rcu_read_unlock (); -if (!found) { -WARN ("osnoise unregister did not find tr %s\n" , tr->name); +if (!found)return ; - }synchronize_rcu ();kfree (inst);
@@ -1190,6 +1206,7 @@ static __always_inline void osnoise_stop_tracing(void) "stop tracing hit on cpu %d\n", smp_processor_id());tracer_tracing_off (tr); + }rcu_read_unlock (); }
@@ -2041,6 +2058,16 @@ static int osnoise_workload_start(void) {int retval; +/* +* Instances need to be registered after calling workload +* start. Hence, if there is already an instance, the +* workload was already registered. Otherwise, this +* code is on the way to register the first instance, +* and the workload will start. +*/ +if (osnoise_has_registered_instances ()) +return 0 ; +osn_var_reset_all (); retval =osnoise_hook_events ();
@@ -2066,6 +2093,13 @@ static int osnoise_workload_start(void)*/ static void osnoise_workload_stop (void ) { +/* +* Instances need to be unregistered before calling +* stop. Hence, if there is a registered instance, more +* than one instance is running, and the workload will not +* yet stop. Otherwise, this code is on the way to disable +* the last instance, and the workload can stop. +*/ if (osnoise_has_registered_instances ())return ;
@@ -2083,7 +2117,11 @@ static void osnoise_tracer_start(struct trace_array *tr) {int retval; -if (osnoise_has_registered_instances ()) +/* +* If the instance is already registered, there is no need to +* register it again. +*/ +if (osnoise_instance_registered (tr))return ; retval =osnoise_workload_start ();
@@ -2095,18 +2133,17 @@ static void osnoise_tracer_start(struct trace_array *tr)static void osnoise_tracer_stop (struct trace_array *tr) { -if (!osnoise_has_registered_instances ()) -return ; -osnoise_unregister_instance (tr);osnoise_workload_stop (); }static int osnoise_tracer_init (struct trace_array *tr) { - -/* Only allow one instance to enable this */ -if (osnoise_has_registered_instances ()) +/* +* Only allow osnoise tracer if timerlat tracer is not running +* already. +*/ +if (osnoise_data.timerlat_tracer)return -EBUSY ; tr->max_latency =0 ;
@@ -2135,45 +2172,55 @@ static void timerlat_tracer_start(struct trace_array *tr) {int retval; -if (osnoise_has_registered_instances ()) +/* +* If the instance is already registered, there is no need to +* register it again. +*/ +if (osnoise_instance_registered (tr))return ; - osnoise_data.timerlat_tracer =1 ; - retval =osnoise_workload_start ();if (retval) - goto out_err; +pr_err (BANNER "Error starting timerlat tracer\n" );osnoise_register_instance (tr);return ; -out_err: -pr_err (BANNER "Error starting timerlat tracer\n" ); }static void timerlat_tracer_stop (struct trace_array *tr) {int cpu; -if (!osnoise_has_registered_instances ()) -return ; - -for_each_online_cpu (cpu) -per_cpu (per_cpu_osnoise_var, cpu).sampling =0 ; +osnoise_unregister_instance (tr); -osnoise_tracer_stop (tr); +/* +* Instruct the threads to stop only if this is the last instance. +*/ +if (!osnoise_has_registered_instances ()) { +for_each_online_cpu (cpu) +per_cpu (per_cpu_osnoise_var, cpu).sampling =0 ; + } - osnoise_data.timerlat_tracer =0 ; +osnoise_workload_stop (); }static int timerlat_tracer_init (struct trace_array *tr) { -/* Only allow one instance to enable this */ -if (osnoise_has_registered_instances ()) +/* +* Only allow timerlat tracer if osnoise tracer is not running already. +*/ +if (osnoise_has_registered_instances () && !osnoise_data.timerlat_tracer)return -EBUSY ; - tr->max_latency =0 ; +/* +* If this is the first instance, set timerlat_tracer to block +* osnoise tracer start. +*/ +if (!osnoise_has_registered_instances ()) + osnoise_data.timerlat_tracer =1 ; + tr->max_latency =0 ;timerlat_tracer_start (tr);return 0 ;
@@ -2182,6 +2229,13 @@ static int timerlat_tracer_init(struct trace_array *tr)static void timerlat_tracer_reset (struct trace_array *tr) {timerlat_tracer_stop (tr); + +/* +* If this is the last instance, reset timerlat_tracer allowing +* osnoise to be started. +*/ +if (!osnoise_has_registered_instances ()) + osnoise_data.timerlat_tracer =0 ; }static struct tracer timerlat_tracer__read_mostly = {
Signature · 1 line
2.31.1
PATCH v3 6/19 rtla: Real-Time Linux Analysis tool
In reply to Daniel Bristot de OliveiraThe rtla is a meta-tool that includes a set of commands that aims to analyze the real-time properties of Linux. But instead of testing Linux as a black box, rtla leverages kernel tracing capabilities to provide precise information about the properties and root causes of unexpected results.
rtla --help works and provide information about the available options.
This is just the "main" and the Makefile, no function yet.
--- tools/tracing/rtla/Makefile | 59 ++++++++++++++++++++++++++++ tools/tracing/rtla/src/rtla.c | 72 +++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 tools/tracing/rtla/Makefile create mode 100644 tools/tracing/rtla/src/rtla.c
tools/tracing/rtla/Makefile new file +59 -0
@@ -0,0 +1,59 @@ +NAME := rtla +VERSION := 0.1 + +INSTALL = install +CC := gcc +FOPTS := -flto=auto -ffat-lto-objects -fexceptions -fstack-protector-strong \ + -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection +MOPTS := -m64 -mtune=generic +WOPTS := -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -Wno-maybe-uninitialized + +TRACEFS_HEADERS := $$(pkg-config --cflags libtracefs) + +CFLAGS := -O -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(MOPTS) $(WOPTS) $(TRACEFS_HEADERS) +LDFLAGS := -ggdb +LIBS := -ltracefs -ltraceevent -lpthread -lprocps + +SRC := $(wildcard src/*.c) +HDR := $(wildcard src/*.h) +OBJ := $(SRC:.c=.o) +DIRS := src +FILES := Makefile +CEXT := bz2 +TARBALL := $(NAME)-$(VERSION).tar.$(CEXT) +TAROPTS := -cvjf $(TARBALL) +BINDIR := /usr/bin +DATADIR := /usr/share +DOCDIR := $(DATADIR)/doc +MANDIR := $(DATADIR)/man +LICDIR := $(DATADIR)/licenses + +.PHONY: all tests + +all: rtla + +rtla: $(OBJ) + $(CC) -o rtla $(LDFLAGS) $(OBJ) $(LIBS) + +static: $(OBJ) + $(CC) -o rtla-static $(LDFLAGS) --static $(OBJ) $(LIBS) -lpthread -ldl + +.PHONY: install +install: + $(INSTALL) rtla -m 755 $(DESTDIR)$(BINDIR) + @test ! -f $(DESTDIR)$(BINDIR)/osnoise || rm $(DESTDIR)$(BINDIR)/osnoise + ln -s $(DESTDIR)$(BINDIR)/rtla $(DESTDIR)$(BINDIR)/osnoise + +.PHONY: clean tarball push +clean: + @test ! -f rtla || rm rtla + @test ! -f rtla-static || rm rtla-static + @test ! -f src/rtla.o || rm src/rtla.o + @test ! -f $(TARBALL) || rm -f $(TARBALL) + @rm -rf *~ $(OBJ) *.tar.$(CEXT) + +tarball: clean + rm -rf $(NAME)-$(VERSION) && mkdir $(NAME)-$(VERSION) + cp -r $(DIRS) $(FILES) $(NAME)-$(VERSION) + tar $(TAROPTS) --exclude='*~' $(NAME)-$(VERSION) + rm -rf $(NAME)-$(VERSION)
tools/tracing/rtla/src/rtla.c new file +72 -0
72 lines not on this page · raw message
Signature · 1 line
2.31.1
PATCH v3 7/19 rtla: Helper functions for rtla
In reply to Daniel Bristot de OliveiraThis is a set of utils and tracer helper functions. They are used by rtla mostly to parse config, display data and some trace operations that are not part of libtracefs (because they are only useful it for this case).
--- tools/tracing/rtla/src/trace.c | 219 +++++++++++++++++ tools/tracing/rtla/src/trace.h | 27 ++ tools/tracing/rtla/src/utils.c | 433 +++++++++++++++++++++++++++++++++ tools/tracing/rtla/src/utils.h | 56 +++++ 4 files changed, 735 insertions(+) create mode 100644 tools/tracing/rtla/src/trace.c create mode 100644 tools/tracing/rtla/src/trace.h create mode 100644 tools/tracing/rtla/src/utils.c create mode 100644 tools/tracing/rtla/src/utils.h
tools/tracing/rtla/src/trace.c new file +219 -0
@@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include <sys/sendfile.h> +#include <tracefs.h> +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> + +#include "trace.h" +#include "utils.h" + +/* +* enable_tracer_by_name - enable a tracer on the given instance +*/ +int enable_tracer_by_name (struct tracefs_instance *inst,const char *tracer) +{ +enum tracefs_tracers t; +int retval; + + t =TRACEFS_TRACER_CUSTOM ; + +debug_msg ("enabling %s tracer\n" , tracer); + + retval =tracefs_tracer_set (inst, t, tracer); +if (retval <0 ) { +if (errno ==ENODEV ) +err_msg ("tracer %s not found!\n" , tracer); + +err_msg ("failed to enable the tracer %s\n" , tracer); +return -1 ; + } + +return 0 ; +} + +/* +* disable_tracer - set nop tracer to the insta +*/ +void disable_tracer (struct tracefs_instance *inst) +{ +enum tracefs_tracers t =TRACEFS_TRACER_NOP ; +int retval; + + retval =tracefs_tracer_set (inst, t); +if (retval <0 ) +err_msg ("oops, error disabling tracer\n" ); +} + +/* +* create_instance - create a trace instance with *instance_name +*/ +struct tracefs_instance *create_instance (char *instance_name) +{ +return tracefs_instance_create (instance_name); +} + +/* +* destroy_instance - remove a trace instance and free the data +*/ +void destroy_instance (struct tracefs_instance *inst) +{ +tracefs_instance_destroy (inst); +tracefs_instance_free (inst); +} + +/* +* save_trace_to_file - save the trace output of the instance to the file +*/ +int save_trace_to_file (struct tracefs_instance *inst,const char *filename) +{ +const char *file ="trace" ; +mode_t mode =0644 ; +char *buffer[4096 ]; +int out_fd, in_fd; +int retval =-1 ; + + in_fd =tracefs_instance_file_open (inst, file,O_RDONLY ); +if (in_fd <0 ) { +err_msg ("Failed to open trace file\n" ); +return -1 ; + } + + out_fd =creat (filename, mode); +if (out_fd <0 ) { +err_msg ("Failed to create output file %s\n" , filename); + goto out_close; + } + +do { + retval =read (in_fd, buffer,sizeof (buffer)); +if (read <=0 ) + goto out_close; + + retval =write (out_fd, buffer, retval); +if (retval <0 ) + goto out_close; + }while (retval >0 ); + + retval =0 ; +close (out_fd); +out_close: +close (in_fd); +return retval; +} + +struct tracefs_instance *stop_inst; +static void stop_trace_pipe (int sig) +{ +tracefs_trace_pipe_stop (stop_inst); +} + +/* +* save_trace_pipe_to_file - save the trace output from a pipe to the file +* +* it works until receiving a signal to stop. +*/ +int save_trace_pipe_to_file (struct tracefs_instance *inst,const char *filename) +{ +mode_t mode =0644 ; +int retval; +int fd; + + fd =creat (filename, mode); + + stop_inst = inst; +signal (SIGINT , stop_trace_pipe); + retval =tracefs_trace_pipe_stream (fd, inst,SPLICE_F_NONBLOCK ); + stop_inst =NULL ; + +close (fd); +return retval; +} + +/* +* collect_registered_events - call the existing callback function for the event +* +* If an event has a registered callback function, call it. +* Otherwise, ignore the event. +*/ +int +collect_registered_events (struct tep_event *event,struct tep_record *record, +int cpu,void *context) +{ +struct trace_instance *trace = context; +struct trace_seq *s = trace->seq; + +if (!event->handler) +return 0 ; + + event->handler (s, record, event, context); + +return 0 ; +} + +/* +* trace_instance_destroy - destroy and free a rtla trace instance +*/ +void trace_instance_destroy (struct trace_instance *trace) +{ +if (trace->inst) { +disable_tracer (trace->inst); +destroy_instance (trace->inst); + } + +if (trace->seq) +free (trace->seq); + +if (trace->tep) +tep_free (trace->tep); +} + +/* +* trace_instance_init - create an rtla trace instance +* +* It is more than the tracefs instance, as it contains other +* things required for the tracing, such as the local events and +* a seq file. +* +* Note that the trace instance is returned disabled. This allows +* the tool to apply some other configs, like setting priority +* to the kernel threads, before starting generating trace entries. +*/ +int trace_instance_init (struct trace_instance *trace,char *tool_name) +{ + trace->seq =calloc (1 ,sizeof (*trace->seq)); +if (!trace->seq) + goto out_err; + +trace_seq_init (trace->seq); + + trace->inst =create_instance (tool_name); +if (!trace->inst) + goto out_err; + + trace->tep =tracefs_local_events (NULL ); +if (!trace->tep) + goto out_err; + +/* +* Let the main enable the record after setting some other +* things such as the priority of the tracer's threads. +*/ +tracefs_trace_off (trace->inst); + +return 0 ; + +out_err: +trace_instance_destroy (trace); +return 1 ; +} + +/* +* trace_instance_start - start tracing a given rtla instance +*/ +int trace_instance_start (struct trace_instance *trace) +{ +return tracefs_trace_on (trace->inst); +}
tools/tracing/rtla/src/trace.h new file +27 -0
@@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <tracefs.h> +#include <stddef.h> + +struct trace_instance { +struct tracefs_instance *inst; +struct tep_handle *tep; +struct trace_seq *seq; +}; + +int trace_instance_init (struct trace_instance *trace,char *tool_name); +int trace_instance_start (struct trace_instance *trace); +void trace_instance_destroy (struct trace_instance *trace); + +struct trace_seq *get_trace_seq (void ); +int enable_tracer_by_name (struct tracefs_instance *inst,const char *tracer); +void disable_tracer (struct tracefs_instance *inst); + +int enable_osnoise (struct trace_instance *trace); +int enable_timerlat (struct trace_instance *trace); + +struct tracefs_instance *create_instance (char *instance_name); +void destroy_instance (struct tracefs_instance *inst); + +int save_trace_to_file (struct tracefs_instance *inst,const char *filename); +int collect_registered_events (struct tep_event *tep,struct tep_record *record, +int cpu,void *context);
tools/tracing/rtla/src/utils.c new file +433 -0
433 lines not on this page · raw message
tools/tracing/rtla/src/utils.h new file +56 -0
56 lines not on this page · raw message
Signature · 1 line
2.31.1
PATCH v3 8/19 rtla: Add osnoise tool
In reply to Daniel Bristot de OliveiraThe osnoise tool is the interface for the osnoise tracer. The osnoise tool will have multiple "modes" with different outputs. At this point, no mode is included.
The osnoise.c includes the osnoise_context abstraction. It serves to read-save-change-restore the default values from tracing/osnoise/ directory. When the context is deleted, the default values are restored.
It also includes some other helper functions for managing osnoise tracer sessions.
With these bits and pieces in place, we can start adding some functionality to rtla.
--- tools/tracing/rtla/src/osnoise.c | 815 +++++++++++++++++++++++++++++++ tools/tracing/rtla/src/osnoise.h | 85 ++++ tools/tracing/rtla/src/rtla.c | 10 + 3 files changed, 910 insertions(+) create mode 100644 tools/tracing/rtla/src/osnoise.c create mode 100644 tools/tracing/rtla/src/osnoise.h
tools/tracing/rtla/src/osnoise.c new file +815 -0
@@ -0,0 +1,815 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <[email protected]> +*/ + +#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 "osnoise.h" +#include "utils.h" + +/* +* 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 *osnoise_cpus =tracefs_get_tracing_file ("osnoise/cpus" ); +char curr_cpus[1024 ]; +int retval; + + context->cpus_fd =open (osnoise_cpus,O_RDWR ); +if (!context->cpus_fd) + goto out_err; + + retval =read (context->cpus_fd, &curr_cpus,sizeof (curr_cpus)); +if (!retval) + goto out_close; + + context->orig_cpus =strdup (curr_cpus); +if (!context->orig_cpus) + goto out_err; + + retval =write (context->cpus_fd, cpus,strlen (cpus) +1 ); +if (!retval) + goto out_err; + +tracefs_put_tracing_file (osnoise_cpus); + +return 0 ; + +out_close: +close (context->cpus_fd); + context->cpus_fd =-1 ; +out_err: +tracefs_put_tracing_file (osnoise_cpus); +return 1 ; +} + +/* +* 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 ; + + retval =write (context->cpus_fd, context->orig_cpus,strlen (context->orig_cpus)); +if (!retval) +err_msg ("could not restore original osnoise cpus\n" ); + +free (context->orig_cpus); +} + +/* +* 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) +{ +char buffer[BUFF_U64_STR_SIZE ]; +char *runtime_path; +int retval; + +if (context->runtime_us) +return context->runtime_us; + + runtime_path =tracefs_get_tracing_file ("osnoise/runtime_us" ); + + context->runtime_fd =open (runtime_path,O_RDWR ); +if (!context->runtime_fd) + goto out_err; + + retval =read (context->runtime_fd, &buffer,sizeof (buffer)); +if (!retval) + goto out_close; + + context->runtime_us =get_long_from_str (buffer); +if (!context->runtime_us) + goto out_close; + + context->orig_runtime_us = context->runtime_us; + +tracefs_put_tracing_file (runtime_path); + +return context->runtime_us; + +out_close: +close (context->runtime_fd); + context->runtime_fd =-1 ; +out_err: +tracefs_put_tracing_file (runtime_path); +return 0 ; +} + +/* +* 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) +{ +char buffer[BUFF_U64_STR_SIZE ]; +char *period_path; +int retval; + +if (context->period_us) +return context->period_us; + + period_path =tracefs_get_tracing_file ("osnoise/period_us" ); + + context->period_fd =open (period_path,O_RDWR ); +if (!context->period_fd) + goto out_err; + + retval =read (context->period_fd, &buffer,sizeof (buffer)); +if (!retval) + goto out_close; + + context->period_us =get_long_from_str (buffer); +if (!context->period_us) + goto out_close; + + context->orig_period_us = context->period_us; + +tracefs_put_tracing_file (period_path); + +return context->period_us; + +out_close: +close (context->period_fd); + context->period_fd =-1 ; +out_err: +tracefs_put_tracing_file (period_path); +return 0 ; +} + +static int __osnoise_write_runtime (struct osnoise_context *context, +unsigned long long runtime) +{ +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (context->runtime_fd ==-1 ) { +err_msg ("tried to write osnoise runtime before getting it\n" ); +return 0 ; + } + +snprintf (buffer,sizeof (buffer),"%llu\n" , runtime); + + retval =write (context->runtime_fd, buffer,strlen (buffer) +1 ); +if (retval <0 ) +return -1 ; + + context->runtime_us = runtime; +return 0 ; +} + +static int __osnoise_write_period (struct osnoise_context *context, +unsigned long long period) +{ +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (context->period_fd ==-1 ) +return 0 ; + +snprintf (buffer,sizeof (buffer),"%llu\n" , period); + + retval =write (context->period_fd, buffer,strlen (buffer) +1 ); +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); + +if (!curr_period_us || !curr_runtime_us) +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 runtime = context->orig_runtime_us; +unsigned long long period = context->orig_period_us; +int retval; + +if (context->runtime_fd <0 && context->period_fd <0 ) +return ; + + retval =osnoise_set_runtime_period (context, runtime, period); +if (retval) +err_msg ("Could not restore original osnoise runtime/period\n" ); +} + +/* +* osnoise_get_stop_us - read and save the original "stop_tracing_us" +*/ +static long long +osnoise_get_stop_us (struct osnoise_context *context) +{ +char buffer[BUFF_U64_STR_SIZE ]; +char *stop_path; +int retval; + +if (context->stop_us_fd >0 ) +return context->stop_us; + + stop_path =tracefs_get_tracing_file ("osnoise/stop_tracing_us" ); + + context->stop_us_fd =open (stop_path,O_RDWR ); +if (!context->stop_us_fd) + goto out_err; + + retval =read (context->stop_us_fd, &buffer,sizeof (buffer)); +if (!retval) + goto out_close; + + context->stop_us =get_long_from_str (buffer); + context->orig_stop_us = context->stop_us; + +tracefs_put_tracing_file (stop_path); + +return context->stop_us; + +out_close: +close (context->stop_us_fd); + context->stop_us_fd =-1 ; +out_err: +tracefs_put_tracing_file (stop_path); +return -1 ; +} + +/* +* 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); +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (curr_stop_us <0 ) +return -1 ; + +snprintf (buffer,BUFF_U64_STR_SIZE ,"%lld\n" , stop_us); + + retval =write (context->stop_us_fd, buffer,strlen (buffer) +1 ); +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) +{ +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (context->stop_us_fd <0 ) +return ; + +if (context->orig_stop_us == context->stop_us) +return ; + +snprintf (buffer,BUFF_U64_STR_SIZE ,"%lld\n" , context->orig_stop_us); + + retval =write (context->stop_us_fd, buffer,strlen (buffer) +1 ); +if (retval <0 ) +err_msg ("Could not restore original osnoise stop_us\n" ); +} + +/* +* osnoise_get_stop_us - read and save the original "stop_tracing_total_us" +*/ +static long long +osnoise_get_stop_total_us (struct osnoise_context *context) +{ +char buffer[BUFF_U64_STR_SIZE ]; +char *stop_path; +int retval; + +if (context->stop_total_us_fd >0 ) +return context->stop_total_us; + + stop_path =tracefs_get_tracing_file ("osnoise/stop_tracing_total_us" ); + + context->stop_total_us_fd =open (stop_path,O_RDWR ); +if (!context->stop_total_us_fd) + goto out_err; + + retval =read (context->stop_total_us_fd, &buffer,sizeof (buffer)); +if (!retval) + goto out_close; + + context->stop_total_us =get_long_from_str (buffer); + context->orig_stop_total_us = context->stop_total_us; + +tracefs_put_tracing_file (stop_path); + +return context->stop_total_us; + +out_close: +close (context->stop_total_us_fd); + context->stop_total_us_fd =-1 ; +out_err: +tracefs_put_tracing_file (stop_path); +return -1 ; +} + +/* +* osnoise_set_stop_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); +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (curr_stop_total_us <0 ) +return -1 ; + +snprintf (buffer,BUFF_U64_STR_SIZE ,"%lld\n" , stop_total_us); + + retval =write (context->stop_total_us_fd, buffer,strlen (buffer) +1 ); +if (retval <0 ) +return -1 ; + + context->stop_total_us = stop_total_us; + +return 0 ; +} + +/* +* osnoise_restore_stop_us - restore the original stop_tracing_us +*/ +void osnoise_restore_stop_total_us (struct osnoise_context *context) +{ +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (context->stop_total_us_fd <0 ) +return ; + +if (context->orig_stop_total_us == context->stop_total_us) +return ; + +snprintf (buffer,BUFF_U64_STR_SIZE ,"%lld\n" , context->orig_stop_total_us); + + retval =write (context->stop_total_us_fd, buffer,strlen (buffer) +1 ); +if (retval <0 ) +err_msg ("Could not restore original osnoise stop_total_us\n" ); +} + +/* +* 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) +{ +char buffer[BUFF_U64_STR_SIZE ]; +char *stop_path; +int retval; + +if (context->timerlat_period_us_fd >0 ) +return context->timerlat_period_us; + + stop_path =tracefs_get_tracing_file ("osnoise/timerlat_period_us" ); + + context->timerlat_period_us_fd =open (stop_path,O_RDWR ); +if (!context->timerlat_period_us_fd) + goto out_err; + + retval =read (context->timerlat_period_us_fd, &buffer,sizeof (buffer)); +if (!retval) + goto out_close; + + context->timerlat_period_us =get_long_from_str (buffer); + context->orig_timerlat_period_us = context->timerlat_period_us; + +tracefs_put_tracing_file (stop_path); + +return context->timerlat_period_us; + +out_close: +close (context->timerlat_period_us_fd); + context->timerlat_period_us_fd =-1 ; +out_err: +tracefs_put_tracing_file (stop_path); +return -1 ; +} + +/* +* 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); +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (curr_timerlat_period_us <0 ) +return -1 ; + +snprintf (buffer,BUFF_U64_STR_SIZE ,"%lld\n" , timerlat_period_us); + + retval =write (context->timerlat_period_us_fd, buffer,strlen (buffer) +1 ); +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) +{ +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (context->timerlat_period_us_fd <0 ) +return ; + +if (context->orig_timerlat_period_us == context->timerlat_period_us) +return ; + +snprintf (buffer,BUFF_U64_STR_SIZE ,"%lld\n" , context->orig_timerlat_period_us); + + retval =write (context->timerlat_period_us_fd, buffer,strlen (buffer) +1 ); +if (retval <0 ) +err_msg ("Could not restore original osnoise timerlat_period_us\n" ); +} + +/* +* osnoise_get_print_stack - read and save the original "print_stack" +*/ +static long long +osnoise_get_print_stack (struct osnoise_context *context) +{ +char buffer[BUFF_U64_STR_SIZE ]; +char *stop_path; +int retval; + +if (context->print_stack_fd >0 ) +return context->print_stack; + + stop_path =tracefs_get_tracing_file ("osnoise/print_stack" ); + + context->print_stack_fd =open (stop_path,O_RDWR ); +if (!context->print_stack_fd) + goto out_err; + + retval =read (context->print_stack_fd, &buffer,sizeof (buffer)); +if (!retval) + goto out_close; + + context->print_stack =get_long_from_str (buffer); + context->orig_print_stack = context->print_stack; + +tracefs_put_tracing_file (stop_path); + +return context->print_stack; + +out_close: +close (context->print_stack_fd); + context->print_stack_fd =-1 ; +out_err: +tracefs_put_tracing_file (stop_path); +return -1 ; +} + +/* +* 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); +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (curr_print_stack <0 ) +return -1 ; + +snprintf (buffer,BUFF_U64_STR_SIZE ,"%lld\n" , print_stack); + + retval =write (context->print_stack_fd, buffer,strlen (buffer) +1 ); +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) +{ +char buffer[BUFF_U64_STR_SIZE ]; +int retval; + +if (context->print_stack_fd <0 ) +return ; + +if (context->orig_print_stack == context->print_stack) +return ; + +snprintf (buffer,BUFF_U64_STR_SIZE ,"%lld\n" , context->orig_print_stack); + + retval =write (context->print_stack_fd, buffer,strlen (buffer) +1 ); +if (retval <0 ) +err_msg ("Could not restore original osnoise print_stack\n" ); +} + +/* +* 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; + +pthread_mutex_lock (&context->lock); +if (context->flags &FLAG_CONTEXT_DELETED ) { + ret =-1 ; + }else { + context->ref++; + ret =0 ; + } +pthread_mutex_unlock (&context->lock); + +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) + goto out_err; + +if (pthread_mutex_init (&context->lock,NULL ) <0 ) + goto out_err; + + context->cpus_fd =-1 ; + context->runtime_fd =-1 ; + context->period_fd =-1 ; + context->stop_us_fd =-1 ; + context->stop_total_us_fd =-1 ; + +osnoise_get_context (context); + +return context; +out_err: +if (context) +free (context); +return NULL ; +} + +/* +* 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) +{ +pthread_mutex_lock (&context->lock); +if (--context->ref <1 ) + context->flags |=FLAG_CONTEXT_DELETED ; +pthread_mutex_unlock (&context->lock); + +if (!(context->flags &FLAG_CONTEXT_DELETED )) +return ; + +osnoise_restore_cpus (context); +if (context->cpus_fd >=0 ) +close (context->cpus_fd); + +osnoise_restore_runtime_period (context); +if (context->runtime_fd >=0 ) +close (context->runtime_fd); +if (context->period_fd >=0 ) +close (context->period_fd); + +osnoise_restore_stop_us (context); +osnoise_restore_stop_total_us (context); +osnoise_restore_print_stack (context); +osnoise_restore_timerlat_period_us (context); + +pthread_mutex_destroy (&context->lock); +free (context); +} + +/* +* osnoise_destroy_tool - disable trace, restore configs and free data +*/ +void osnoise_destroy_tool (struct osnoise_tool *top) +{ +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 osnoiser tracer for tracing\n" ); + goto out_err; + } + +return trace; +out_err: +osnoise_destroy_tool (trace); +return NULL ; +} + +static void osnoise_usage (void ) +{ +int i; + +static const char *const msg[] = { +"" , +"osnoise version " VERSION , +"" , +" usage: [rtla] osnoise [MODE] ..." , +"" , +" modes:" , +"" , +NULL , + }; + +for (i =0 ; msg[i]; i++) +fprintf (stderr,"%s\n" , msg[i]); +exit (1 ); +} + +int osnoise_main (int argc,char *argv[]) +{ +if (argc <=1 ) + goto usage; + +if ((strcmp (argv[1 ],"-h" ) ==0 ) || (strcmp (argv[1 ],"--help" ) ==0 )) { +osnoise_usage (); +exit (0 ); + } + +usage: +osnoise_usage (); +exit (1 ); +}
tools/tracing/rtla/src/osnoise.h new file +85 -0
85 lines not on this page · raw message
tools/tracing/rtla/src/rtla.c +10 -0
@@ -8,6 +8,8 @@#include <string.h> #include <stdio.h> +#include "osnoise.h" +/* * rtla_usage - print rtla usage */
@@ -22,6 +24,7 @@ static void rtla_usage(void)" usage: rtla COMMAND ..." ,"" ," commands:" , +" osnoise - gives information about the operating system noise (osnoise)" ,"" , NULL, };
@@ -39,7 +42,14 @@ static void rtla_usage(void)*/ int run_command (int argc,char **argv,int start_position) { +if (strcmp (argv[start_position],"osnoise" ) ==0 ) { +osnoise_main (argc-start_position, &argv[start_position]); + goto ran; + } +return 0 ; +ran: +return 1 ; }int main (int argc,char *argv[])
Signature · 1 line
2.31.1
PATCH v3 9/19 rtla/osnoise: Add osnoise top mode
In reply to Daniel Bristot de OliveiraThe rtla osnoise tool is an interface for the osnoise tracer. The osnoise tracer dispatches a kernel thread per-cpu. These threads read the time in a loop while with preemption, softirqs and IRQs enabled, thus allowing all the sources of osnoise during its execution. The osnoise threads take note of the entry and exit point of any source of interferences, increasing a per-cpu interference counter. The osnoise tracer also saves an interference counter for each source of interference.
The rtla osnoise top mode displays information about the periodic summary from the osnoise tracer.
One example of rtla osnoise top output is:
[root@alien ~]# rtla osnoise top -c 0-3 -d 1m -q -r 900000 -P F:1
Operating System Noise
duration: 0 00:01:00 | time is in us
CPU Period Runtime Noise % CPU Aval Max Noise Max Single HW NMI IRQ Softirq Thread
0 #58 52200000 1031 99.99802 91 60 0 0 52285 0 101 1 #59 53100000 5 99.99999 5 5 0 9 53122 0 18 2 #59 53100000 7 99.99998 7 7 0 8 53115 0 18 3 #59 53100000 8274 99.98441 277 23 0 9 53778 0 660
"rtla osnoise top --help" works and provide information about the available options.
--- tools/tracing/rtla/src/osnoise.c | 20 +- tools/tracing/rtla/src/osnoise.h | 1 + tools/tracing/rtla/src/osnoise_top.c | 567 +++++++++++++++++++++++++++ 3 files changed, 587 insertions(+), 1 deletion(-) create mode 100644 tools/tracing/rtla/src/osnoise_top.c
tools/tracing/rtla/src/osnoise.c +19 -1
@@ -790,7 +790,9 @@ static void osnoise_usage(void)" usage: [rtla] osnoise [MODE] ..." ,"" ," modes:" , +" top - prints the summary from osnoise tracer" ,"" , +"if no MODE is given, the top mode is called, passing the arguments" , NULL, };
@@ -801,12 +803,28 @@ static void osnoise_usage(void)int osnoise_main (int argc,char *argv[]) { -if (argc <=1 ) +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 ();exit (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 ); } usage:
tools/tracing/rtla/src/osnoise.h +1 -0
@@ -82,4 +82,5 @@ void osnoise_destroy_tool(struct osnoise_tool *top);struct osnoise_tool *osnoise_init_tool (char *tool_name);struct osnoise_tool *osnoise_init_trace_tool (char *tracer); +int osnoise_top_main (int argc,char **argv);int osnoise_main (int argc,char **argv);
tools/tracing/rtla/src/osnoise_top.c new file +567 -0
567 lines not on this page · raw message
Signature · 1 line
2.31.1
PATCH v3 10/19 rtla/osnoise: Add the hist mode
In reply to Daniel Bristot de OliveiraThe rtla osnoise hist tool collects all osnoise:sample_threshold occurrence in a histogram, displaying the results in a user-friendly way. The tool also allows many configurations of the osnoise tracer and the collection of the tracer output.
Here is one example of the rtla osnoise hist tool output:
---------- %< ----------
[root@f34 ~]# rtla osnoise hist --bucket-size 10 --entries 100 -c 0-8 -d 1M -r 9000 -P F:1 # RTLA osnoise histogram
# Time unit is microseconds (us)
# Duration: 0 00:01:00
Index CPU-000 CPU-001 CPU-002 CPU-003 CPU-004 CPU-005 CPU-006 CPU-007 CPU-008
0 430 434 352 455 440 463 467 436 484 10 88 88 92 141 120 100 126 166 100 20 19 7 12 22 8 8 13 13 16 30 6 0 2 0 1 2 2 1 0 50 0 0 0 0 0 0 1 0 0 over: 0 0 0 0 0 0 0 0 0 count: 543 529 458 618 569 573 609 616 600 min: 0 0 0 0 0 0 0 0 0 avg: 0 0 0 0 0 0 0 0 0
max: 30 20 30 20 30 30 50 30 20
---------- >% ----------
Running
- rtla osnoise hist --help
provides information about the available options.
--- tools/tracing/rtla/src/osnoise.c | 6 +- tools/tracing/rtla/src/osnoise.h | 1 + tools/tracing/rtla/src/osnoise_hist.c | 783 ++++++++++++++++++++++++++ 3 files changed, 789 insertions(+), 1 deletion(-) create mode 100644 tools/tracing/rtla/src/osnoise_hist.c
tools/tracing/rtla/src/osnoise.c +5 -1
@@ -790,7 +790,8 @@ static void osnoise_usage(void)" usage: [rtla] osnoise [MODE] ..." ,"" ," modes:" , -" top - prints the summary from osnoise tracer" , +" 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,
@@ -825,6 +826,9 @@ int osnoise_main(int argc, char *argv[]) }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:
tools/tracing/rtla/src/osnoise.h +1 -0
@@ -82,5 +82,6 @@ void osnoise_destroy_tool(struct osnoise_tool *top);struct osnoise_tool *osnoise_init_tool (char *tool_name);struct osnoise_tool *osnoise_init_trace_tool (char *tracer); +int osnoise_hist_main (int argc,char *argv[]);int osnoise_top_main (int argc,char **argv);int osnoise_main (int argc,char **argv);
tools/tracing/rtla/src/osnoise_hist.c new file +783 -0
783 lines not on this page · raw message
Signature · 1 line
2.31.1
PATCH v3 11/19 rtla: Add timerlat tool and timelart top mode
In reply to Daniel Bristot de OliveiraThe rtla timerlat tool is an interface for the timerlat tracer. The timerlat tracer dispatches a kernel thread per-cpu. These threads set a periodic timer to wake themselves up and go back to sleep. After the wakeup, they collect and generate useful information for the debugging of operating system timer latency.
The timerlat tracer outputs information in two ways. It periodically prints the timer latency at the timer IRQ handler and the Thread handler. It also provides information for each noise via the osnoise tracepoints.
The rtla timerlat top mode displays a summary of the periodic output from the timerlat tracer.
Here is one example of the rtla timerlat tool output:
---------- %< ----------
[root@alien ~]# rtla timerlat top -c 0-3 -d 1m
Timer Latency
0 00:01:00 | IRQ Timer Latency (us) | Thread Timer Latency (us) CPU COUNT | cur min avg max | cur min avg max 0 #60001 | 0 0 0 3 | 1 1 1 6 1 #60001 | 0 0 0 3 | 2 1 1 5 2 #60001 | 0 0 1 6 | 1 1 2 7 3 #60001 | 0 0 0 7 | 1 1 1 11
---------- >% ----------
Running:
# rtla timerlat --help # rtla timerlat top --help provides information about the available options.
--- tools/tracing/rtla/Makefile | 2 + tools/tracing/rtla/src/rtla.c | 5 + tools/tracing/rtla/src/timerlat.c | 68 +++ tools/tracing/rtla/src/timerlat.h | 4 + tools/tracing/rtla/src/timerlat_top.c | 581 ++++++++++++++++++++++++++ 5 files changed, 660 insertions(+) create mode 100644 tools/tracing/rtla/src/timerlat.c create mode 100644 tools/tracing/rtla/src/timerlat.h create mode 100644 tools/tracing/rtla/src/timerlat_top.c
tools/tracing/rtla/Makefile +2 -0
@@ -43,6 +43,8 @@ install: $(INSTALL) rtla -m 755 $(DESTDIR)$(BINDIR) @test ! -f $(DESTDIR)$(BINDIR)/osnoise || rm $(DESTDIR)$(BINDIR)/osnoise ln -s $(DESTDIR)$(BINDIR)/rtla $(DESTDIR)$(BINDIR)/osnoise + @test ! -f $(DESTDIR)$(BINDIR)/timerlat || rm $(DESTDIR)$(BINDIR)/timerlat + ln -s $(DESTDIR)$(BINDIR)/rtla $(DESTDIR)$(BINDIR)/timerlat .PHONY: clean tarball push clean:
tools/tracing/rtla/src/rtla.c +5 -0
@@ -9,6 +9,7 @@#include <stdio.h> #include "osnoise.h" +#include "timerlat.h" /* * rtla_usage - print rtla usage
@@ -25,6 +26,7 @@ static void rtla_usage(void)"" ," commands:" ," osnoise - gives information about the operating system noise (osnoise)" , +" timerlat - measures the timer irq and thread latency" ,"" , NULL, };
@@ -45,6 +47,9 @@ int run_command(int argc, char **argv, int start_position)if (strcmp (argv[start_position],"osnoise" ) ==0 ) {osnoise_main (argc-start_position, &argv[start_position]); goto ran; + }else if (strcmp (argv[start_position],"timerlat" ) ==0 ) { +timerlat_main (argc-start_position, &argv[start_position]); + goto ran; }return 0 ;
tools/tracing/rtla/src/timerlat.c new file +68 -0
68 lines not on this page · raw message
tools/tracing/rtla/src/timerlat.h new file +4 -0
@@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 + +int timerlat_top_main (int argc,char *argv[]); +int timerlat_main (int argc,char *argv[]);
tools/tracing/rtla/src/timerlat_top.c new file +581 -0
581 lines not on this page · raw message
Signature · 1 line
2.31.1
PATCH v3 12/19 rtla/timerlat: Add timerlat hist mode
In reply to Daniel Bristot de OliveiraThe rtla hist hist mode displays a histogram of each tracer event occurrence, both for IRQ and timer latencies. The tool also allows many configurations of the timerlat tracer and the collection of the tracer output.
Here is one example of the rtla timerlat hist mode output:
---------- %< ----------
[root@alien ~]# rtla timerlat hist -c 0-3 -d 1M # RTLA timerlat histogram
# Time unit is microseconds (us)
# Duration: 0 00:01:00
Index IRQ-000 Thr-000 IRQ-001 Thr-001 IRQ-002 Thr-002 IRQ-003 Thr-003
0 58572 0 59373 0 58691 0 58895 0
1 1422 57021 628 57241 1310 56160 1102 56805
2 6 2931 0 2695 0 3567 4 3031 3 1 40 0 53 0 260 0 142 4 0 7 0 5 0 6 0 17 5 0 2 0 5 0 7 0 4 6 0 0 0 2 0 1 0 1 8 0 0 0 0 0 0 0 1 over: 0 0 0 0 0 0 0 0 count: 60001 60001 60001 60001 60001 60001 60001 60001 min: 0 1 0 1 0 1 0 1 avg: 0 1 0 1 0 1 0 1 max: 3 5 1 6 1 6 2 8
---------- >% ----------
Running
- rtla timerlat hist --help
provides information about the available options.
--- tools/tracing/rtla/src/timerlat.c | 6 +- tools/tracing/rtla/src/timerlat.h | 2 +- tools/tracing/rtla/src/timerlat_hist.c | 780 +++++++++++++++++++++++++ 3 files changed, 786 insertions(+), 2 deletions(-) create mode 100644 tools/tracing/rtla/src/timerlat_hist.c
tools/tracing/rtla/src/timerlat.c +5 -1
@@ -25,7 +25,8 @@ static void timerlat_usage(void)" usage: [rtla] timerlat [MODE] ..." ,"" ," modes:" , -" top - prints the summary from timerlat tracer" , +" top - prints the summary from timerlat tracer" , +" hist - prints a histogram of timer latencies" ,"" ,"if no MODE is given, the top mode is called, passing the arguments" , NULL,
@@ -60,6 +61,9 @@ int timerlat_main(int argc, char *argv[]) }else if (strcmp (argv[1 ],"top" ) ==0 ) {timerlat_top_main (argc-1 , &argv[1 ]);exit (0 ); + }else if (strcmp (argv[1 ],"hist" ) ==0 ) { +timerlat_hist_main (argc-1 , &argv[1 ]); +exit (0 ); } usage:
tools/tracing/rtla/src/timerlat.h +1 -1
@@ -1,4 +1,4 @@// SPDX-License-Identifier: GPL-2.0 - +int timerlat_hist_main (int argc,char *argv[]);int timerlat_top_main (int argc,char *argv[]);int timerlat_main (int argc,char *argv[]);
tools/tracing/rtla/src/timerlat_hist.c new file +780 -0
780 lines not on this page · raw message
Signature · 1 line
2.31.1
PATCH v3 13/19 rtla: Add Documentation
In reply to Daniel Bristot de OliveiraAdds the basis for rtla documentation. It is based on libtracefs Documentation as suggested by Steven Rostedt. This patch also includes the rtla(1) man page.
--- tools/tracing/rtla/Documentation/Makefile | 223 ++++++++++++++++++ .../tracing/rtla/Documentation/asciidoc.conf | 118 +++++++++ .../rtla/Documentation/manpage-base.xsl | 35 +++ .../rtla/Documentation/manpage-normal.xsl | 13 + tools/tracing/rtla/Documentation/rtla.txt | 56 +++++ tools/tracing/rtla/Documentation/utils.mk | 144 +++++++++++ tools/tracing/rtla/Makefile | 20 +- 7 files changed, 604 insertions(+), 5 deletions(-) create mode 100644 tools/tracing/rtla/Documentation/Makefile create mode 100644 tools/tracing/rtla/Documentation/asciidoc.conf create mode 100644 tools/tracing/rtla/Documentation/manpage-base.xsl create mode 100644 tools/tracing/rtla/Documentation/manpage-normal.xsl create mode 100644 tools/tracing/rtla/Documentation/rtla.txt create mode 100644 tools/tracing/rtla/Documentation/utils.mk
tools/tracing/rtla/Documentation/Makefile new file +223 -0
@@ -0,0 +1,223 @@ +# SPDX-License-Identifier: LGPL-2.1 + +include utils.mk + +# This Makefile and manpage XSL files were taken from libtracefs +# and modified + + +MAN1_TXT= \ + $(wildcard rtla-*.txt) \ + rtla.txt + +MAN_TXT = $(MAN1_TXT) +_MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) +_MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT)) +_DOC_MAN1=$(patsubst %.txt,%.m,$(MAN1_TXT)) + +MAN_XML=$(addprefix $(OUTPUT),$(_MAN_XML)) +MAN_HTML=$(addprefix $(OUTPUT),$(_MAN_HTML)) +DOC_MAN1=$(addprefix $(OUTPUT),$(_DOC_MAN1)) + +# Make the path relative to DESTDIR, not prefix +ifndef DESTDIR +prefix?=$(HOME) +endif +bindir?=$(prefix)/bin +htmldir?=$(prefix)/share/doc/rtla-doc +pdfdir?=$(prefix)/share/doc/rtla-doc +mandir?=$(prefix)/share/man +man1dir=$(mandir)/man1 + +ASCIIDOC=asciidoc +ASCIIDOC_EXTRA = --unsafe -f asciidoc.conf +ASCIIDOC_HTML = xhtml11 +MANPAGE_XSL = manpage-normal.xsl +XMLTO_EXTRA = --skip-validation +INSTALL?=install +RM ?= rm -f + +ifdef USE_ASCIIDOCTOR +ASCIIDOC = asciidoctor +ASCIIDOC_EXTRA = -a compat-mode +ASCIIDOC_EXTRA += -I. -rasciidoctor-extensions +ASCIIDOC_EXTRA += -a mansource="rtla" -a manmanual="rtla Manual" +ASCIIDOC_HTML = xhtml5 +endif + +ASCIIDOC_INSTALLED := $(shell command -v $(ASCIIDOC) 2> /dev/null) +ifndef ASCIIDOC_INSTALLED + missing_tools += $(ASCIIDOC) +endif + +XMLTO=xmlto +XMLTO_INSTALLED := $(shell command -v $(XMLTO) 2> /dev/null) +ifndef XMLTO_INSTALLED + missing_tools += $(XMLTO) +endif + +# +# For asciidoc ... +# -7.1.2, no extra settings are needed. +# 8.0-, set ASCIIDOC8. +# + +# +# For docbook-xsl ... +# -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0) +# 1.69.0, no extra settings are needed? +# 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP? +# 1.71.1, no extra settings are needed? +# 1.72.0, set DOCBOOK_XSL_172. +# 1.73.0-, set ASCIIDOC_NO_ROFF +# + +# +# If you had been using DOCBOOK_XSL_172 in an attempt to get rid +# of 'the ".ft C" problem' in your generated manpages, and you +# instead ended up with weird characters around callouts, try +# using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8). +# + +ifdef ASCIIDOC8 +ASCIIDOC_EXTRA += -a asciidoc7compatible +endif +ifdef DOCBOOK_XSL_172 +ASCIIDOC_EXTRA += -a rtla-asciidoc-no-roff +MANPAGE_XSL = manpage-1.72.xsl +else + ifdef ASCIIDOC_NO_ROFF + # docbook-xsl after 1.72 needs the regular XSL, but will not + # pass-thru raw roff codes from asciidoc.conf, so turn them off. + ASCIIDOC_EXTRA += -a rtla-asciidoc-no-roff + endif +endif +ifdef MAN_BOLD_LITERAL +XMLTO_EXTRA += -m manpage-bold-literal.xsl +endif +ifdef DOCBOOK_SUPPRESS_SP +XMLTO_EXTRA += -m manpage-suppress-sp.xsl +endif + +SHELL_PATH ?= $(SHELL) +# Shell quote; +SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) + +DESTDIR ?= +DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' + +export DESTDIR DESTDIR_SQ + +QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir +QUIET_SUBDIR1 = + +ifneq ($(findstring $(MAKEFLAGS),w),w) +PRINT_DIR = --no-print-directory +else # "make -w" +NO_SUBDIR = : +endif + +ifneq ($(findstring $(MAKEFLAGS),s),s) +ifneq ($(V),1) + QUIET_ASCIIDOC = @echo ' ASCIIDOC '$@; + QUIET_XMLTO = @echo ' XMLTO '$@; + QUIET_SUBDIR0 = +@subdir= + QUIET_SUBDIR1 = ;$(NO_SUBDIR) \ + echo ' SUBDIR ' $$subdir; \ + $(MAKE) $(PRINT_DIR) -C $$subdir + export V +endif +endif + +all: check-man-tools html man1 + +man: man1 +man1: $(DOC_MAN1) + +html: $(MAN_HTML) $(MAN1_HTML) + +$(MAN_HTML) $(MAN1_HTML) $(DOC_MAN1): asciidoc.conf + +install: check-man-tools install-man install-html + +check-man-tools: +ifdef missing_tools + $(error "You need to install $(missing_tools) for man pages") +endif + +install-%.1: $(OUTPUT)%.1 + $(Q)$(call do_install,$<,$(man1dir),644); + +do-install-man: man $(addprefix install-,$(wildcard $(OUTPUT)*.1)) + +install-man: man + $(Q)$(MAKE) -C . do-install-man + +install-%.txt: $(OUTPUT)%.html + $(Q)$(call do_install,$<,$(htmldir),644); + +install-%.txt.1: $(OUTPUT)%.html + $(Q)$(call do_install,$<,$(htmldir),644); + +do-install-html: html $(addprefix install-,$(wildcard *.txt)) $(addprefix install-,$(wildcard *.txt.1)) + +install-html: html do-install-html + +uninstall: uninstall-man uninstall-html + +uninstall-man: + $(Q)$(RM) $(addprefix $(DESTDIR)$(man1dir)/,$(DOC_MAN1)) + +uninstall-html: + $(Q)$(RM) $(addprefix $(DESTDIR)$(htmldir)/,$(MAN_HTML)) $(addprefix $(DESTDIR)$(htmldir)/,$(MAN1_HTML)) + +ifdef missing_tools + DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed) +else + DO_INSTALL_MAN = do-install-man +endif + +CLEAN_FILES = \ + $(MAN_XML) $(addsuffix +,$(MAN_XML)) \ + $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \ + $(DOC_MAN1) *.1 *.m + +clean: + $(Q) $(RM) $(CLEAN_FILES) + +ifdef USE_ASCIIDOCTOR +$(OUTPUT)%.1 : $(OUTPUT)%.txt.1 + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ + $(ASCIIDOC) -b manpage -d manpage \ + $(ASCIIDOC_EXTRA) -artla_version=$(TRACEFS_VERSION) -o $@+ $< && \ + mv $@+ $@ +endif + +$(OUTPUT)%.m : $(OUTPUT)%.xml + $(QUIET_XMLTO)$(RM) $@ && \ + $(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<; \ + touch $@ + +$(OUTPUT)%.xml : %.txt + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ + $(ASCIIDOC) -b docbook -d manpage \ + $(ASCIIDOC_EXTRA) -artla_version=$(TRACEFS_VERSION) -o $@+ $< && \ + mv $@+ $@ + +$(OUTPUT)%.xml : %.txt.1 + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ + $(ASCIIDOC) -b docbook -d manpage \ + $(ASCIIDOC_EXTRA) -artla_version=$(TRACEFS_VERSION) -o $@+ $< && \ + mv $@+ $@ + +$(MAN_HTML): $(OUTPUT)%.html : %.txt + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ + $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage \ + $(ASCIIDOC_EXTRA) -artla_version=$(TRACEFS_VERSION) -o $@+ $< && \ + mv $@+ $@ + +$(MAN1_HTML): $(OUTPUT)%.html : %.txt.1 + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ + $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage \ + $(ASCIIDOC_EXTRA) -artla_version=$(TRACEFS_VERSION) -o $@+ $< && \ + mv $@+ $@
tools/tracing/rtla/Documentation/asciidoc.conf new file +118 -0
118 lines not on this page · raw message
tools/tracing/rtla/Documentation/manpage-base.xsl new file +35 -0
@@ -0,0 +1,35 @@ +<!-- manpage-base.xsl: + special formatting for manpages rendered from asciidoc+docbook --> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + version="1.0"> + +<!-- these params silence some output from xmlto --> +<xsl:param name="man.output.quietly" select="1"/> +<xsl:param name="refentry.meta.get.quietly" select="1"/> + +<!-- convert asciidoc callouts to man page format; + git.docbook.backslash and git.docbook.dot params + must be supplied by another XSL file or other means --> +<xsl:template match="co"> + <xsl:value-of select="concat( + $git.docbook.backslash,'fB(', + substring-after(@id,'-'),')', + $git.docbook.backslash,'fR')"/> +</xsl:template> +<xsl:template match="calloutlist"> + <xsl:value-of select="$git.docbook.dot"/> + <xsl:text>sp </xsl:text> + <xsl:apply-templates/> + <xsl:text> </xsl:text> +</xsl:template> +<xsl:template match="callout"> + <xsl:value-of select="concat( + $git.docbook.backslash,'fB', + substring-after(@arearefs,'-'), + '. ',$git.docbook.backslash,'fR')"/> + <xsl:apply-templates/> + <xsl:value-of select="$git.docbook.dot"/> + <xsl:text>br </xsl:text> +</xsl:template> + +</xsl:stylesheet>
tools/tracing/rtla/Documentation/manpage-normal.xsl new file +13 -0
@@ -0,0 +1,13 @@ +<!-- manpage-normal.xsl: + special settings for manpages rendered from asciidoc+docbook + handles anything we want to keep away from docbook-xsl 1.72.0 --> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + version="1.0"> + +<xsl:import href="manpage-base.xsl"/> + +<!-- these are the normal values for the roff control characters --> +<xsl:param name="git.docbook.backslash">\</xsl:param> +<xsl:param name="git.docbook.dot" >.</xsl:param> + +</xsl:stylesheet>
tools/tracing/rtla/Documentation/rtla.txt new file +56 -0
56 lines not on this page · raw message
tools/tracing/rtla/Documentation/utils.mk new file +144 -0
144 lines not on this page · raw message
tools/tracing/rtla/Makefile +15 -5
@@ -17,7 +17,7 @@ LIBS := -ltracefs -ltraceevent -lpthread -lprocps SRC := $(wildcard src/*.c) HDR := $(wildcard src/*.h) OBJ := $(SRC:.c=.o) -DIRS := src +DIRS := src Documentation FILES := Makefile CEXT := bz2 TARBALL := $(NAME)-$(VERSION).tar.$(CEXT)
@@ -27,19 +27,20 @@ DATADIR := /usr/share DOCDIR := $(DATADIR)/doc MANDIR := $(DATADIR)/man LICDIR := $(DATADIR)/licenses +SRCTREE := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)) .PHONY: all tests all: rtla -rtla: $(OBJ) +rtla: $(OBJ) doc $(CC) -o rtla $(LDFLAGS) $(OBJ) $(LIBS) static: $(OBJ) $(CC) -o rtla-static $(LDFLAGS) --static $(OBJ) $(LIBS) -lpthread -ldl .PHONY: install -install: +install: doc_install $(INSTALL) rtla -m 755 $(DESTDIR)$(BINDIR) @test ! -f $(DESTDIR)$(BINDIR)/osnoise || rm $(DESTDIR)$(BINDIR)/osnoise ln -s $(DESTDIR)$(BINDIR)/rtla $(DESTDIR)$(BINDIR)/osnoise
@@ -47,15 +48,24 @@ install: ln -s $(DESTDIR)$(BINDIR)/rtla $(DESTDIR)$(BINDIR)/timerlat .PHONY: clean tarball push -clean: +clean: doc_clean @test ! -f rtla || rm rtla @test ! -f rtla-static || rm rtla-static @test ! -f src/rtla.o || rm src/rtla.o @test ! -f $(TARBALL) || rm -f $(TARBALL) @rm -rf *~ $(OBJ) *.tar.$(CEXT) -tarball: clean +tarball: clean rm -rf $(NAME)-$(VERSION) && mkdir $(NAME)-$(VERSION) cp -r $(DIRS) $(FILES) $(NAME)-$(VERSION) tar $(TAROPTS) --exclude='*~' $(NAME)-$(VERSION) rm -rf $(NAME)-$(VERSION) + +doc: + $(MAKE) -C $(SRCTREE)/Documentation all + +doc_clean: + $(MAKE) -C $(SRCTREE)/Documentation clean + +doc_install: + $(MAKE) -C $(SRCTREE)/Documentation install
Signature · 1 line
2.31.1
PATCH v3 14/19 rtla: Add rtla osnoise man page
In reply to Daniel Bristot de OliveiraMan page for rtla osnoise command.
--- .../rtla/Documentation/rtla-osnoise.txt | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tools/tracing/rtla/Documentation/rtla-osnoise.txt
tools/tracing/rtla/Documentation/rtla-osnoise.txt new file +68 -0
@@ -0,0 +1,68 @@ +rtla-osnoise(1) +=============== + +NAME +---- +rtla-osnoise - Measure the operating system noise + +SYNOPSIS +-------- +*rtla osnoise* [MODE] ... + +DESCRIPTION +----------- +The rtla-osnoise(1) tool is an interface for the osnoise tracer. The osnoise +tracer dispatches a kernel thread per-cpu. These threads read the time in +a loop while with preemption, softirqs and IRQs enabled, thus allowing all +the sources of osnoise during its execution. The osnoise threads take note +of the entry and exit point of any source of interferences, increasing a +per-cpu interference counter. The osnoise tracer also saves an interference +counter for each source of interference. + +The osnoise tracer outputs information in two ways. It periodically prints +a summary of the noise of the operating system, including the counters of +the occurrence of the source of interference. It also provides information +for each noise via the osnoise tracepoints. The rtla-osnoise-top(1) mode +display information about the periodic summary from the osnoise tracer. +The rtla-osnoise-hist(1) mode display information about the noise using +the *osnoise:* tracepoints. For further details, please refer to the +respective man page. + +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. + +OPTIONS +------- +*-h*, *--help*:: +Display the help text. + +For other options, see the man page for the corresponding mode. + +SEE ALSO +-------- +_rtla-osnoise-top(1)_, _rtla-osnoise-hist(1)_ + +Osnoise tracer documentation: <https://www.kernel.org/doc/html/latest/trace/osnoise-tracer.html> + +AUTHOR +------ +Written by Daniel Bristot de Oliveira <[email protected]> + +REPORTING BUGS +-------------- +Report bugs to <[email protected]> + +LICENSE +------- +rtla is Free Software licensed under the GNU GPLv2 + +COPYING +------- +Copyright \(C) 2021 Red Hat, Inc. Free use of this software is granted under +the terms of the GNU Public License (GPL).
Signature · 1 line
2.31.1
PATCH v3 15/19 rtla: Add rtla osnoise top documentation
In reply to Daniel Bristot de OliveiraMan page for rtla osnoise top mode.
--- .../rtla/Documentation/rtla-osnoise-top.txt | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tools/tracing/rtla/Documentation/rtla-osnoise-top.txt
tools/tracing/rtla/Documentation/rtla-osnoise-top.txt new file +98 -0
@@ -0,0 +1,98 @@ +rtla-osnoise-top(1) +=================== + +NAME +---- +rtla-osnoise-top - Display a summary of the operating system noise + +SYNOPSIS +-------- +*rtla osnoise top* ['OPTIONS'] + +DESCRIPTION +----------- +The rtla-osnoise-top(1) tool is an interface for the osnoise tracer. The +osnoise tracer dispatches a kernel thread per-cpu. These threads read the +time in a loop while with preemption, softirq and IRQs enabled, thus +allowing all the sources of osnoise during its execution. The osnoise's +tracer threads take note of the delta between each time read, along with +an interference counter for each source of interference. At the end of +each period, the osnoise tracer displays a summary of the results. + +*rtla osnoise top* collects the periodic summary from the osnoise tracer, +including the counters of the occurrence of the interference source, +displaying the results in a user-friendly format. + +The tool also allows many configurations of the osnoise tracer and the +collection of the tracer output. + +OPTIONS +------- +*-h*, *--help*:: +Print help menu. +*-p*, *--period* 'us':: +Set the osnoise tracer period in microseconds. +*-r*, *--runtime* 'us':: +Set the osnoise tracer runtime in microseconds. +*-s*, *--stop* 'us':: +Stop the trace if a single sample is higher than the argument in microseconds. +If -T is set, it will also save the trace to the output. +*-S*, *--stop-total* 'us':: +Stop the trace if the total sample is higher than the argument in microseconds. +If -T is set, it will also save the trace to the output. +*-c*, *--cpus* 'cpu-list':: +Set the osnoise tracer to run the sample threads in the cpu-list. +*-d*, *--duration* 'time[s|m|h|d]':: +Set the duration of the session. +*-t*, *--trace*['=file']:: +Save the stopped trace to ['file|osnoise_trace.txt']. +*-q*, *--quiet*:: +Print only a summary at the end of the session. +*-P*, *--priority* 'o:prio|r:prio|f:prio|d:runtime:period':: +Set scheduling parameters to the osnoise tracer threads, the format to set the priority are: + - 'o:prio' - use SCHED_OTHER with 'prio'; + - 'r:prio' - use SCHED_RR with 'prio'; + - 'f:prio' - use SCHED_FIFO with 'prio'; + - 'd:runtime[us|ms|s]:period[us|ms|s]' - use SCHED_DEADLINE with 'runtime' and 'period' in nanoseconds. + +EXAMPLE +------- +In the example below, the rtla osnoise top tool is set to run with a +real-time priority 'FIFO:1', on CPUs '0-3', for '900ms' at each period +('1s' by default). The reason for reducing the runtime is to avoid starving +the rtla tool. The tool is also set to run for 'one minute' and to display +a summary of the report at the end of the session. + +------------------------------------------------------- +[root@f34 ~]# rtla osnoise top -P F:1 -c 0-3 -r 900000 -d 1M -q + Operating System Noise +duration: 0 00:01:00 | time is in us +CPU Period Runtime Noise % CPU Aval Max Noise Max Single HW NMI IRQ Softirq Thread + 0 #59 53100000 304896 99.42580 6978 56 549 0 53111 1590 13 + 1 #59 53100000 338339 99.36282 8092 24 399 0 53130 1448 31 + 2 #59 53100000 290842 99.45227 6582 39 855 0 53110 1406 12 + 3 #59 53100000 204935 99.61405 6251 33 290 0 53156 1460 12 +------------------------------------------------------- + +SEE ALSO +-------- +_rtla-osnoise(1)_, _rtla-osnoise-hist_(1) + +Osnoise tracer documentation: <https://www.kernel.org/doc/html/latest/trace/osnoise-tracer.html> + +AUTHOR +------ +Written by Daniel Bristot de Oliveira <[email protected]> + +REPORTING BUGS +-------------- +Report bugs to <[email protected]> + +LICENSE +------- +rtla is Free Software licensed under the GNU GPLv2 + +COPYING +------- +Copyright \(C) 2021 Red Hat, Inc. Free use of this software is granted under +the terms of the GNU Public License (GPL).
Signature · 1 line
2.31.1
PATCH v3 16/19 rtla: Add rtla osnoise hist documentation
In reply to Daniel Bristot de OliveiraMan page for rtla osnoise hist mode.
--- .../rtla/Documentation/rtla-osnoise-hist.txt | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tools/tracing/rtla/Documentation/rtla-osnoise-hist.txt
tools/tracing/rtla/Documentation/rtla-osnoise-hist.txt new file +117 -0
@@ -0,0 +1,117 @@ +rtla-osnoise-hist(1) +=================== + +NAME +---- +rtla-osnoise-hist - Display a histogram of the osnoise tracer samples + +SYNOPSIS +-------- +*rtla osnoise hist* ['OPTIONS'] + +DESCRIPTION +----------- +The *rtla-osnoise-hist(1)* tool is an interface for the osnoise tracer. The +osnoise tracer dispatches a kernel thread per-cpu. These threads read the +time in a loop while with preemption, SoftIRQs and IRQs enabled, thus +allowing all the sources of osnoise during its execution. The osnoise threads +take note of the delta between each time read. Anytime the delta between two +consecutive reads of the timer is higher than a 'threshold,' an +*osnoise:sample_threshold* event is generated reporting the detected noise. + +The *rtla-osnoise-hist(1)* tool collects all *osnoise:sample_threshold* +occurrence in a histogram, displaying the results in a user-friendly way. +The tool also allows many configurations of the osnoise tracer and the +collection of the tracer output. + +OPTIONS +------- +*-h*, *--help*:: +Print help menu. +*-p*, *--period* 'us':: +Set the osnoise tracer period in microseconds. +*-r*, *--runtime* 'us':: +Set the osnoise tracer runtime in microseconds. +*-s*, *--stop* 'us':: +Stop the trace if a single sample is higher than the argument in microseconds. +If -t is set, it will also save the trace to the output. +*-S*, *--stop-total* 'us':: +Stop the trace if the total sample is higher than the argument in microseconds. +If -t is set, it will also save the trace to the output. +*-c*, *--cpus* 'cpu-list':: +Set the osnoise tracer to run the sample threads in the cpu-list. +*-d*, *--duration* 'time[s|m|h|d]':: +Set the duration of the session. +*-t*, *--trace*['=file']:: +Save the stopped trace to ['file|osnoise_trace.txt']. +*-P*, *--priority* 'o:prio|r:prio|f:prio|d:runtime:period':: +Set scheduling parameters to the osnoise tracer threads, the format to +set the priority are: + - 'o:prio' - use SCHED_OTHER with 'prio'; + - 'r:prio' - use SCHED_RR with 'prio'; + - 'f:prio' - use SCHED_FIFO with 'prio'; + - 'd:runtime[us|ms|s]:period[us|ms|s]' - use SCHED_DEADLINE with +'runtime' and 'period' in nanoseconds. + +*-b*, --bucket-size 'N':: +Set the histogram bucket size (default 1). +*-e*, --entries 'N':: +Set the number of entries of the histogram (default 256). +*--no-header*:: +Do not print header. +*--no-summary*:: +Do not print summary. +*--no-index*:: +Do not print index. +*--with-zeros*:: +Print zero only entries. + +EXAMPLE +------- +In the example below, osnoise tracer threads are set to run with real-time +priority 'FIFO:1', on CPUs '0-11', for '900ms' at each period ('1s' by +default). The reason for reducing the runtime is to avoid starving the rtla +tool. The tool is also set to run for 'one minute.' The output histogram is +set to group outputs in buckets of '10 us' and '25' entries. + +------------------------------------------------------- +[root@f34 ~/]# rtla osnoise hist -P F:1 -c 0-11 -r 900000 -d 1M -b 10 -e 25 +# RTLA osnoise histogram +# Time unit is microseconds (us) +# Duration: 0 00:01:00 +Index CPU-000 CPU-001 CPU-002 CPU-003 CPU-004 CPU-005 CPU-006 CPU-007 CPU-008 CPU-009 CPU-010 CPU-011 +0 42982 46287 51779 53740 52024 44817 49898 36500 50408 50128 49523 52377 +10 12224 8356 2912 878 2667 10155 4573 18894 4214 4836 5708 2413 +20 8 5 12 2 13 24 20 41 29 53 39 39 +30 1 1 0 0 10 3 6 19 15 31 30 38 +40 0 0 0 0 0 4 2 7 2 3 8 11 +50 0 0 0 0 0 0 0 0 0 1 1 2 +over: 0 0 0 0 0 0 0 0 0 0 0 0 +count: 55215 54649 54703 54620 54714 55003 54499 55461 54668 55052 55309 54880 +min: 0 0 0 0 0 0 0 0 0 0 0 0 +avg: 0 0 0 0 0 0 0 0 0 0 0 0 +max: 30 30 20 20 30 40 40 40 40 50 50 50 +------------------------------------------------------- + +SEE ALSO +-------- +_rtla-osnoise(1)_, _rtla-osnoise-top_(1) + +Osnoise tracer documentation: <https://www.kernel.org/doc/html/latest/trace/osnoise-tracer.html> + +AUTHOR +------ +Written by Daniel Bristot de Oliveira <[email protected]> + +REPORTING BUGS +-------------- +Report bugs to <[email protected]> + +LICENSE +------- +rtla is Free Software licensed under the GNU GPLv2 + +COPYING +------- +Copyright \(C) 2021 Red Hat, Inc. Free use of this software is granted under +the terms of the GNU Public License (GPL).
Signature · 1 line
2.31.1
PATCH v3 17/19 rtla: Add rtla timerlat documentation
In reply to Daniel Bristot de OliveiraMan page for rtla timerlat tool.
--- .../rtla/Documentation/rtla-timerlat.txt | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tools/tracing/rtla/Documentation/rtla-timerlat.txt
tools/tracing/rtla/Documentation/rtla-timerlat.txt new file +65 -0
@@ -0,0 +1,65 @@ +rtla-timerlat(1) +================ + +NAME +---- +rtla-timerlat - Measures the operating system timer latency + +SYNOPSIS +-------- +*rtla timerlat* [MODE] ... + +DESCRIPTION +----------- +The rtla-timerlat(1) tool is an interface for the timerlat tracer. The +timerlat tracer dispatches a kernel thread per-cpu. These threads set +a periodic timer to wake themselves up and go back to sleep. After the +wakeup, they collect and generate useful information for the debugging +of operating system timer latency. + +The timerlat tracer outputs information in two ways. It periodically +prints the timer latency at the timer 'IRQ' handler and the 'Thread' handler. +It also provides information for each noise via the osnoise tracepoints. +The rtla-timerlat-top(1) mode displays a summary of the periodic output +from the timerlat tracer. The rtla-hist-hist(1) mode displays a histogram of +each tracer event occurrence. For further details, please refer to the +respective man page. + +MODES +----- +*top*:: + Prints the summary from timerlat tracer. +*hist*:: + Prints a histogram of timerlat samples. + +If no MODE is given, the top mode is called, passing the arguments. + +OPTIONS +------- +*-h*, *--help*:: + Display the help text. + +For other options, see the man page for the corresponding mode. + +SEE ALSO +-------- +_rtla-timerlat-top(1)_, _rtla-timerlat-hist(1)_ + +Timerlat tracer documentation: <https://www.kernel.org/doc/html/latest/trace/timerlat-tracer.html> + +AUTHOR +------ +Written by Daniel Bristot de Oliveira <[email protected]> + +REPORTING BUGS +-------------- +Report bugs to <[email protected]> + +LICENSE +------- +rtla is Free Software licensed under the GNU GPLv2 + +COPYING +------- +Copyright \(C) 2021 Red Hat, Inc. Free use of this software is granted under +the terms of the GNU Public License (GPL).
Signature · 1 line
2.31.1
PATCH v3 18/19 rtla: Add rtla timerlat top documentation
In reply to Daniel Bristot de OliveiraMan page for rtla timerlat top mode.
--- .../rtla/Documentation/rtla-timerlat-top.txt | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 tools/tracing/rtla/Documentation/rtla-timerlat-top.txt
tools/tracing/rtla/Documentation/rtla-timerlat-top.txt new file +181 -0
@@ -0,0 +1,181 @@ +rtla-timerlat-top(1) +==================== + +NAME +---- +rtla-timerlat-top - Measures the operating system timer latency + +SYNOPSIS +-------- +*rtla timerlat top* ['OPTIONS'] ... + +DESCRIPTION +The rtla-timerlat-top(1) mode displays a summary of the periodic output +from the timerlat tracer. + +The timerlat tracer dispatches a kernel thread per-cpu. These threads +set a periodic timer to wake themselves up and go back to sleep. After +the wakeup, they collect and generate useful information for the +debugging of operating system timer latency. + +The timerlat tracer outputs information in two ways. It periodically +prints the timer latency at the timer 'IRQ' handler and the 'Thread' handler. +It also provides information for each noise via the osnoise tracepoints +that can be seem with the option -T. + +OPTIONS +------- +*-h*, *--help*:: +Print help menu. +*-p*, *--period* 'us':: +Set the timerlat tracer period in microseconds. +*-i*, *--irq* 'us':: +Stop trace if the irq latency is higher than the argument in us. +*-T*, *--thread* 'us':: +Stop trace if the thread latency is higher than the argument in us. +*-s*, *--stack* 'us':: +Save the stack trace at the IRQ if a thread latency is higher than the +argument in us. +*-c*, *--cpus* 'cpu-list':: +Set the timerlat tracer to run the sample threads in the cpu-list. +*-d*, *--duration* 'time[s|m|h|d]':: +Set the duration of the session. +*-T*, *--trace*['=file']:: +Save the stopped trace to ['file|timerlat_trace.txt']. +*-q*, *--quiet*:: +Print only a summary at the end of the session. +*-P*, *--priority* 'o:prio|r:prio|f:prio|d:runtime:period':: +Set scheduling parameters to the timerlat tracer threads, the format to set +the priority are: + - 'o:prio' - use SCHED_OTHER with 'prio'; + - 'r:prio' - use SCHED_RR with 'prio'; + - 'f:prio' - use SCHED_FIFO with 'prio'; + - 'd:runtime[us|ms|s]:period[us|ms|s]' - use SCHED_DEADLINE with 'runtime' +and 'period' in nanoseconds. + +EXAMPLE +------- + +In the example below, the timerlat tracer is set to capture the stack trace at +the IRQ handler, printing it to the buffer if the *Thread Timer Latency* is +higher than _30 us_. It is also set to stop the session if a *Thread Timer +Latency* higher than _30 us_ is hit. Finally, it is set to save the trace +buffer if the stop condition is hit. + +------------------------------------------------------- +[root@alien ~]# rtla timerlat top -s 30 -t 30 -T + Timer Latency + 0 00:00:59 | IRQ Timer Latency (us) | Thread Timer Latency (us) +CPU COUNT | cur min avg max | cur min avg max + 0 #58634 | 1 0 1 10 | 11 2 10 23 + 1 #58634 | 1 0 1 9 | 12 2 9 23 + 2 #58634 | 0 0 1 11 | 10 2 9 23 + 3 #58634 | 1 0 1 11 | 11 2 9 24 + 4 #58634 | 1 0 1 10 | 11 2 9 26 + 5 #58634 | 1 0 1 8 | 10 2 9 25 + 6 #58634 | 12 0 1 12 | 30 2 10 30 <--- CPU with spike + 7 #58634 | 1 0 1 9 | 11 2 9 23 + 8 #58633 | 1 0 1 9 | 11 2 9 26 + 9 #58633 | 1 0 1 9 | 10 2 9 26 + 10 #58633 | 1 0 1 13 | 11 2 9 28 + 11 #58633 | 1 0 1 13 | 12 2 9 24 + 12 #58633 | 1 0 1 8 | 10 2 9 23 + 13 #58633 | 1 0 1 10 | 10 2 9 22 + 14 #58633 | 1 0 1 18 | 12 2 9 27 + 15 #58633 | 1 0 1 10 | 11 2 9 28 + 16 #58633 | 0 0 1 11 | 7 2 9 26 + 17 #58633 | 1 0 1 13 | 10 2 9 24 + 18 #58633 | 1 0 1 9 | 13 2 9 22 + 19 #58633 | 1 0 1 10 | 11 2 9 23 + 20 #58633 | 1 0 1 12 | 11 2 9 28 + 21 #58633 | 1 0 1 14 | 11 2 9 24 + 22 #58633 | 1 0 1 8 | 11 2 9 22 + 23 #58633 | 1 0 1 10 | 11 2 9 27 +timerlat hit stop tracing +saving trace to timerlat_trace.txt +[root@alien bristot]# tail -60 timerlat_trace.txt +[...] + timerlat/5-79755 [005] ....... 426.271226: #58634 context thread timer_latency 10823 ns + sh-109404 [006] dnLh213 426.271247: #58634 context irq timer_latency 12505 ns + sh-109404 [006] dNLh313 426.271258: irq_noise: local_timer:236 start 426.271245463 duration 12553 ns + sh-109404 [006] d...313 426.271263: thread_noise: sh:109404 start 426.271245853 duration 4769 ns + timerlat/6-79756 [006] ....... 426.271264: #58634 context thread timer_latency 30328 ns + timerlat/6-79756 [006] ....1.. 426.271265: <stack trace> + => timerlat_irq + => __hrtimer_run_queues + => hrtimer_interrupt + => __sysvec_apic_timer_interrupt + => sysvec_apic_timer_interrupt + => asm_sysvec_apic_timer_interrupt + => _raw_spin_unlock_irqrestore <---- spinlock that disabled interrupt. + => try_to_wake_up + => autoremove_wake_function + => __wake_up_common + => __wake_up_common_lock + => ep_poll_callback + => __wake_up_common + => __wake_up_common_lock + => fsnotify_add_event + => inotify_handle_inode_event + => fsnotify + => __fsnotify_parent + => __fput + => task_work_run + => exit_to_user_mode_prepare + => syscall_exit_to_user_mode + => do_syscall_64 + => entry_SYSCALL_64_after_hwframe + => 0x7265000001378c + => 0x10000cea7 + => 0x25a00000204a + => 0x12e302d00000000 + => 0x19b51010901b6 + => 0x283ce00726500 + => 0x61ea308872 + => 0x00000fe3 + bash-109109 [007] d..h... 426.271265: #58634 context irq timer_latency 1211 ns + timerlat/6-79756 [006] ....... 426.271267: timerlat_main: stop tracing hit on cpu 6 +---------------------------------------- + +In the trace, it is possible the notice that the *IRQ Timer Latency* was +already high, accounting *12505 ns*. The IRQ delay was caused by the +'bash-109109' process that disabled IRQs in the wake-up path +('_try_to_wake_up()' function). The duration of the IRQ handler that woke +up the timerlat thread, informed with the *irq_noise* event, was also high +and added more *12553 ns* to the Thread latency. Finally, the *thread_noise* +added by the currently running thread (including the scheduling overhead) +added more *4769 ns*. Summing up these values, the *Thread Timer Latency* +accounted for *30328 ns*. + +The primary reason for this high value is the wake-up path that was hit +twice during this case: when the 'bash-109109' was waking up a thread +and then when the 'timerlat' thread was awakened. This information can +then be used as the starting point of a more fine-grained analysis. + +Note that timerlat was dispatched without changing timerlat threads' priority. +That is generally not needed because the thread has priority FIFO:95 by +default, which is a common priority used by real-time kernel developers to +analyze scheduling delays. + +SEE ALSO +-------- +_rtla-timerlat(1)_, _rtla-timerlat-hist(1)_ + +Timerlat tracer documentation: <https://www.kernel.org/doc/html/latest/trace/timerlat-tracer.html> + +AUTHOR +------ +Written by Daniel Bristot de Oliveira <[email protected]> + +REPORTING BUGS +-------------- +Report bugs to <[email protected]> + +LICENSE +------- +rtla is Free Software licensed under the GNU GPLv2 + +COPYING +------- +Copyright \(C) 2021 Red Hat, Inc. Free use of this software is granted under +the terms of the GNU Public License (GPL).
Signature · 1 line
2.31.1
PATCH v3 19/19 rtla: Add rtla timerlat hist documentation
In reply to Daniel Bristot de OliveiraMan page for rtla timerlat hist mode.
--- .../rtla/Documentation/rtla-timerlat-hist.txt | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 tools/tracing/rtla/Documentation/rtla-timerlat-hist.txt
tools/tracing/rtla/Documentation/rtla-timerlat-hist.txt new file +162 -0
@@ -0,0 +1,162 @@ +rtla-timerlat-hist(1) +===================== + +NAME +---- +rtla-timerlat-hist - Histograms of the operating system timer latency + +SYNOPSIS +-------- +*rtla timerlat hist* ['OPTIONS'] ... + +DESCRIPTION +----------- +The rtla-hist-hist(1) mode displays a histogram of each tracer event occurrence. + +The rtla-timerlat(1) tool is an interface for the timerlat tracer. The +timerlat tracer dispatches a kernel thread per-cpu. These threads set a +periodic timer to wake themselves up and go back to sleep. After the wakeup, +they collect and generate useful information for the debugging of operating +system timer latency. + +The timerlat tracer outputs information in two ways. It periodically prints +the timer latency at the timer 'IRQ' handler and the 'Thread' handler. It +also provides information for each noise via the osnoise tracepoints. This +tool uses the periodic information, and the osnoise tracepoints are enabled +when using the -T option. + +OPTIONS +------- +*-h*, *--help*:: +Print help menu. +*-p*, *--period* 'us':: +Set the timerlat tracer period in microseconds. +*-i*, *--irq* 'us':: +Stop trace if the irq latency is higher than the argument in us. +*-T*, *--thread* 'us':: +Stop trace if the thread latency is higher than the argument in us. +*-s*, *--stack* 'us':: +Save the stack trace at the IRQ if a thread latency is higher than the +argument in us. +*-c*, *--cpus* 'cpu-list':: +Set the timerlat tracer to run the sample threads in the cpu-list. +*-d*, *--duration* 'time[s|m|h|d]':: +Set the duration of the session. +*-T*, *--trace*['=file']:: +Save the stopped trace to ['file|timerlat_trace.txt']. +*-P*, *--priority* 'o:prio|r:prio|f:prio|d:runtime:period':: +Set scheduling parameters to the timerlat tracer threads, the format to +set the priority are: + - 'o:prio' - use SCHED_OTHER with 'prio'; + - 'r:prio' - use SCHED_RR with 'prio'; + - 'f:prio' - use SCHED_FIFO with 'prio'; + - 'd:runtime[us|ms|s]:period[us|ms|s]' - use SCHED_DEADLINE with 'runtime' and +'period' in nanoseconds. + +*-b*, *--bucket-size* 'N':: +Set the histogram bucket size (default 1). +*-e*, *--entries* 'N':: +Set the number of entries of the histogram (default 256). +*--no-irq*:: +Ignore IRQ latencies. +*--no-thread*:: +Ignore thread latencies. +*--no-header*:: +So not print header. +*--no-summary*:: +Do not print summary. +*--no-index*:: +So not print index. +*--with-zeros*:: +Print zero only entries. + +EXAMPLE +------- +In the example below, *rtla timerlat hist* is set to run for '10' minutes, +in the cpus '0-4', 'skipping zero' only lines. Moreover, *rtla timerlat +hist* will change the priority of the timelat threads to run under +'SCHED_DEADLINE' priority, with a '10 us' runtime every '1 ms' period. The +'1ms' period is also passed to the timerlat tracer. + +------------------------------------------ +[root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1ms +# RTLA timerlat histogram +# Time unit is microseconds (us) +# Duration: 0 00:10:00 +Index IRQ-000 Thr-000 IRQ-001 Thr-001 IRQ-002 Thr-002 IRQ-003 Thr-003 IRQ-004 Thr-004 +0 276489 0 206089 0 466018 0 481102 0 205546 0 +1 318327 35487 388149 30024 94531 48382 83082 71078 388026 55730 +2 3282 122584 4019 126527 28231 109012 23311 89309 4568 98739 +3 940 11815 837 9863 6209 16227 6895 17196 910 9780 +4 444 17287 424 11574 2097 38443 2169 36736 462 13476 +5 206 43291 255 25581 1223 101908 1304 101137 236 28913 +6 132 101501 96 64584 635 213774 757 215471 99 73453 +7 74 169347 65 124758 350 57466 441 53639 69 148573 +8 53 85183 31 156751 229 9052 306 9026 39 139907 +9 22 10387 12 42762 161 2554 225 2689 19 26192 +10 13 1898 8 5770 114 1247 128 1405 13 3772 +11 9 560 9 924 71 686 76 765 8 713 +12 4 256 2 360 50 411 64 474 3 278 +13 2 167 2 172 43 256 53 350 4 180 +14 1 88 1 116 15 198 42 223 0 115 +15 2 63 3 94 11 139 20 150 0 58 +16 2 37 0 56 5 78 10 102 0 39 +17 0 18 0 28 4 57 8 80 0 15 +18 0 8 0 17 2 50 6 56 0 12 +19 0 9 0 5 0 19 0 48 0 18 +20 0 4 0 8 0 11 2 27 0 4 +21 0 2 0 3 1 9 1 18 0 6 +22 0 1 0 3 1 7 0 3 0 5 +23 0 2 0 4 0 2 0 7 0 2 +24 0 2 0 2 1 3 0 3 0 5 +25 0 0 0 1 0 1 0 1 0 3 +26 0 1 0 0 0 2 0 2 0 0 +27 0 0 0 3 0 1 0 0 0 1 +28 0 0 0 3 0 0 0 1 0 0 +29 0 0 0 2 0 2 0 1 0 3 +30 0 1 0 0 0 0 0 0 0 0 +31 0 1 0 0 0 0 0 2 0 2 +32 0 0 0 1 0 2 0 0 0 0 +33 0 0 0 2 0 0 0 0 0 1 +34 0 0 0 0 0 0 0 0 0 2 +35 0 1 0 1 0 0 0 0 0 1 +36 0 1 0 0 0 1 0 1 0 0 +37 0 0 0 1 0 0 0 0 0 0 +40 0 0 0 0 0 1 0 1 0 0 +41 0 0 0 0 0 0 0 0 0 1 +42 0 0 0 0 0 0 0 0 0 1 +44 0 0 0 0 0 1 0 0 0 0 +46 0 0 0 0 0 0 0 1 0 0 +47 0 0 0 0 0 0 0 0 0 1 +50 0 0 0 0 0 0 0 0 0 1 +54 0 0 0 1 0 0 0 0 0 0 +58 0 0 0 1 0 0 0 0 0 0 +over: 0 0 0 0 0 0 0 0 0 0 +count: 600002 600002 600002 600002 600002 600002 600002 600002 600002 600002 +min: 0 1 0 1 0 1 0 1 0 1 +avg: 0 5 0 5 0 4 0 4 0 5 +max: 16 36 15 58 24 44 21 46 13 50 +------------------------------------------ + +SEE ALSO +-------- +_rtla-timerlat(1)_, _rtla-timerlat-top(1)_ + +Timerlat tracer documentation: <https://www.kernel.org/doc/html/latest/trace/timerlat-tracer.html> + +AUTHOR +------ +Written by Daniel Bristot de Oliveira <[email protected]> + +REPORTING BUGS +-------------- +Report bugs to <[email protected]> + +LICENSE +------- +rtla is Free Software licensed under the GNU GPLv2 + +COPYING +------- +Copyright \(C) 2021 Red Hat, Inc. Free use of this software is granted under +the terms of the GNU Public License (GPL).
Signature · 1 line
2.31.1
Re: [PATCH V3 13/19] rtla: Add Documentation
In reply to Daniel Bristot de OliveiraQuoted 20 lines · Daniel Bristot de Oliveira
Adds the basis for rtla documentation. It is based on libtracefs Documentation as suggested by Steven Rostedt. This patch also includes the rtla(1) man page.
Cc Steven Rostedt <[email protected]>Cc Ingo Molnar <[email protected]>Cc Tom Zanussi <[email protected]>Cc Masami Hiramatsu <[email protected]>Cc Juri Lelli <[email protected]>Cc Clark Williams <[email protected]>Cc John Kacur <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Sebastian Andrzej Siewior <[email protected]>Cc Daniel Bristot de Oliveira <[email protected]>Suggested-by Steven Rostedt <[email protected]>Signed-off-by Daniel Bristot de Oliveira <[email protected]>
Quoted 15 lines
--- tools/tracing/rtla/Documentation/Makefile | 223 ++++++++++++++++++ .../tracing/rtla/Documentation/asciidoc.conf | 118 +++++++++ .../rtla/Documentation/manpage-base.xsl | 35 +++ .../rtla/Documentation/manpage-normal.xsl | 13 + tools/tracing/rtla/Documentation/rtla.txt | 56 +++++ tools/tracing/rtla/Documentation/utils.mk | 144 +++++++++++ tools/tracing/rtla/Makefile | 20 +- 7 files changed, 604 insertions(+), 5 deletions(-) create mode 100644 tools/tracing/rtla/Documentation/Makefile create mode 100644 tools/tracing/rtla/Documentation/asciidoc.conf create mode 100644 tools/tracing/rtla/Documentation/manpage-base.xsl create mode 100644 tools/tracing/rtla/Documentation/manpage-normal.xsl create mode 100644 tools/tracing/rtla/Documentation/rtla.txt create mode 100644 tools/tracing/rtla/Documentation/utils.mk
So please forgive me for being obnoxious but I have to ask...do we *really* need to add yet another markup language and docs build infrastructure to the kernel? I'm glad to see documentation, of course, but I would be gladder if it weren't a silo completely separate from the rest of the kernel docs. Is there a reason why this couldn't have been done with Sphinx?
Thanks,
jon
Re: [PATCH V3 06/19] rtla: Real-Time Linux Analysis tool
In reply to Daniel Bristot de Oliveiratools/tracing/rtla/Makefile line 1
Quoted 4 lines · Daniel Bristot de Oliveira
tools/tracing/rtla/Makefile new file +1
-0@@ -0,0 +1,59 @@ +CC := gcc
Some $(CROSS_COMPILE) for the poor souls who will integrate this into embedded distributions?
tools/tracing/rtla/Makefile line 12
Quoted 3 lines
tools/tracing/rtla/Makefile new file +3
-0+ +TRACEFS_HEADERS := $$(pkg-config --cflags libtracefs) +
ditto. This uses the host's pkg-config unconditionally.
Thanks,
--
Ahmed S. Darwish
Linutronix GmbH
Re: [PATCH V3 06/19] rtla: Real-Time Linux Analysis tool
Quoted 9 lines · Ahmed S. Darwish
tools/tracing/rtla/Makefile line 1
Quoted 4 lines · Daniel Bristot de Oliveira
tools/tracing/rtla/Makefile new file +1
-0@@ -0,0 +1,59 @@ +CC := gccSome $(CROSS_COMPILE) for the poor souls who will integrate this into embedded distributions?
Quoted 5 lines
tools/tracing/rtla/Makefile line 4
Quoted 3 lines
tools/tracing/rtla/Makefile new file +3
-0+ +TRACEFS_HEADERS := $$(pkg-config --cflags libtracefs) +ditto. This uses the host's pkg-config unconditionally.
mind trying this (on top of the current one)?
Thanks!
tools/tracing/rtla/Makefile +20 -4
@@ -1,14 +1,30 @@ NAME := rtla VERSION := 0.1 +# Makefiles suck: This macro sets a default value of $(2) for the +# variable named by $(1), unless the variable has been set by +# environment or command line. This is necessary for CC and AR +# because make sets default values, so the simpler ?= approach +# won't work as expected. +define allow-override + $(if $(or $(findstring environment,$(origin $(1))),\ + $(findstring command line,$(origin $(1)))),,\ + $(eval $(1) = $(2))) +endef + +# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix. +$(call allow-override,CC,$(CROSS_COMPILE)gcc) +$(call allow-override,AR,$(CROSS_COMPILE)ar) +$(call allow-override,PKG_CONFIG,pkg-config) +$(call allow-override,LD_SO_CONF_PATH,/etc/ld.so.conf.d/) +$(call allow-override,LDCONFIG,ldconfig) + INSTALL = install -CC := gcc FOPTS := -flto=auto -ffat-lto-objects -fexceptions -fstack-protector-strong \ - -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -MOPTS := -m64 -mtune=generic + -fasynchronous-unwind-tables -fstack-clash-protection WOPTS := -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -Wno-maybe-uninitialized -TRACEFS_HEADERS := $$(pkg-config --cflags libtracefs) +TRACEFS_HEADERS := $$($(PKG_CONFIG) --cflags libtracefs) CFLAGS := -O -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(MOPTS) $(WOPTS) $(TRACEFS_HEADERS) LDFLAGS := -ggdb
Re: [PATCH V3 13/19] rtla: Add Documentation
In reply to Jonathan CorbetQuoted 38 lines · Jonathan Corbet
Quoted 20 lines · Daniel Bristot de Oliveira
Adds the basis for rtla documentation. It is based on libtracefs Documentation as suggested by Steven Rostedt. This patch also includes the rtla(1) man page.
Cc Steven Rostedt <[email protected]>Cc Ingo Molnar <[email protected]>Cc Tom Zanussi <[email protected]>Cc Masami Hiramatsu <[email protected]>Cc Juri Lelli <[email protected]>Cc Clark Williams <[email protected]>Cc John Kacur <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Sebastian Andrzej Siewior <[email protected]>Cc Daniel Bristot de Oliveira <[email protected]>Suggested-by Steven Rostedt <[email protected]>Signed-off-by Daniel Bristot de Oliveira <[email protected]>Quoted 15 lines
--- tools/tracing/rtla/Documentation/Makefile | 223 ++++++++++++++++++ .../tracing/rtla/Documentation/asciidoc.conf | 118 +++++++++ .../rtla/Documentation/manpage-base.xsl | 35 +++ .../rtla/Documentation/manpage-normal.xsl | 13 + tools/tracing/rtla/Documentation/rtla.txt | 56 +++++ tools/tracing/rtla/Documentation/utils.mk | 144 +++++++++++ tools/tracing/rtla/Makefile | 20 +- 7 files changed, 604 insertions(+), 5 deletions(-) create mode 100644 tools/tracing/rtla/Documentation/Makefile create mode 100644 tools/tracing/rtla/Documentation/asciidoc.conf create mode 100644 tools/tracing/rtla/Documentation/manpage-base.xsl create mode 100644 tools/tracing/rtla/Documentation/manpage-normal.xsl create mode 100644 tools/tracing/rtla/Documentation/rtla.txt create mode 100644 tools/tracing/rtla/Documentation/utils.mk
Quoted 6 lines
So please forgive me for being obnoxious but I have to ask...do we *really* need to add yet another markup language and docs build infrastructure to the kernel? I'm glad to see documentation, of course, but I would be gladder if it weren't a silo completely separate from the rest of the kernel docs. Is there a reason why this couldn't have been done with Sphinx?
I am not a document format specialist, neither have a strong opinion on this, so suggestions are welcome. I used this format as a suggestion from steven, it is also similar to what we have on perf...
The idea here is to create a set of man pages. I saw that it is possible to create man pages using Sphinx, but there are so many options that it is hard to get started...
I also noticed that bpftools uses .rst files, but uses rst2man to convert the files.
Converting the current files to .rst is easy.
So, could give me some directions on what you think would be the best way to create this set of man pages?
A link to a project that creates a set of man pages using Sphinx using a Makefile would be a plus :-).
-- Daniel
Quoted 5 lines
Thanks,
jon
Steven Rostedt
maintainerRe: [PATCH V3 13/19] rtla: Add Documentation
Quoted 3 lines · On Tue, 19 Oct 2021 14:56:15 +0200 Daniel Bristot de Oliveira…
I am not a document format specialist, neither have a strong opinion on this, so suggestions are welcome. I used this format as a suggestion from steven, it is also similar to what we have on perf...
My suggestion came from not knowing that the man pages were going to live in the kernel Documentation tree ;-)
Quoted 7 lines
The idea here is to create a set of man pages. I saw that it is possible to create man pages using Sphinx, but there are so many options that it is hard to get started...
I also noticed that bpftools uses .rst files, but uses rst2man to convert the files.
Quoted 7 lines
Converting the current files to .rst is easy.
So, could give me some directions on what you think would be the best way to create this set of man pages?
A link to a project that creates a set of man pages using Sphinx using a
Makefilewould be a plus :-).
If everyone is OK with converting to .rst and using rst2man I'm fine with that.
-- Steve
Re: [PATCH V3 13/19] rtla: Add Documentation
Quoted 9 lines · Steven Rostedt
Quoted 3 lines · On Tue, 19 Oct 2021 14:56:15 +0200 Daniel Bristot de Oliveira…
I am not a document format specialist, neither have a strong opinion on this, so suggestions are welcome. I used this format as a suggestion from steven, it is also similar to what we have on perf...
My suggestion came from not knowing that the man pages were going to live in the kernel Documentation tree ;-)
That is true!
Question, should we mode these files to Documentation/trace/ ?
Quoted 12 lines
Quoted 12 lines
The idea here is to create a set of man pages. I saw that it is possible to create man pages using Sphinx, but there are so many options that it is hard to get started...
I also noticed that bpftools uses .rst files, but uses rst2man to convert the files.
Converting the current files to .rst is easy.
So, could give me some directions on what you think would be the best way to create this set of man pages?
Quoted 6 lines
Quoted 2 lines
A link to a project that creates a set of man pages using Sphinx using a
Makefilewould be a plus :-).If everyone is OK with converting to .rst and using rst2man I'm fine with that.
+1
-- Daniel
Quoted 2 lines
-- Steve
Steven Rostedt
maintainerRe: [PATCH V3 13/19] rtla: Add Documentation
Quoted 6 lines · On Tue, 19 Oct 2021 16:07:40 +0200 Daniel Bristot de Oliveira…
Quoted 2 lines
My suggestion came from not knowing that the man pages were going to live in the kernel Documentation tree ;-)
That is true!
Question, should we mode these files to
Documentation/trace/?
Hmm, maybe a sub directory?
Is this really tracing, or is it another domain (analysis)?
-- Steve
Re: [PATCH V3 13/19] rtla: Add Documentation
Quoted 6 lines · Steven Rostedt
Quoted 3 lines · On Tue, 19 Oct 2021 16:07:40 +0200 Daniel Bristot de Oliveira…
Quoted 2 lines
My suggestion came from not knowing that the man pages were going to live in the kernel Documentation tree ;-)
Quoted 7 lines
Quoted 3 lines
That is true!
Question, should we mode these files to
Documentation/trace/?Hmm, maybe a sub directory?
Is this really tracing, or is it another domain (analysis)?
Hummm... it uses tracing and capture trace... but to do analysis. rtsl (tool inside the rtla in the future) will be even more in the analysis side....
-- Daniel
Quoted 2 lines
-- Steve
Steven Rostedt
maintainerRe: [PATCH V3 13/19] rtla: Add Documentation
Quoted 4 lines · On Tue, 19 Oct 2021 17:08:57 +0200 Daniel Bristot de Oliveira…
Quoted 1 line
Is this really tracing, or is it another domain (analysis)?
Hummm... it uses tracing and capture trace... but to do analysis. rtsl (tool inside the rtla in the future) will be even more in the analysis side....
Right. It's a user of tracing, but not a tracer itself. Which is why I'm thinking it deserves its own category.
Jon, do you have thoughts about this?
-- Steve
Re: [PATCH V3 13/19] rtla: Add Documentation
In reply to Daniel Bristot de OliveiraQuoted 7 lines · Daniel Bristot de Oliveira
Quoted 2 lines · Steven Rostedt
My suggestion came from not knowing that the man pages were going to live in the kernel Documentation tree ;-)
That is true!
Question, should we mode these files to
Documentation/trace/?
Hmm...we don't really have man pages for individual commands now, so haven't thought much about how to handle them.
My first reaction would be to make a new directory like Documentation/tools and put man pages there. That can become a new "book" within the larger documentation collection. Make sense?
Thanks,
jon
Steven Rostedt
maintainerRe: [PATCH V3 13/19] rtla: Add Documentation
Quoted 3 lines · On Tue, 19 Oct 2021 09:28:33 -0600 Jonathan Corbet <[email protected]> wrote:
My first reaction would be to make a new directory like
Documentation/toolsand put man pages there. That can become a new "book" within the larger documentation collection. Make sense?
Sounds good to me. Daniel?
-- Steve
Re: [PATCH V3 13/19] rtla: Add Documentation
Quoted 8 lines · Steven Rostedt
Quoted 3 lines · On Tue, 19 Oct 2021 09:28:33 -0600 Jonathan Corbet <[email protected]> wrote:
My first reaction would be to make a new directory like
Documentation/toolsand put man pages there. That can become a new "book" within the larger documentation collection. Make sense?Sounds good to me. Daniel?
Sounds good to me... actually, not only to me, but for all tools on tools I guess.
Should I start with Documentation/tools/rtla/${rtla_files}.rst?
-- Daniel
Quoted 2 lines
-- Steve
Re: [PATCH V3 13/19] rtla: Add Documentation
In reply to Steven RostedtQuoted 10 lines · Steven Rostedt
Quoted 4 lines · On Tue, 19 Oct 2021 17:08:57 +0200 Daniel Bristot de Oliveira…
Quoted 1 line
Is this really tracing, or is it another domain (analysis)?
Hummm... it uses tracing and capture trace... but to do analysis. rtsl (tool inside the rtla in the future) will be even more in the analysis side....
Right. It's a user of tracing, but not a tracer itself. Which is why I'm thinking it deserves its own category.
For the docs only, or for the tool itself too... like, tools/rtla/ ?
-- Daniel
Quoted 5 lines
Jon, do you have thoughts about this?
-- Steve
Re: [PATCH V3 13/19] rtla: Add Documentation
In reply to Daniel Bristot de OliveiraQuoted 3 lines · Daniel Bristot de Oliveira
Sounds good to me... actually, not only to me, but for all tools on tools I guess.
Should I start with
Documentation/tools/rtla/${rtla_files}.rst?
Sounds good to me.
Thanks,
jon