嗨,伙计们,当我们的一些司机(PowerPC目标)的SMP移植,我们观察到一些行为,我需要你们摆脱一些光:
在UP系统上执行local_irq_disable()时,jiffies往往会冻结,即计数停止递增。 这是预期的吗? 我认为这个递减中断是'内部的',不应该受到local_irq_disabletypes调用的影响,因为我期望它禁止本地IRQ中断处理(外部中断)。 系统当然冻结,然后还做了一个local_irq_enable()jiffies计数跳转,它似乎是补偿local_irq_disable()和enable()调用之间的“时间stream逝”。
在SMP系统(2个e500核心的P2020)上做相同的结果是令人惊讶的。 首先,被插入的模块执行这个testing总是在核心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将保护系统免受同时在同一核心上运行的核心定时器的影响。
我们如何编写一个对asynchronous事件安全的代码,即中断和内核定时器,并且对于UP和SMP都是有效的。
local_irq_disable只会禁用当前内核的中断,所以,当你是单核的时候,所有的东西都被禁止了(包括定时器中断),这就是为什么jiffies没有被更新。 在SMP上运行时,有时候会碰巧禁用正在更新jiffies的内核的中断,有时候不会。 这通常不是问题,因为中断只能在非常短的时间内被禁止,所有的定时器将在中断被重新启用后触发。
你怎么知道你的模块总是在核心1上运行? 在当前版本的内核中,它甚至可能同时运行在多个内核上(也就是说,如果你不强迫它不这样做的话)。
这个问题有几个方面。 让我们一个1。
1。
一个)
local_irq_save()只是清除eflags寄存器的IF标志。 IRQ处理程序可以在其他内核上一致地运行。
global_irq_save()不可用,因为这将需要处理器间通信来实现,因为本地irq禁用仅在很短的时间内才有用,所以它不是真正需要的。
b)
现代的APIC允许在当前的内核之间进行IRQ动态分配,除了极少数例外,内核本质上是编程必要的寄存器以获得IRQ的循环分配。
这样做的结果是,如果irqs在本地被禁用了足够长的时间,当APIC向核心发送一个IRQ时,IRQ被禁用,最终的结果将是系统将全局停止接收这个特定的IRQ,直到irqs最终在接收到该类型的最后一个IRQ的核心上本地重新启用。
2。
关于jiffies更新和irq禁用的不同结果,取决于所选的时钟源。
你可以找出哪一个是通过咨询选择的:
$ cat / sys / devices / system / clocksource / clocksource0 / current_clocksource
如果你有tsc作为时钟源,那么所有的核心在本地都有。 但是,如果你的clocksource是其他的东西,例如:HPET一个外部设备,那么jiffies会因为第一点所描述的原因而被冻结。