当任务正在执行关键部分但需要在禁用了抢占的单处理器系统上进行调度时,会发生什么情况?

时间:2019-01-24 14:15:29

标签: linux-kernel kernel scheduling spinlock preemption

这是一个场景。假设某个内核任务在单处理器系统上运行且禁用了抢占功能。任务获得一个自旋锁。现在,它正在执行关键部分。此时,如果该任务可用的时间片到期并且必须将其排定,该怎么办?

  1. spin_lock有防止这种情况发生的机制吗?
  2. 可以预定吗?如果是,那么关键部分会怎样?
  3. 它可以被中断请求中断吗? (假设已禁用抢占功能)
  4. 这种情况可行吗?换句话说,这种情况会发生吗?

从内核代码中,我了解到spin_lock基本上是禁用了抢占的单处理器上的nop。准确地说,它所做的只是barrier() 我知道为什么它是nop(因为它是单处理器,并且没有其他任务可以在那一瞬间处理数据),但我仍然不知道如何将其不间断(由于IRQ或调度)。 我在这里想念什么?指向Linux内核代码的指针对此很有帮助。

我的基本假设:

32位Linux内核

2 个答案:

答案 0 :(得分:1)

实际上,spin_lock()通过在尝试获取锁之前调用preempt_disable()来禁用抢占,因此情况#1,#2,#3永远不会发生。 spin_lock()从最近的源代码中最终调用__raw_spin_lock(),后者在调用preempt_disable()来获取锁之前先调用spin_acquire()。中断上下文中常用的spin_lock_irqsave()具有相似的上下文。

关于#3,如果变量是在进程/中断上下文之间共享的,则应始终使用spin_lock_irq()/spin_lock_irqsave()而不是spin_lock()以避免死锁。

答案 1 :(得分:0)

处理时间片到期的机制是计时器中断。中断将为该进程设置TIF_NEEDS_RESCHED标志。从计时器的中断上下文返回到关键部分时,将检查是否由于TIF_NEEDS_RESCHED标志而抢占了该进程。由于禁用了抢占功能,因此什么也不会发生,它会返回到您的关键部分。

关键部分结束后,释放锁将调用preempt_enable()以重新启用抢占。在那一刻,再次检查是否要抢占。由于已设置TIF_NEEDS_RESCHED标志并启用了抢占功能,因此该进程将被抢占。

  1. 自旋锁禁用抢占。
  2. 否,因为抢占已禁用。
  3. 是的。有自旋锁版本禁用IRQ来防止这种情况。
  4. 否,因为自旋锁禁用了抢占。

自旋锁在单元处理器系统上根本不存在,因为它们没有意义。如果不拥有锁的线程尝试获取该锁,则意味着拥有该锁的线程当前处于睡眠状态(只有一个cpu)。因此,没有理由旋转等待正在睡着的东西。因此,在这些情况下,自旋锁已被优化为仅可抢占禁用,因此没有其他线程可以触及关键部分。