【发布时间】:2021-05-06 23:59:24
【问题描述】:
考虑以下内核代码
local_irq_disable();
__update_rq_clock(rq);
spin_lock(&rq->lock);
rq 是指向每个处理器 struct 的指针(即不受 SMP 并发约束)。由于在调用 local_irq_disable 后,rq 将永远不会在另一个地方被访问(因为 rq 仅由单个处理器使用,并且禁用本地中断意味着不会在该 CPU 上运行中断处理程序),那么有什么意义在前面的函数之间嵌入__update_rq_clock?换句话说,考虑到rq 在__update_rq_clock 内部的两种情况下都是安全的,无论是否被锁定,它与以下内容有何不同?
spin_lock_irqsave(&rq->lock, flags);
__update_rq_clock(rq);
【问题讨论】:
-
第一个代码在获取锁之前更新,所以锁没有效果。第二个代码保存了之前的 irq 状态,想必以后会恢复。所以它们是非常不同的。
-
@stark 没关系,调用
local_irq_disable或spin_lock_irqsave的结果是一样的:它们都会禁用中断。中断级别的唯一区别是spin_lock_irqsave会记住启用了哪些中断,禁用了哪些中断,以便我们以后可以将它们恢复为以前的状态,而local_irq_enable只会启用所有内容。但我不关心这部分,我的问题不是关于启用中断,而是关于锁定rq的含义、__update_rq_clock内部的安全性以及调用这些函数的顺序。 -
不同之处在于关键部分(受锁保护)在他们的情况下比在你的情况下更小。如果某些功能不需要锁保护,为什么要在锁下调用它?
-
@Tsyvarev 但是,这没关系!是一样的,
rq在这两种情况下都受到了根本的保护,rq不受 SMP 并发的影响,因为它是一个 per-processor 结构,这意味着唯一的并发风险来自中断处理程序,但中断处理程序被 @ 禁用987654339@,这意味着rq没有被其他地方访问的风险(既不是处理器也不是中断处理程序!),因此将spin_lock(&rq->lock)延迟到__update_rq_clock(rq)之后不会导致更小的临界区,因为实际上没有关键部分! -
这意味着我们实际上没有从延迟
spin_lock中得到任何东西,所以我们可以直接使用spin_lock_irqsave,它绝对会导致同样的事情!
标签: c concurrency linux-kernel locking spinlock