Avoid sleep while holding a spin lock

I recently read section 5.5.2 (Spinlocks and Atomic Context) of LDDv3:

Avoiding sleep while holding a lock can be tricky; many kernel functions can sleep, and this behavior is not always well-documented . Copying data to or from user space is an obvious example: it is necessary that the required user space page can be replaced from disk before the copy can continue, and this operation clearly requires sleep. Almost any operation that should allocate memory can sleep; kmalloc may decide to abandon the processor and wait for more memory to appear, unless explicitly stated. Beds can happen in amazing places; the writing code that will be executed under spinlock requires attention to all the functions that you call .

It is clear to me that spin blocks should always be held for a minimum amount of time, and I think it is relatively easy to write the correct code using spin lock from scratch.

Suppose, however, that we have a large project in which pins are widely used. How can we make sure that functions called from critical sections protected by spinlocks will never sleep?

Thanks in advance!

+4
source share
2 answers

How about enabling sleep-inside-spin-lock checks for your kernel? It is usually located in the "Kernel Debugging" section when running make config. You can also try to duplicate its behavior in your code.

+4
source

One thing that I have noticed in many projects is people who seem to misuse spinlocks, they are used instead of the other fixing primitives that should have been used.

Linux spin-lock exists only in multiprocessor assemblies (in single processes the gating of the spin-lock preprocessor jobs is empty), which are used for short circuits on a multiprocessor platform.

If the code cannot use the spin lock, it simply rotates the processor until the lock becomes free. Thus, any other process running on another processor should release the lock, or perhaps it can be released by the interrupt handler, but the wait event mechanism is a much better way to wait for an interrupt.

The ipqsave-spinlock primitive is a neat way to disable / enable interrupts so that the driver can block the interrupt handler, but it must be done long enough so that the process can update some variables shared by the interrupt handler if you disable it and you are not going to schedule it.

If you need to block an interrupt handler, use spin lock with irqsave.

For a general kernel lock, you should use the mutex / semaphore api, which will sleep on the lock if necessary.

To lock code running in other processes, use muxtex / semaphore. To block code running in an interrupt context, use irq save / restore or spinlock_irq save / restore

To block code running on other processors, use spin blocks and do not hold the lock for long.

I hope this helps

-1
source

All Articles