In the linux kernel, why can\'t you sleep while holding a spinlock?
It's not that you can't sleep while holding a spin lock. It is a very very bad idea to do that. Quoting LDD:
Therefore, the core rule that applies to spinlocks is that any code must, while holding a spinlock, be atomic. It cannot sleep; in fact, it cannot relinquish the processor for any reason except to service interrupts (and sometimes not even then).
Any deadlock like mentioned above may result in an unrecoverable state. Another thing that could happen is that the spinlock gets locked on one CPU, and then when the thread sleeps, it wakes up on the other CPU, resulting in a kernel panic.
Answering Bandicoot's comment, in a spin lock context, pre-emption is disabled only in case of a uniprocessor pre-emptible kernel because disabling pre-emption effectively prevents races.
If the kernel is compiled without CONFIG_SMP, but CONFIG_PREEMPT is set, then spinlocks simply disable preemption, which is sufficient to prevent any races. For most purposes, we can think of preemption as equivalent to SMP, and not worry about it separately.
http://www.kernel.org/pub/linux/kernel/people/rusty/kernel-locking/index.html
The key point is in Linux kernel, acquiring a spin lock will disable preemption. Thus sleeping while holding a spin lock could potentially cause deadlock.
For example, thread A acquires a spin lock. Thread A will not be preempted until it releases the lock. As long as thread A quickly does its job and releases the lock, there is no problem. But if thread A sleeps while holding the lock, thread B could be scheduled to run since the sleep function will invoke the scheduler. And thread B could acquire the same lock as well. Thread B also disables preemption and tries to acquire the lock. And a deadlock occurs. Thread B will never get the lock since thread A holds it, and thread A will never get to run since thread B disables preemption.
And why disabling preemption in the first place? I guess it's because we don't want threads on other processors to wait too long.