tracing: Account bottom half disabled sections.
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Mon, 13 Dec 2021 10:08:53 +0000 (11:08 +0100)
committerSteven Rostedt <rostedt@goodmis.org>
Thu, 13 Jan 2022 21:23:04 +0000 (16:23 -0500)
Disabling only bottom halves via local_bh_disable() disables also
preemption but this remains invisible to tracing. On a CONFIG_PREEMPT
kernel one might wonder why there is no scheduling happening despite the
N flag in the trace. The reason might be the a rcu_read_lock_bh()
section.

Add a 'b' to the tracing output if in task context with disabled bottom
halves.

Link: https://lkml.kernel.org/r/YbcbtdtC/bjCKo57@linutronix.de
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
include/linux/trace_events.h
kernel/trace/trace.c
kernel/trace/trace_output.c

index 3900404..70c069a 100644 (file)
@@ -172,6 +172,7 @@ enum trace_flag_type {
        TRACE_FLAG_SOFTIRQ              = 0x10,
        TRACE_FLAG_PREEMPT_RESCHED      = 0x20,
        TRACE_FLAG_NMI                  = 0x40,
+       TRACE_FLAG_BH_OFF               = 0x80,
 };
 
 #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
index 547d826..a73d78d 100644 (file)
@@ -2603,6 +2603,8 @@ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status)
                trace_flags |= TRACE_FLAG_HARDIRQ;
        if (in_serving_softirq())
                trace_flags |= TRACE_FLAG_SOFTIRQ;
+       if (softirq_count() >> (SOFTIRQ_SHIFT + 1))
+               trace_flags |= TRACE_FLAG_BH_OFF;
 
        if (tif_need_resched())
                trace_flags |= TRACE_FLAG_NEED_RESCHED;
@@ -4190,7 +4192,7 @@ unsigned long trace_total_entries(struct trace_array *tr)
 static void print_lat_help_header(struct seq_file *m)
 {
        seq_puts(m, "#                    _------=> CPU#            \n"
-                   "#                   / _-----=> irqs-off        \n"
+                   "#                   / _-----=> irqs-off/BH-disabled\n"
                    "#                  | / _----=> need-resched    \n"
                    "#                  || / _---=> hardirq/softirq \n"
                    "#                  ||| / _--=> preempt-depth   \n"
@@ -4231,7 +4233,7 @@ static void print_func_help_header_irq(struct array_buffer *buf, struct seq_file
 
        print_event_info(buf, m);
 
-       seq_printf(m, "#                            %.*s  _-----=> irqs-off\n", prec, space);
+       seq_printf(m, "#                            %.*s  _-----=> irqs-off/BH-disabled\n", prec, space);
        seq_printf(m, "#                            %.*s / _----=> need-resched\n", prec, space);
        seq_printf(m, "#                            %.*s| / _---=> hardirq/softirq\n", prec, space);
        seq_printf(m, "#                            %.*s|| / _--=> preempt-depth\n", prec, space);
index 3547e71..8aa493d 100644 (file)
@@ -445,14 +445,18 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
        char irqs_off;
        int hardirq;
        int softirq;
+       int bh_off;
        int nmi;
 
        nmi = entry->flags & TRACE_FLAG_NMI;
        hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
        softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
+       bh_off = entry->flags & TRACE_FLAG_BH_OFF;
 
        irqs_off =
+               (entry->flags & TRACE_FLAG_IRQS_OFF && bh_off) ? 'D' :
                (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
+               bh_off ? 'b' :
                (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' :
                '.';