Re: [DOCUMENTATION] Revised Unreliable Kernel Locking Guide

From: Manfred Spraul
Date: Fri Dec 12 2003 - 22:18:41 EST


Hi Rusty,

From Chapter 4.1:

|spin_lock_irqsave()| (include/linux/spinlock.h) is a variant which saves whether interrupts were on or off in a flags word, which is passed to |spin_unlock_irqrestore()|. This means that the same code can be used inside an hard irq handler (where interrupts are already off) and in softirqs (where the irq disabling is required).

Interrupts are typically on within the hard irq handler.
spin_lock() is usually ok because an interrupt handler is never reentered. Thus if a lock is only accessed from a single irq handler, then spin_lock() is the faster approach. That's why many nic drivers use spin_lock instead of spin_lock_irqsave() in their irq handlers.
OTHO: if a driver lock is a global resource that is used from different irqs, then it must either use _irqsave(), or set SA_INTERRUPT.
Examples: rtc_lock relies on SA_INTERRUPT: it's touched from the rtc irq and the timer irq path, and both rtc and timer set SA_INTERRUPT.
I assume ide relies on _irqsave(), but the code is too difficult to follow.

Btw, perhaps you could add the 2nd synchronization approach for interrupts: if it's an extremely rare event, then no lock at all in the irq handler (no reentrancy guaranteed by the kernel), and spin_lock+disable_irq() in the softirq/tasklet. My network drivers use that to synchronize packet rx with close.

--
Manfred

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/