Search code examples
clinux-kernelmutexinterruptspinlock

Use spin_lock() vs down_interruptible() in workqueue


I run into a situation that using spin_lock() inside a workqueue hangs the system in case the intervals between multiple interrupts are too short. After changing spin_lock() to down_interruptible() the issue is gone for now.

However I saw several bottom halves implementation in kernel code that use spin_lock() instead of mutex/semaphore (for example, the irq-function in a request_threaded_irq()). What would be the reason for that? My best guess is the mutex/sempahore might be overkill in this situation.


Solution

  • It depends entirely on what data you are trying to protect with this lock and from where (which context) that data can be accessed (besides the workqueue). If the lock and corresponding data can be also accessed from the atomic context (such as interrupt handlers), you should use appropriate locking.

    Workqueue is about process context, thus it's allowed to go to sleep if necessary. Also going to sleep while holding spin_lock would be a fatal error. So in workqueue you can use sleep-able functions but not while holding spin_lock.

    Semaphores are sleep-able locks like mutexes, so if your data and the corresponding lock will not be used from within atomic context, I see no reason to give up mutexes/semaphores.

    More info:

    Interrupts, Spin Locks, and Preemption

    Linux kernel interrupt handler mutex protection.