Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spin_lock_irqsave vs spin_lock_irq

On an SMP machine we must use spin_lock_irqsave and not spin_lock_irq from interrupt context.

Why would we want to save the flags (which contain the IF)?

Is there another interrupt routine that could interrupt us?

like image 220
cojocar Avatar asked Apr 01 '10 10:04

cojocar


People also ask

What is Spin_lock_irqsave?

spin_lock_irqsave is basically used to save the interrupt state before taking the spin lock, this is because spin lock disables the interrupt, when the lock is taken in interrupt context, and re-enables it when while unlocking. The interrupt state is saved so that it should reinstate the interrupts again.

What is spin lock in Linux?

The basic form of locking in the Linux kernel is the spinlock. Spinlocks take their name from the fact that they continuously loop, or spin, waiting to acquire a lock. Because spinlocks operate in this manner, it is imperative not to have any section of code inside a spinlock attempt to acquire a lock twice.


2 Answers

spin_lock_irqsave is basically used to save the interrupt state before taking the spin lock, this is because spin lock disables the interrupt, when the lock is taken in interrupt context, and re-enables it when while unlocking. The interrupt state is saved so that it should reinstate the interrupts again.

Example:

  1. Lets say interrupt x was disabled before spin lock was acquired
  2. spin_lock_irq will disable the interrupt x and take the the lock
  3. spin_unlock_irq will enable the interrupt x.

So in the 3rd step above after releasing the lock we will have interrupt x enabled which was earlier disabled before the lock was acquired.

So only when you are sure that interrupts are not disabled only then you should spin_lock_irq otherwise you should always use spin_lock_irqsave.

like image 86
pastum Avatar answered Sep 22 '22 14:09

pastum


If interrupts are already disabled before your code starts locking, when you call spin_unlock_irq you will forcibly re-enable interrupts in a potentially unwanted manner. If instead you also save the current interrupt enable state in flags through spin_lock_irqsave, attempting to re-enable interrupts with the same flags after releasing the lock, the function will just restore the previous state (thus not necessarily enabling interrupts).

Example with spin_lock_irqsave:

spinlock_t mLock = SPIN_LOCK_UNLOCK; unsigned long flags;  spin_lock_irqsave(&mLock, flags); // Save the state of interrupt enable in flags and then disable interrupts // Critical section spin_unlock_irqrestore(&mLock, flags); // Return to the previous state saved in flags 

Example with spin_lock_irq( without irqsave ):

spinlock_t mLock = SPIN_LOCK_UNLOCK; unsigned long flags;  spin_lock_irq(&mLock); // Does not know if interrupts are already disabled // Critical section spin_unlock_irq(&mLock); // Could result in an unwanted interrupt re-enable... 
like image 27
Hagai Avatar answered Sep 19 '22 14:09

Hagai