fastcall unsigned int do_IRQ(struct pt_regs *regs){
irq_enter();//increase hardware irq preemptcount
__do_IRQ(irq, regs){
handle_IRQ_event(irq, regs, action){
if (!(action->flags & SA_INTERRUPT)){
local_irq_enable();
}
do {
ret = action->handler(irq, action->dev_id, regs);
} while (action);
local_irq_disable();
}//end handle_IRQ_event
}//end __do_IRQ
irq_exit(){
sub_preempt_count(IRQ_EXIT_OFFSET);//decrease hardware irq preemptcount
do_softirq(){
if (in_interrupt()){// softirq should be serilaized for one cpu
return;
}
local_irq_save(flags);//save flags reg and disable local irq
__do_softirq(){
local_bh_disable();//increase the softirq counter to serilaize the softirq (checked by in_interrupt()).
//this means for one cpu, only one softirq should be execute at one time.
//No other softirq could be executed while there is one softirq in processing on the specified cpu.
//no two softirqs can be executed at the same time. even they are different ones.
local_irq_enable();
do {
if (pending & 1) {
h->action(h);
}
h++;
pending >>= 1;
} while (pending);
local_irq_disable();
pending = local_softirq_pending();
if (pending)
wakeup_softirqd();//handle the left pending softirq in kernel thread (now is in the irq context). this gives running changes to user thread
__local_bh_enable();//decrease the softirq counter
}//end __do_softirq
local_irq_restore(flags);//restore flags reg and local irq
}//end do_softirq
}//end irq_exit
}// end do_IRQ
阅读(712) | 评论(0) | 转发(0) |