Operating-System Kernels

a kernel spinlock

Two CPU cores in a kernel can try to touch the same data structure at the same time, and without coordination they will corrupt it. A lock makes one wait while the other works. A spinlock is the simplest kind of lock for the kernel: when a core cannot get the lock because another core holds it, it does not go to sleep - it just spins, sitting in a tight loop continuously re-checking the lock until it becomes free, then grabs it. It is busy-waiting: burning CPU cycles doing nothing useful except waiting.

Spinning sounds wasteful, and for long waits it is - but it is exactly right for very short critical sections, because it avoids the overhead of putting a task to sleep and waking it later. If the lock will be held for only a handful of instructions, spinning a few cycles is far cheaper than a context switch. The deeper reason spinlocks exist, though, is that they are the ONLY kind of lock usable in interrupt context, where you cannot sleep at all. A top-half interrupt handler or a softirq that needs to protect shared data has no choice: it must use a spinlock, because the sleeping alternative (a mutex) is forbidden where there is no task to put to sleep.

Here is the rule you must never violate, and the most important thing to remember about spinlocks: you must not sleep while holding one. Imagine holding a spinlock and then doing something that blocks - the holder is now asleep and not running, while another core spins forever waiting for a lock that will never be released, because the holder cannot wake up to release it. That is a deadlock that can freeze the machine. So code under a spinlock must be short, must not call anything that might sleep (no sleeping memory allocation, no copy_from_user which can fault and block, no mutex), and on a single processor it typically also disables preemption (and sometimes interrupts) so the holder cannot be scheduled away mid-section. When the work might need to sleep, you use a mutex instead, not a spinlock.

spin_lock(&lock); list_add(&node, &shared_list); spin_unlock(&lock); // tiny, no sleeping inside. NEVER: spin_lock(&lock); mutex_lock(&m); /* may sleep -> deadlock */ ; or kmalloc(n, GFP_KERNEL) (may sleep) under the spinlock.

A spinlock guards a tiny critical section by busy-waiting. Holding one, you must never call anything that can sleep.

The cardinal rule: never sleep while holding a spinlock - the holder would block while other cores spin forever waiting, deadlocking the machine. Use a spinlock only for very short, sleep-free critical sections (and it is the only lock allowed in interrupt context); if the work can block, use a sleeping mutex instead.

Also called
spinlockbusy-wait lockspin lock自旋鎖