先分别看定义:
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK | NMI_MASK))
#define in_irq() (hardirq_count()) // 判断当前是否在硬件中断上下文
#define in_softirq() (softirq_count()) // 判断当前是否在软件中断上下文
#define in_interrupt() (irq_count()) // 判断当前是否在中断状态(硬中断或软中断、上下半部)
/*Linux源码中的注释
* PREEMPT_MASK: 0x000000ff
* SOFTIRQ_MASK: 0x0000ff00
* HARDIRQ_MASK: 0x03ff0000
* NMI_MASK: 0x04000000
*/
这里其实把preempt_count划分成了四部分:抢占计数器、软中断计数、硬件中断计数、NMI计数。
抢占计数器:0-7位
软中断计数器:8-15位
硬中断计数器:16-25位
NMI标识:26位
基于上面的信息,实现了上面Linux内核中判断各个上下文的宏:
in_interrupt 判断中断计数和底半部计数是否大于0
如果只希望判断是否在硬件中断上下文,则可以使用:in_irq()