// current_thread_info()->preempt_count bit划分
// /*
// * - bits 0-7 are the preemption count (max preemption depth: 256)
// * - bits 8-15 are the softirq count (max # of softirqs: 256)
// *
// * The hardirq count can be overridden per architecture, the default is:
// *
// * - bits 16-27 are the hardirq count (max # of hardirqs: 4096)
// * - ( bit 28 is the PREEMPT_ACTIVE flag. )
// *
// * PREEMPT_MASK: 0x000000ff
// * SOFTIRQ_MASK: 0x0000ff00
// * HARDIRQ_MASK: 0x0fff0000
// */
// #define PREEMPT_BITS 8
// #define SOFTIRQ_BITS 8
//
// #ifndef HARDIRQ_BITS
// #define HARDIRQ_BITS 12
// #endif
// #define PREEMPT_SHIFT 0
// #define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS) //8
// #define HARDIRQ_SHIFT (SOFTIRQ_SHIFT + SOFTIRQ_BITS) //16
// #define __IRQ_MASK(x) ((1UL << (x))-1)
// #define PREEMPT_MASK (__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT) //0x000000ff
// #define HARDIRQ_MASK (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT) //0x0000ff00
// #define SOFTIRQ_MASK (__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) //0x0fff0000
//
// #define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT) //1<<0
// #define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT) //1<<8
// #define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT) //1<<16
// #define preempt_count() (current_thread_info()->preempt_count)
// #define hardirq_count() (preempt_count() & HARDIRQ_MASK)
// #define softirq_count() (preempt_count() & SOFTIRQ_MASK)
// #define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
// #define in_irq() (hardirq_count())
// #define in_softirq() (softirq_count())
// #define in_interrupt() (irq_count())
// #define add_preempt_count(val) do { preempt_count() += (val); } while (0)
// #define sub_preempt_count(val) do { preempt_count() -= (val); } while (0)
// 中断进入
// 调用路径:do_IRQ->irq_enter
// 函数主要任务:
// 1.递增hardirq嵌套计数
1.1 void irq_enter(void)
{
do {
//递增hardirq计数
add_preempt_count(HARDIRQ_OFFSET);
} while (0);
}
// 中断退出
// 调用路径:do_IRQ->irq_exit
// 函数主要任务:
// 1.递减hardirq计数
// 2.如果此中断为嵌套路径上最后一个(#(hardirq+softirq)=0),并且此刻有软中断待处理
// 2.1 执行软中断处理函数
// 3.递减抢占计数
// 注:
// 通过sub_preempt_count(IRQ_EXIT_OFFSET)、preempt_enable_no_resched()的配合,实现
// 检查是否有待处理软中断,以及执行
1.2 void irq_exit(void)
{
// 中断退出路径上对内核抢占的考虑
// 当支持内核抢占时,CONFIG_PREEMPT=1,此时IRQ_EXIT_OFFSET=(1<<16-1)
// preempt_count -= IRQ_EXIT_OFFSET => preempt_count -= (1<<16) + 1
// 等价于:
// 1.递减hardirq计数
// 2.preempt+1,禁止内核抢占
sub_preempt_count(IRQ_EXIT_OFFSET);
//#(softirq+hardirq)=0 && 有待处理的软中断
if (!in_interrupt() && local_softirq_pending())
{
//执行软中断处理函数
invoke_softirq();
}
//preempt-1,开启内核抢占
preempt_enable_no_resched();
}
1.3
#ifdef CONFIG_PREEMPT
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else
# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
#endif
#define preempt_enable_no_resched() \
do { \
barrier(); \
sub_preempt_count(1); \
} while (0)
中断子系统6_中断嵌套处理
最新推荐文章于 2024-06-24 22:43:46 发布