It'sPete
It'sPete

Reputation: 5211

spin_lock_irqsave() in interrupt context

I'm maintaining a driver which shares some resource between the ISR (i.e., in interrupt context) and the read() syscall. In both cases, spin_lock_irqsave() is used, since (obviously) the resource can be acquired in the interrupt context.

However, I was wondering if using spin_lock_irqsave() is necessary in the interrupt context. Namely, the Unreliable Guide to Locking (see here: https://kernel.readthedocs.io/en/sphinx-samples/kernel-locking.html) states:

Note that the spin_lock_irqsave() will turn off interrupts if they are on, otherwise does nothing (if we are already in an interrupt handler), hence these functions are safe to call from any context.

As a result, is it common practice to use "normal" spin_lock() in the interrupt handler (since the particular interrupt is already disabled) and then call spin_lock_irqsave() in the user context? Alternatively, is the better practice to just use spin_lock_irqsave() everywhere? I'm leaning towards the latter, for two reasons:

  1. As soon as someone sees that a lock is acquired with spin_lock_irqsave(), it's obvious that the lock is intended to be shared with the interrupt context.
  2. As someone maintaining the code, you don't have to ensure whether or not a particular function is going to be called in what context. Said differently, using spin_lock_irqsave() works in any context, so you don't have to ensure that a function is only called in a certain context.

With the above said, I'm wondering what the convention/best practice is for code that resides in kernel space. Is it better to use spin_lock_irqsave() everywhere the lock is acquired, even if you can guarantee that the lock is being acquired from the interrupt context?

Upvotes: 4

Views: 3604

Answers (1)

07 0xff
07 0xff

Reputation: 21

See Unreliable Guide To Locking in kernel documentation. There's a table of minimum requirements for locking to synchronize between different contexts which, roughly speaking, can be summarized as:

  1. If one of them is a process: use the ones that are strong enough to disable the other. For example if the other competitor is a softirq, then you need at least spin_lock_bh, which disables softirq while locking.
  2. Else if one of the them is hard irq: the advent of hard irq is inevitable unless you disable it beforehand, so spin_lock_irq or spin_lock_irqsave, depending on whether the other is hard irq or not.
  3. Otherwise, use spin_lock.

(Of course, those are under assumption that your kernel isn't config as PREEMPT_RT)

Upvotes: 1

Related Questions