Why can't you sleep while holding a spinlock?

In the linux kernel, why can't you sleep while holding a spin lock?

+7
source share
8 answers

Example: your driver is executing and has just unlocked it, which controls access to its device. While the lock is held, the device throws an interrupt, which is why your interrupt handler starts. The interrupt handler must also obtain a lock before accessing the device. Spin lock allocation in an interrupt handler is a legit thing; this is one of the reasons that spinlock operations are not sleeping. But what happens if the interrupt procedure is executed on the same processor as the code that originally took out the lock? While the interrupt handler is spinning, the interrupt code will not be able to run to release the lock. This processor will spin forever.

Source: http://www.makelinux.net/ldd3/chp-5-sect-5.shtml

+15
source

It is not that you cannot sleep while holding a direct lock. This is a very bad idea. Quoting LDD:

Therefore, the basic rule applicable to spinlocks is that any code must, while holding a spin lock, be atomic. He cannot sleep; in fact, he cannot refuse the processor for any reason other than service interruptions (and sometimes not even then).

Any deadlock, as mentioned above, can lead to an irreparable state. Another thing that can happen is that the spin lock is blocked on one CPU, and then when the thread sleeps, it wakes up on another CPU, which leads to a kernel panic.

Bandicoot's answering comment, in the context of spin lock, pre-emption is disabled only in the case of a single-processor pre-released kernel, because disabling pre-emption effectively prevents races.

If the kernel is compiled without CONFIG_SMP, but CONFIG_PREEMPT is installed, then spinlocks simply disables preemption, which is sufficient to prevent any races. For most purposes, we can think of the SMP equivalent advantage and not worry about it separately.

http://www.kernel.org/pub/linux/kernel/people/rusty/kernel-locking/index.html

+7
source

I do not agree with William's answer (his example). He mixes two different concepts: continuity and synchronization.

The interrupt context can supplant the process context, and thus, if RESOURCE is used between them, we need to use

spin_lock_irqsave() 

(1) disable IRQ (2) to get the lock. In step 1, we could disable interruption prevention.

I think this thread is very convincing. Sleep () means that the thread / process gives the CPU and CONTEXT SWITCH control to another without releasing the spin lock, which is why it is wrong.

+3
source

The key point is the Linux kernel, in which locking the lock will disable prevention. Thus, sleeping while holding a spin lock can potentially cause a dead end.

For example, thread A receives a spin lock. Thread A will not be unloaded 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 can be scheduled since the sleep function will call the scheduler. And thread B could get the same lock. Thread B also disables prevention and attempts to obtain a lock. And there is a dead end. Thread B will never get a lock, since thread A holds it, and thread A will never start, since thread B disables prevention.

And why is disabling preemptive use in the first place? I suppose because we don’t want threads on other processors to wait too long.

+3
source

I think this mail has a clear answer:

The process cannot be unloaded and do not sleep while maintaining a spin lock due to the behavior of the studs. If the process captures a spin lock and goes to bed before releasing it. A second process is expected (or an interrupt handler) that will capture the spin lock. On a single-processor machine, the second process blocks the CPU, preventing the first process from waking up and releasing the spin lock so that the second process continues, this is basically a dead end.

+3
source

Another likely explanation is that prevention is disabled in the context of spinlocks.

+2
source

In addition, what is said in it, suppose that the process is asleep while holding a file. If a new scheduled process tries to get the same direct lock, it starts spinning so that access to the lock is available. As the new process continues to spin, it is not possible to schedule the first process, and thus the lock will never be released so that the second process rotates forever, and we have a dead end.

+2
source

totally agree with Nan Wang. I think the most important concept is “prevention” and “planning,” and how this happens when you acquire spin locks. when a forced lock occurs, the continuity is disabled (true or not, I don’t know, but I suppose it’s right), this means that interrupting the timer cannot force out the current spin-lock holder, but the current direct commit still causes drowsy kernel functions and actively invokes the scheduler and run the "other task". if the “other task”, as it turned out, wanted to purchase the same spin-block as the first spin-lock holder, a problem arises here: since prevention is already disabled by the first spin-lock holder, the “other task”, which is caused by an active call of the scheduler with using the first spin-lock holder, it cannot be forced out, therefore its rotation always takes the processor, which is why there is a dead end.

0
source

All Articles