当系统收到中断后,会通过中断向量表跳转到中断处理函数中。
例如,时钟中断触发时,会执行到el1_irq,进而执行irq_handler。当从irq_handler返回后,中断处理函数就完成了,此时产生一个抢占点,首先ldr w24, [tsk, #TSK_TI_PREEMPT]读取当前进程struct task_struct中的premmpt_count值,如果为0表示可以抢占调度,不为0的话,说明已经被抢占了,不能再次抢占,跳到1中;然后继续判断当前进程是否已经设置了TIF_NEED_RESCHED标志位(时钟中断的处理函数会根据需要设置进程的此标志位),如果没有设置,不能被抢占调度,跳到1中,否则跳到el1_preempt,进行抢占调度。
#ifdef CONFIG_PREEMPT ldr w24, [tsk, #TSK_TI_PREEMPT] // get preempt count cbnz w24, 1f // preempt count != 0 ldr x0, [tsk, #TSK_TI_FLAGS] // get flags tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? bl el1_preempt 1: #endif #ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_on #endif kernel_exit 1 ENDPROC(el1_irq) #ifdef CONFIG_PREEMPT el1_preempt: mov x24, lr 1: bl preempt_schedule_irq // irq en/disable is done inside ldr x0, [tsk, #TSK_TI_FLAGS] // get new tasks TI_FLAGS tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling? ret x24 #endif