lkml.org 
[lkml]   [2011]   [Apr]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 4/7] lockdep: Printk nice description for irq inversion bug
    From: Steven Rostedt <srostedt@redhat.com>

    The irq inversion and irq dependency bug are only subtly different.
    The diffenerence lies where the interrupt occurred.

    For irq dependency:

    irq_disable
    lock(A)
    lock(B)
    unlock(B)
    unlock(A)
    irq_enable

    lock(B)
    unlock(B)

    <interrupt>
    lock(A)

    The interrupt comes in after it has been established that lock A
    can be held when taking an irq unsafe lock. Lockdep detects the problem
    when taking lock A in interrupt context.

    <interrupt>
    lock(A)

    irq_disable
    lock(A)
    lock(B)
    unlock(B)
    unlock(A)
    irq_enable

    lock(B)
    unlock(B)

    With the irq_inversion the irq happens before it is established
    and lockdep detects the problem with the taking of lock B.

    Since the problem with the locking for both of these issues are
    in actuality the same, they both should report the same scenario.

    other info that might help us debug this:

    Chain exists of:
    &rq->lock --> lockA --> lockC

    Possible interrupt unsafe locking scenario:

    CPU0 CPU1
    ---- ----
    lock(lockC);
    local_irq_disable();
    lock(&rq->lock);
    lock(lockA);
    <Interrupt>
    lock(&rq->lock);

    *** DEADLOCK ***

    Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
    ---
    kernel/lockdep.c | 34 +++++++++++++++++++++++++++++-----
    1 files changed, 29 insertions(+), 5 deletions(-)

    diff --git a/kernel/lockdep.c b/kernel/lockdep.c
    index a0f253b..8646b8c 100644
    --- a/kernel/lockdep.c
    +++ b/kernel/lockdep.c
    @@ -1395,15 +1395,15 @@ print_shortest_lock_dependencies(struct lock_list *leaf,
    static void
    print_irq_lock_scenario(struct lock_list *safe_entry,
    struct lock_list *unsafe_entry,
    - struct held_lock *prev,
    - struct held_lock *next)
    + struct lock_class *prev_class,
    + struct lock_class *next_class)
    {
    struct lock_class *safe_class = safe_entry->class;
    struct lock_class *unsafe_class = unsafe_entry->class;
    - struct lock_class *middle_class = hlock_class(prev);
    + struct lock_class *middle_class = prev_class;

    if (middle_class == safe_class)
    - middle_class = hlock_class(next);
    + middle_class = next_class;

    /*
    * A direct locking problem where unsafe_class lock is taken
    @@ -1499,7 +1499,8 @@ print_bad_irq_dependency(struct task_struct *curr,
    print_stack_trace(forwards_entry->class->usage_traces + bit2, 1);

    printk("\nother info that might help us debug this:\n\n");
    - print_irq_lock_scenario(backwards_entry, forwards_entry, prev, next);
    + print_irq_lock_scenario(backwards_entry, forwards_entry,
    + hlock_class(prev), hlock_class(next));

    lockdep_print_held_locks(curr);

    @@ -2219,6 +2220,10 @@ print_irq_inversion_bug(struct task_struct *curr,
    struct held_lock *this, int forwards,
    const char *irqclass)
    {
    + struct lock_list *entry = other;
    + struct lock_list *middle = NULL;
    + int depth;
    +
    if (!debug_locks_off_graph_unlock() || debug_locks_silent)
    return 0;

    @@ -2237,6 +2242,25 @@ print_irq_inversion_bug(struct task_struct *curr,
    printk("\n\nand interrupts could create inverse lock ordering between them.\n\n");

    printk("\nother info that might help us debug this:\n");
    +
    + /* Find a middle lock (if one exists) */
    + depth = get_lock_depth(other);
    + do {
    + if (depth == 0 && (entry != root)) {
    + printk("lockdep:%s bad path found in chain graph\n", __func__);
    + break;
    + }
    + middle = entry;
    + entry = get_lock_parent(entry);
    + depth--;
    + } while (entry && entry != root && (depth >= 0));
    + if (forwards)
    + print_irq_lock_scenario(root, other,
    + middle ? middle->class : root->class, other->class);
    + else
    + print_irq_lock_scenario(other, root,
    + middle ? middle->class : other->class, root->class);
    +
    lockdep_print_held_locks(curr);

    printk("\nthe shortest dependencies between 2nd lock and 1st lock:\n");
    --
    1.7.2.3



    \
     
     \ /
      Last update: 2011-04-21 03:45    [W:0.060 / U:1.116 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site