1

I was going through with internals of "Completion" APIs, and found out that we cannot use wait_for_completion() if interrupts are already disabled on the processor. However semaphore does not have this restriction.

Excerpt from kernel doc: https://docs.kernel.org/scheduler/completion.html

Note that wait_for_completion() is calling spin_lock_irq()/spin_unlock_irq(), so it can only be called safely when you know that interrupts are enabled. Calling it from IRQs-off atomic contexts will result in hard-to-detect spurious enabling of interrupts.

My queries are:

  1. Why cannot we call irqsave version of spinlock inside wait_for_completion() ?
  2. Despite having good interface, is it not making completion unpopular synchronization technique vis a vis semaphore?
MankPan
  • 79
  • 6
  • 2
    You can't do a wait of any kind when interrupts are disabled. – stark Jun 29 '23 at 17:00
  • @stark, but then why down() calls raw_spin_lock_irqsave() ? semaphore also wait – MankPan Jun 29 '23 at 18:13
  • down? You mean the function marked `Use of this function is deprecated, please use down_interruptible`? – stark Jun 29 '23 at 18:52
  • 1
    Neither `wait_for_completion` nor `down_interruptible` are *allowed* to be called in atomic context. The fact that [implementation](https://elixir.bootlin.com/linux/v6.3.10/source/kernel/locking/semaphore.c#L77) of `down_interruptible` uses `raw_spin_lock_irqsave` instead of more lightweight `raw_spin_lock_irq` looks strange: calling irqsave version has a sense only in the code which may be executed in atomic context. But `down_interruptible` even calls `might_sleep();`, which warns when called in atomic context... – Tsyvarev Jun 29 '23 at 21:50
  • @Tsyvarev, I found explanation about why down(_interruptible()) is calling raw_spin_lock_irqsave(). Please see lines 12-25 [here](https://elixir.bootlin.com/linux/v6.4/source/kernel/locking/semaphore.c) – MankPan Jun 30 '23 at 12:15
  • 2
    "It turns out various parts of the kernel expect to be able to use down() on a semaphore in interrupt context when they know it will succeed, so we have to use irqsave variants for down(), down_interruptible() and down_killable() too." - Oh, ok. I suspected that non-blocking usage of `down` could be a reason for irqsave usage. But the very first version of `down` has been accompanied with non-blocking `down_trylock`. And instead of replacing incorrect usage of `down` with `down_trylock`, they decided to modify `down`... – Tsyvarev Jun 30 '23 at 14:01

0 Answers0