]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
trace/osnoise: Add trace events for samples
authorTomas Glozar <tglozar@redhat.com>
Mon, 3 Feb 2025 09:04:18 +0000 (10:04 +0100)
committerSteven Rostedt (Google) <rostedt@goodmis.org>
Thu, 27 Feb 2025 00:44:30 +0000 (19:44 -0500)
Add trace events that fire at osnoise and timerlat sample generation, in
addition to the already existing noise and threshold events.

This allows processing the samples directly in the kernel, either with
ftrace triggers or with BPF.

Cc: John Kacur <jkacur@redhat.com>
Cc: Luis Goncalves <lgoncalv@redhat.com>
Link: https://lore.kernel.org/20250203090418.1458923-1-tglozar@redhat.com
Signed-off-by: Tomas Glozar <tglozar@redhat.com>
Tested-by: Gabriele Monaco <gmonaco@redhat.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
include/trace/events/osnoise.h
kernel/trace/trace_osnoise.c

index a2379a4f06849dc2a1a6c49981ab211c0973b07c..3f42736238014ee2b9c3e518f3dbff702683619b 100644 (file)
@@ -3,9 +3,105 @@
 #define TRACE_SYSTEM osnoise
 
 #if !defined(_OSNOISE_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+
+#ifndef _OSNOISE_TRACE_H
 #define _OSNOISE_TRACE_H
+/*
+ * osnoise sample structure definition. Used to store the statistics of a
+ * sample run.
+ */
+struct osnoise_sample {
+       u64                     runtime;        /* runtime */
+       u64                     noise;          /* noise */
+       u64                     max_sample;     /* max single noise sample */
+       int                     hw_count;       /* # HW (incl. hypervisor) interference */
+       int                     nmi_count;      /* # NMIs during this sample */
+       int                     irq_count;      /* # IRQs during this sample */
+       int                     softirq_count;  /* # softirqs during this sample */
+       int                     thread_count;   /* # threads during this sample */
+};
+
+#ifdef CONFIG_TIMERLAT_TRACER
+/*
+ * timerlat sample structure definition. Used to store the statistics of
+ * a sample run.
+ */
+struct timerlat_sample {
+       u64                     timer_latency;  /* timer_latency */
+       unsigned int            seqnum;         /* unique sequence */
+       int                     context;        /* timer context */
+};
+#endif // CONFIG_TIMERLAT_TRACER
+#endif // _OSNOISE_TRACE_H
 
 #include <linux/tracepoint.h>
+TRACE_EVENT(osnoise_sample,
+
+       TP_PROTO(struct osnoise_sample *s),
+
+       TP_ARGS(s),
+
+       TP_STRUCT__entry(
+               __field(        u64,            runtime )
+               __field(        u64,            noise   )
+               __field(        u64,            max_sample      )
+               __field(        int,            hw_count        )
+               __field(        int,            irq_count       )
+               __field(        int,            nmi_count       )
+               __field(        int,            softirq_count   )
+               __field(        int,            thread_count    )
+       ),
+
+       TP_fast_assign(
+               __entry->runtime = s->runtime;
+               __entry->noise = s->noise;
+               __entry->max_sample = s->max_sample;
+               __entry->hw_count = s->hw_count;
+               __entry->irq_count = s->irq_count;
+               __entry->nmi_count = s->nmi_count;
+               __entry->softirq_count = s->softirq_count;
+               __entry->thread_count = s->thread_count;
+       ),
+
+       TP_printk("runtime=%llu noise=%llu max_sample=%llu hw_count=%d"
+                 " irq_count=%d nmi_count=%d softirq_count=%d"
+                 " thread_count=%d",
+                 __entry->runtime,
+                 __entry->noise,
+                 __entry->max_sample,
+                 __entry->hw_count,
+                 __entry->irq_count,
+                 __entry->nmi_count,
+                 __entry->softirq_count,
+                 __entry->thread_count)
+);
+
+#ifdef CONFIG_TIMERLAT_TRACER
+TRACE_EVENT(timerlat_sample,
+
+       TP_PROTO(struct timerlat_sample *s),
+
+       TP_ARGS(s),
+
+       TP_STRUCT__entry(
+               __field(        u64,            timer_latency   )
+               __field(        unsigned int,   seqnum          )
+               __field(        int,            context         )
+       ),
+
+       TP_fast_assign(
+               __entry->timer_latency = s->timer_latency;
+               __entry->seqnum = s->seqnum;
+               __entry->context = s->context;
+       ),
+
+       TP_printk("timer_latency=%llu seqnum=%u context=%d",
+                 __entry->timer_latency,
+                 __entry->seqnum,
+                 __entry->context)
+);
+#endif // CONFIG_TIMERLAT_TRACER
+
 TRACE_EVENT(thread_noise,
 
        TP_PROTO(struct task_struct *t, u64 start, u64 duration),
index f3a2722ee4c07882e420c3c8cb4dafa85ef05467..d7083526d922782f7d1eb6450dd9de87d3971517 100644 (file)
@@ -315,33 +315,6 @@ static inline void osn_var_reset_all(void)
  */
 bool trace_osnoise_callback_enabled;
 
-/*
- * osnoise sample structure definition. Used to store the statistics of a
- * sample run.
- */
-struct osnoise_sample {
-       u64                     runtime;        /* runtime */
-       u64                     noise;          /* noise */
-       u64                     max_sample;     /* max single noise sample */
-       int                     hw_count;       /* # HW (incl. hypervisor) interference */
-       int                     nmi_count;      /* # NMIs during this sample */
-       int                     irq_count;      /* # IRQs during this sample */
-       int                     softirq_count;  /* # softirqs during this sample */
-       int                     thread_count;   /* # threads during this sample */
-};
-
-#ifdef CONFIG_TIMERLAT_TRACER
-/*
- * timerlat sample structure definition. Used to store the statistics of
- * a sample run.
- */
-struct timerlat_sample {
-       u64                     timer_latency;  /* timer_latency */
-       unsigned int            seqnum;         /* unique sequence */
-       int                     context;        /* timer context */
-};
-#endif
-
 /*
  * Tracer data.
  */
@@ -497,7 +470,7 @@ static void print_osnoise_headers(struct seq_file *s)
  * Record an osnoise_sample into the tracer buffer.
  */
 static void
-__trace_osnoise_sample(struct osnoise_sample *sample, struct trace_buffer *buffer)
+__record_osnoise_sample(struct osnoise_sample *sample, struct trace_buffer *buffer)
 {
        struct ring_buffer_event *event;
        struct osnoise_entry *entry;
@@ -520,17 +493,19 @@ __trace_osnoise_sample(struct osnoise_sample *sample, struct trace_buffer *buffe
 }
 
 /*
- * Record an osnoise_sample on all osnoise instances.
+ * Record an osnoise_sample on all osnoise instances and fire trace event.
  */
-static void trace_osnoise_sample(struct osnoise_sample *sample)
+static void record_osnoise_sample(struct osnoise_sample *sample)
 {
        struct osnoise_instance *inst;
        struct trace_buffer *buffer;
 
+       trace_osnoise_sample(sample);
+
        rcu_read_lock();
        list_for_each_entry_rcu(inst, &osnoise_instances, list) {
                buffer = inst->tr->array_buffer.buffer;
-               __trace_osnoise_sample(sample, buffer);
+               __record_osnoise_sample(sample, buffer);
        }
        rcu_read_unlock();
 }
@@ -574,7 +549,7 @@ static void print_timerlat_headers(struct seq_file *s)
 #endif /* CONFIG_PREEMPT_RT */
 
 static void
-__trace_timerlat_sample(struct timerlat_sample *sample, struct trace_buffer *buffer)
+__record_timerlat_sample(struct timerlat_sample *sample, struct trace_buffer *buffer)
 {
        struct ring_buffer_event *event;
        struct timerlat_entry *entry;
@@ -594,15 +569,17 @@ __trace_timerlat_sample(struct timerlat_sample *sample, struct trace_buffer *buf
 /*
  * Record an timerlat_sample into the tracer buffer.
  */
-static void trace_timerlat_sample(struct timerlat_sample *sample)
+static void record_timerlat_sample(struct timerlat_sample *sample)
 {
        struct osnoise_instance *inst;
        struct trace_buffer *buffer;
 
+       trace_timerlat_sample(sample);
+
        rcu_read_lock();
        list_for_each_entry_rcu(inst, &osnoise_instances, list) {
                buffer = inst->tr->array_buffer.buffer;
-               __trace_timerlat_sample(sample, buffer);
+               __record_timerlat_sample(sample, buffer);
        }
        rcu_read_unlock();
 }
@@ -1608,7 +1585,7 @@ static int run_osnoise(void)
        /* Save interference stats info */
        diff_osn_sample_stats(osn_var, &s);
 
-       trace_osnoise_sample(&s);
+       record_osnoise_sample(&s);
 
        notify_new_max_latency(max_noise);
 
@@ -1803,7 +1780,7 @@ static enum hrtimer_restart timerlat_irq(struct hrtimer *timer)
        s.timer_latency = diff;
        s.context = IRQ_CONTEXT;
 
-       trace_timerlat_sample(&s);
+       record_timerlat_sample(&s);
 
        if (osnoise_data.stop_tracing) {
                if (time_to_us(diff) >= osnoise_data.stop_tracing) {
@@ -1923,7 +1900,7 @@ static int timerlat_main(void *data)
                s.timer_latency = diff;
                s.context = THREAD_CONTEXT;
 
-               trace_timerlat_sample(&s);
+               record_timerlat_sample(&s);
 
                notify_new_max_latency(diff);
 
@@ -2529,7 +2506,7 @@ timerlat_fd_read(struct file *file, char __user *ubuf, size_t count,
                s.timer_latency = diff;
                s.context = THREAD_URET;
 
-               trace_timerlat_sample(&s);
+               record_timerlat_sample(&s);
 
                notify_new_max_latency(diff);
 
@@ -2564,7 +2541,7 @@ timerlat_fd_read(struct file *file, char __user *ubuf, size_t count,
        s.timer_latency = diff;
        s.context = THREAD_CONTEXT;
 
-       trace_timerlat_sample(&s);
+       record_timerlat_sample(&s);
 
        if (osnoise_data.stop_tracing_total) {
                if (time_to_us(diff) >= osnoise_data.stop_tracing_total) {