每个中断处理程序都需要自旋锁吗?

10
在ULK的第5章中,作者如下所述:
“...每个中断处理程序都与自身串行化,也就是说,它不能同时执行多个。因此,访问数据结构不需要同步原语。”
我并不完全理解为什么在具有多个核心的现代CPU上中断处理程序是“串行化”的。 我认为可能存在同一个ISR可以同时在不同的核心上运行的情况,对吗?如果是这种情况,如果您不使用自旋锁来保护数据,则可能会出现竞态条件。
因此,我的问题是,在具有多个CPU的现代系统中,对于每个将读取和编写某些数据的中断处理程序,是否始终需要自旋锁?
5个回答

7

执行中断处理程序时,内核显式禁用中断控制器中的特定中断线,因此一个中断处理程序不能同时执行多次。(其他中断的处理程序可以并发运行。)


我认为,它只禁用执行该处理程序的CPU的中断,而不是其他CPU。这样对吗? - Eugene
1
它在中断控制器上禁用了中断线本身。同一CPU上的其他中断是否被禁用取决于架构特定。 - CL.

4
澄清:根据下面CL的备注-内核确保不会针对相同的中断触发中断处理程序,但是如果您为多个中断注册了相同的中断处理程序,则我认为以下答案是正确的。
您是对的,同一中断处理程序可以在多个核心上并发运行,并且共享数据需要受到保护。然而,自旋锁不是唯一的,也不总是推荐的方法来实现这一点。
还可以使用大量其他同步方法,从每CPU数据,仅使用原子操作访问共享数据,甚至是Read-Copy-Update变体,以保护共享数据。

2
这是错误的;内核明确防止同一中断处理程序在多个核上并发运行。当数据仅从中断处理程序访问时,仅当不同的处理程序共享相同的数据时才需要锁定。ULK是正确的;而LDD也是正确的(“您永远不会看到两个处理器同时处理相同的IRQ。”,第10章)。 - CL.
@CL。我可能解析问题有误,但我认为他在问不同核心上是否有相同的中断处理程序,而不是相同的中断。我理解内核会阻止中断线,但据我所知,如果将相同的中断处理程序注册为处理不同的中断,则没有任何阻止它被多次注册的东西。 - gby

0

在中断处理程序中并不总是需要自旋锁。

请先注意一件事情——当特定设备的中断在中断控制器上发生时,该中断会在中断控制器上以及所有核心上被禁用。因此,同一设备的中断不能同时出现在所有CPU上。因此,在正常情况下,不需要任何自旋锁,因为代码不会重入。

尽管如此,在以下两种情况下,中断处理程序中需要使用自旋锁。

  1. 请注意,当来自设备和IRQ线的中断到达时,该核心会禁用该核心上的所有其他中断,以及其他核心上该设备的中断。其他设备的中断可以出现在其他核心上。

因此,在同一中断处理程序为不同设备注册的情况下,可能存在这样的情况。

例如:

request_irq(A,func,..);

reqest_irq(B,func,..);

对于设备A,调用中断处理程序func。

对于设备B,调用相同的中断处理程序func。

因此,在这种情况下应该使用自旋锁来防止竞争条件。

当同一资源被中断处理程序和运行在进程上下文中的其他代码使用时,会出现问题。例如:有资源A。可能存在这样一种情况,其中一个核心以中断模式运行,中断处理程序正在修改资源A,而另一个核心在进程上下文中运行,并且在其他地方也正在修改相同的资源。因此,为了避免该资源的竞争条件,我们应该使用自旋锁。

0

-1
如果关键数据在中断处理程序和您的进程(可能是内核线程)之间共享,则需要保护数据,因此需要自旋锁。自旋锁的常见内核API是:spin_lock()。
还有这些API的变体,例如spin_lock_irqsave(),可以帮助避免在获取/持有自旋锁时可能遇到的死锁问题。请查看下面的链接以了解该主题的详细信息: http://www.linuxjournal.com/article/5833

-1: 要么解释为什么需要在此处使用spin_lock_irqsave,要么放弃它。它无论如何都不会回答问题。 - Jan Hudec

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接