Why linux disables kernel preemption after the kernel code holds a spinlock?

Vishal Gandhi picture Vishal Gandhi · Aug 15, 2013 · Viewed 7.6k times · Source

I am new to Linux and am reading Linux device drivers book by Rubini & Corbet. I am confused at one statement related to spinlocks; the book states

If a nonpreemptive uniprocessor system ever went into a spin on a lock, it would spin forever; no other thread would ever be able to obtain the CPU to release the lock. For this reason, spinlock operations on uniprocessor systems without preemption enabled are optimized to do nothing, with the exception of the ones that change the IRQ masking status.

Further the book states

The kernel preemption case is handled by the spinlock code itself. Any time kernel code holds a spinlock, preemption is disabled on the relevant processor. Even uniprocessor systems must disable preemption in this way to avoid race conditions.

Question : On a uniprocessor system, if kernel preemption is disabled whenever a kernel code (executing on behalf of the user process) holds the spinlock, then how could another process ever get a chance to run and hence try at acquring the spinlock ? Why does Linux Kernel disables kernel preemption whenever kernel code holds a spinlock?

Answer

superdesk picture superdesk · Aug 15, 2013

The answer to your first question is the reasoning behind your second.

Spinlocks acquired by the kernel may be implemented by turning off preemption, because this ensures that the kernel will complete its critical section without another process interfering. The entire point is that another process will not be able to run until the kernel releases the lock.

There is no reason that it has to be implemented this way; it is just a simple way to implement it and prevents any process from spinning on the lock that the kernel holds. But this trick only works for the case in which the kernel has acquired the lock: user processes can not turn off preemption, and if the kernel is spinning (i.e. it tries to acquire a spinlock but another process already holds it) it better leave preemption on! Otherwise the system will hang since the kernel is waiting for a lock that will not be released because the process holding it can not release it.

The kernel acquiring a spinlock is a special case. If a user level program acquires a spinlock, preemption will not be disabled.