2

Just curious why spin_lock_irqsave needs to disable the preemption after disabling local interrupt.

static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
    unsigned long flags;

    local_irq_save(flags);
    preempt_disable(); ===> can preemption happen with interrupt disabled?
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    ...
}

Preemption should only be possible with interrupt enabled, thus there should be no need to worry about preemption after disabling interrupt.

Spencer Wieczorek
  • 21,229
  • 7
  • 44
  • 54
eric chen
  • 21
  • 3
  • possible duplicate of [Linux Kernel: Spinlock SMP: Why there is a preempt\_disable() in spin\_lock\_irq SMP version?](http://stackoverflow.com/questions/13263538/linux-kernel-spinlock-smp-why-there-is-a-preempt-disable-in-spin-lock-irq-sm) – Michael Burr Nov 30 '14 at 05:33
  • from Documentation/preempt-locking.txt: But keep in mind that 'irqs disabled' is a fundamentally unsafe way of disabling preemption - any spin_unlock() decreasing the preemption count to 0 might trigger a reschedule. A simple printk() might trigger a reschedule. So use this implicit preemption-disabling property only if you know that the affected codepath does not do any of this. Best policy is to use this only for small, atomic code that you wrote and which calls no complex functions. – eric chen Nov 30 '14 at 05:43

1 Answers1

1

Because there exist functions which cause preemption unless preemption is explicitly disabled, regardless of the state of interrupts. The assumption being that if preemption was not allowed, it would be explicitly disabled and the function would not preempt. Using interrupts to do preemption disabling instead violates this assumption.

One such function is cond_resched(), which calls _cond_resched() in core.c (https://elixir.bootlin.com/linux/v5.9-rc5/source/kernel/sched/core.c#L6116)

It checks for preemption being enabled and invokes the scheduler. This function is called from a number of places in the kernel and it's possible to accidentally trigger one of them, breaking your spin-lock protected critical section.

Furthermore, the interrupt disabling spin lock implies that your critical section may be accessed from an interrupt handler. If you accidentally trigger preemption using cond_resched(), once your process gets scheduled back interrupts will be re-enabled. If an interrupt occurs which attempts to acquire the lock, you will have a deadlock.

Matviy Kotoniy
  • 362
  • 1
  • 13