閱讀554 返回首頁    go 阿裏雲 go 技術社區[雲棲]


中斷子係統6_中斷嵌套處理

//	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)

最後更新:2017-04-03 14:54:20

  上一篇:go directdraw顯示rgb565
  下一篇:go Linux驅動1_DebugFS