Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spin_lock on non-preemtive linux kernels

I read that on a system with 1 CPU and non preemtive linux kernel (2.6.x) a spin_lock call is equivalent to an empty call, and thus implemented that way.

I can't understand that: shouldn't it be equivalent to a sleep on a mutex? Even on non-preemtive kernels interrupt handlers may still be executed for example or I might call a function that would put the original thread to sleep. So it's not true that an empty spin_lock call is "safe" as it would be if it was implemented as a mutex.

Is there something I don't get?

like image 278
Emiliano Avatar asked Dec 03 '22 04:12

Emiliano


2 Answers

If you were to use spin_lock() on a non-preemptive kernel to shield data against an interrupt handler, you'd deadlock (on a single-processor machine).

If the interrupt handler runs while other kernel code holds the lock, it will spin forever, as there is no way for the regular kernel code to resume and release the lock.

Spinlocks can only be used if the lock holder can always run to completion.

The solution for a lock that might be wanted by an interrupt handler is to use spin_lock_irqsave(), which disables interrupts while the spinlock is held. With 1 cpu, no interrupt handler can run, so there will not be a deadlock. On smp, an interrupt handler might start spinning on another cpu, but since the cpu holding the lock can't be interrupted, the lock will eventually be released.

like image 106
Eric Seppanen Avatar answered Dec 11 '22 10:12

Eric Seppanen


To answer the two parts of your question:

Even on non-preemtive kernels interrupt handlers may still be executed for example ...

spin_lock() isn't supposed to protect against interrupt handlers - only user context kernel code. spin_lock_irqsave() is the interrupt-disabling version, and this isn't a no-op on a non-preemptive uniprocessor.

...or I might call a function that would put the original thread to sleep.

It is not allowed to sleep while holding a spin lock. This is the "Scheduling while atomic" bug. If you want to sleep, you have to use a mutex instead (again - these aren't a no-op on non-preemptive uniprocessor).

like image 23
caf Avatar answered Dec 11 '22 10:12

caf