On 23/07/2020 20:56, Nicholas Piggin wrote:
> With the previous patch, lockdep hardirq state changes should not be
> redundant. Softirq state changes already follow that pattern.
> 
> So warn on unexpected enable-when-enabled or disable-when-disabled
> conditions, to catch possible errors or sloppy patterns that could
> lead to similar bad behavior due to NMIs etc.


This one does not apply anymore as Peter's changes went in already but
this one is not really a fix so I can live with that. Did 1/2 go
anywhere? Thanks,


> 
> Signed-off-by: Nicholas Piggin <npig...@gmail.com>
> ---
>  kernel/locking/lockdep.c           | 80 +++++++++++++-----------------
>  kernel/locking/lockdep_internals.h |  4 --
>  kernel/locking/lockdep_proc.c      | 10 +---
>  3 files changed, 35 insertions(+), 59 deletions(-)
> 
> diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
> index 29a8de4c50b9..138458fb2234 100644
> --- a/kernel/locking/lockdep.c
> +++ b/kernel/locking/lockdep.c
> @@ -3649,15 +3649,8 @@ void lockdep_hardirqs_on_prepare(unsigned long ip)
>       if (unlikely(!debug_locks || current->lockdep_recursion))
>               return;
>  
> -     if (unlikely(current->hardirqs_enabled)) {
> -             /*
> -              * Neither irq nor preemption are disabled here
> -              * so this is racy by nature but losing one hit
> -              * in a stat is not a big deal.
> -              */
> -             __debug_atomic_inc(redundant_hardirqs_on);
> +     if (DEBUG_LOCKS_WARN_ON(current->hardirqs_enabled))
>               return;
> -     }
>  
>       /*
>        * We're enabling irqs and according to our state above irqs weren't
> @@ -3695,15 +3688,8 @@ void noinstr lockdep_hardirqs_on(unsigned long ip)
>       if (unlikely(!debug_locks || curr->lockdep_recursion))
>               return;
>  
> -     if (curr->hardirqs_enabled) {
> -             /*
> -              * Neither irq nor preemption are disabled here
> -              * so this is racy by nature but losing one hit
> -              * in a stat is not a big deal.
> -              */
> -             __debug_atomic_inc(redundant_hardirqs_on);
> +     if (DEBUG_LOCKS_WARN_ON(curr->hardirqs_enabled))
>               return;
> -     }
>  
>       /*
>        * We're enabling irqs and according to our state above irqs weren't
> @@ -3738,6 +3724,9 @@ void noinstr lockdep_hardirqs_off(unsigned long ip)
>       if (unlikely(!debug_locks || curr->lockdep_recursion))
>               return;
>  
> +     if (DEBUG_LOCKS_WARN_ON(!curr->hardirqs_enabled))
> +             return;
> +
>       /*
>        * So we're supposed to get called after you mask local IRQs, but for
>        * some reason the hardware doesn't quite think you did a proper job.
> @@ -3745,17 +3734,13 @@ void noinstr lockdep_hardirqs_off(unsigned long ip)
>       if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
>               return;
>  
> -     if (curr->hardirqs_enabled) {
> -             /*
> -              * We have done an ON -> OFF transition:
> -              */
> -             curr->hardirqs_enabled = 0;
> -             curr->hardirq_disable_ip = ip;
> -             curr->hardirq_disable_event = ++curr->irq_events;
> -             debug_atomic_inc(hardirqs_off_events);
> -     } else {
> -             debug_atomic_inc(redundant_hardirqs_off);
> -     }
> +     /*
> +      * We have done an ON -> OFF transition:
> +      */
> +     curr->hardirqs_enabled = 0;
> +     curr->hardirq_disable_ip = ip;
> +     curr->hardirq_disable_event = ++curr->irq_events;
> +     debug_atomic_inc(hardirqs_off_events);
>  }
>  EXPORT_SYMBOL_GPL(lockdep_hardirqs_off);
>  
> @@ -3769,6 +3754,9 @@ void lockdep_softirqs_on(unsigned long ip)
>       if (unlikely(!debug_locks || current->lockdep_recursion))
>               return;
>  
> +     if (DEBUG_LOCKS_WARN_ON(curr->softirqs_enabled))
> +             return;
> +
>       /*
>        * We fancy IRQs being disabled here, see softirq.c, avoids
>        * funny state and nesting things.
> @@ -3776,11 +3764,6 @@ void lockdep_softirqs_on(unsigned long ip)
>       if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
>               return;
>  
> -     if (curr->softirqs_enabled) {
> -             debug_atomic_inc(redundant_softirqs_on);
> -             return;
> -     }
> -
>       current->lockdep_recursion++;
>       /*
>        * We'll do an OFF -> ON transition:
> @@ -3809,26 +3792,26 @@ void lockdep_softirqs_off(unsigned long ip)
>       if (unlikely(!debug_locks || current->lockdep_recursion))
>               return;
>  
> +     if (DEBUG_LOCKS_WARN_ON(!curr->softirqs_enabled))
> +             return;
> +
>       /*
>        * We fancy IRQs being disabled here, see softirq.c
>        */
>       if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
>               return;
>  
> -     if (curr->softirqs_enabled) {
> -             /*
> -              * We have done an ON -> OFF transition:
> -              */
> -             curr->softirqs_enabled = 0;
> -             curr->softirq_disable_ip = ip;
> -             curr->softirq_disable_event = ++curr->irq_events;
> -             debug_atomic_inc(softirqs_off_events);
> -             /*
> -              * Whoops, we wanted softirqs off, so why aren't they?
> -              */
> -             DEBUG_LOCKS_WARN_ON(!softirq_count());
> -     } else
> -             debug_atomic_inc(redundant_softirqs_off);
> +     /*
> +      * We have done an ON -> OFF transition:
> +      */
> +     curr->softirqs_enabled = 0;
> +     curr->softirq_disable_ip = ip;
> +     curr->softirq_disable_event = ++curr->irq_events;
> +     debug_atomic_inc(softirqs_off_events);
> +     /*
> +      * Whoops, we wanted softirqs off, so why aren't they?
> +      */
> +     DEBUG_LOCKS_WARN_ON(!softirq_count());
>  }
>  
>  static int
> @@ -5684,6 +5667,11 @@ void __init lockdep_init(void)
>  
>       printk(" per task-struct memory footprint: %zu bytes\n",
>              sizeof(((struct task_struct *)NULL)->held_locks));
> +
> +     WARN_ON(irqs_disabled());
> +
> +     current->hardirqs_enabled = 1;
> +     current->softirqs_enabled = 1;
>  }
>  
>  static void
> diff --git a/kernel/locking/lockdep_internals.h 
> b/kernel/locking/lockdep_internals.h
> index baca699b94e9..6dd8b1f06dc4 100644
> --- a/kernel/locking/lockdep_internals.h
> +++ b/kernel/locking/lockdep_internals.h
> @@ -180,12 +180,8 @@ struct lockdep_stats {
>       unsigned int   chain_lookup_misses;
>       unsigned long  hardirqs_on_events;
>       unsigned long  hardirqs_off_events;
> -     unsigned long  redundant_hardirqs_on;
> -     unsigned long  redundant_hardirqs_off;
>       unsigned long  softirqs_on_events;
>       unsigned long  softirqs_off_events;
> -     unsigned long  redundant_softirqs_on;
> -     unsigned long  redundant_softirqs_off;
>       int            nr_unused_locks;
>       unsigned int   nr_redundant_checks;
>       unsigned int   nr_redundant;
> diff --git a/kernel/locking/lockdep_proc.c b/kernel/locking/lockdep_proc.c
> index 5525cd3ba0c8..98f204220ed9 100644
> --- a/kernel/locking/lockdep_proc.c
> +++ b/kernel/locking/lockdep_proc.c
> @@ -172,12 +172,8 @@ static void lockdep_stats_debug_show(struct seq_file *m)
>  #ifdef CONFIG_DEBUG_LOCKDEP
>       unsigned long long hi1 = debug_atomic_read(hardirqs_on_events),
>                          hi2 = debug_atomic_read(hardirqs_off_events),
> -                        hr1 = debug_atomic_read(redundant_hardirqs_on),
> -                        hr2 = debug_atomic_read(redundant_hardirqs_off),
>                          si1 = debug_atomic_read(softirqs_on_events),
> -                        si2 = debug_atomic_read(softirqs_off_events),
> -                        sr1 = debug_atomic_read(redundant_softirqs_on),
> -                        sr2 = debug_atomic_read(redundant_softirqs_off);
> +                        si2 = debug_atomic_read(softirqs_off_events);
>  
>       seq_printf(m, " chain lookup misses:           %11llu\n",
>               debug_atomic_read(chain_lookup_misses));
> @@ -196,12 +192,8 @@ static void lockdep_stats_debug_show(struct seq_file *m)
>  
>       seq_printf(m, " hardirq on events:             %11llu\n", hi1);
>       seq_printf(m, " hardirq off events:            %11llu\n", hi2);
> -     seq_printf(m, " redundant hardirq ons:         %11llu\n", hr1);
> -     seq_printf(m, " redundant hardirq offs:        %11llu\n", hr2);
>       seq_printf(m, " softirq on events:             %11llu\n", si1);
>       seq_printf(m, " softirq off events:            %11llu\n", si2);
> -     seq_printf(m, " redundant softirq ons:         %11llu\n", sr1);
> -     seq_printf(m, " redundant softirq offs:        %11llu\n", sr2);
>  #endif
>  }
>  
> 

-- 
Alexey

Reply via email to