嗨,大家好, 在对我们的一些驱动程序进行SMP移植时(在 powerpc target)我们观察了一些我需要你们做的行为 阐明道:
在UP系统上执行local_irq_disable()时,jiffies倾向于 冻结,即计数停止递增。这是预期的吗?我想 递减器中断是“内部”而不应该得到 受到local_irq_disable调用的影响,因为我预计会这样做 禁用本地IRQ中断处理(外部中断)。该 系统当然也会在执行local_irq_enable()时冻结 jiffies计数跳跃,它似乎补偿了'时间 在local_irq_disable()和enable()之间调用。
在SMP系统(具有2个e500核心的P2020)上执行相同操作 结果令人惊讶。首先是插入的模块 这项测试总是在核心1上执行。此外,它有时会执行 没有看到冻结'jiffies'柜台,有时我们看到它 确实冻结了。再次在计数冻结的情况下,它往往会跳跃 在做了local_irq_enable()之后。我不知道为什么会这样 发生。 我们知道在SMP的情况下,两个核心都运行一个计划计时器,所以 在某些情况下,我们看不到冻结jiffie计数或是它 只是核心0?
此外,由于内核定时器依赖于'jiffies' - 这意味着 如果local_irq_disable()已经发生,我们的内核定时器都不会触发 做完了?这是在一个核心中的一个核心上完成的情况 SMP系统?
还有很多其他问题,但我想这些问题就足够了 从关于相同的一般性讨论开始:)
TIA
NS
从实验中得到的更多评论。
我现在的理解是,由于内核定时器依赖于'jiffies'来触发,因此当我发出local_irq_save()时,它们实际上不会在UP系统上触发。实际上,我们的一些代码是基于这样的假设:当我发出local_irq_save()时,它可以保证防止本地处理器和内核定时器上的中断。
然而,在SMP系统上执行相同的实验,即使两个内核都执行local_irq_save(),jiffies也不会停止递增,系统也不会冻结。这怎么可能 ? LINUX是否使用其他机制来触发SMP系统中的定时器中断或可能使用IPI?这也打破了我们的假设,即local_irq_disable将保护系统免受至少在同一核心上运行的内核定时器的影响。
我们如何编写对异步事件(即中断和内核定时器)安全的代码,并且对UP和SMP都有效。
答案 0 :(得分:4)
local_irq_disable仅禁用当前内核的中断,因此,当您是单核时,所有内容都被禁用(包括计时器中断),这就是为什么jiffies不会更新的原因。 在SMP上运行时,有时你会碰巧禁用更新jiffies的核心中断,有时候不会。 这通常不是问题,因为中断应该仅在非常短的时间内被禁用,并且所有预定的定时器将在中断再次启用后触发。
您如何知道您的模块始终在核心1上运行?在内核的当前版本上,它甚至可能同时在多个核心上运行(也就是说,如果你没有强迫它不这样做)。
答案 1 :(得分:4)
这个问题有几个方面。让我们一个接一个。
1
A)
local_irq_save()只是清除eflags寄存器的IF标志。 IRQ处理程序可以在其他核心上运行。
global_irq_save()不可用,因为这需要实现处理器间通信,并且无论如何都不需要它,因为本地irq禁用仅用于非常短的时间段。
b)中
现代APIC允许在当前内核之间进行IRQ动态分配,除了极少数例外,内核实际上编写了必要的寄存器以获得IRQ的循环分布。
这样做的结果是,如果在本地禁用irqs足够长的时间,当APIC向禁用它们的核心提供IRQ时,最终结果将是系统将全局停止接收此特定IRQ直到最终在接收到该类型的最后一个IRQ的核心上本地重新启用irqs的点。
2
关于jiffies更新和irq禁用的不同结果,它取决于所选的clocksource。
您可以通过咨询来确定选择哪一个:
$ cat / sys / devices / system / clocksource / clocksource0 / current_clocksource
如果你有tsc作为clocksource,那么所有核心都在本地拥有它。但是,如果你的clocksource是其他东西,即:HPET是一个外部设备,那么jiffies将因第1点所述的原因而被冻结。