时钟中断TIMER_BH(bottom_half)实现分析
1.3.100
1. 时钟0号中断安装
setup_x86_irq(0, &irq0);@arch/i386/kernel/time.c
|- set_intr_gate(0x20+irq,interrupt[irq]);//interrupt[0]=IRQ0_interrupt
附:IRQ0_interrupt宏函数定义:BUILD_TIMER_IRQ(FIRST,0,0x01)
#define BUILD_TIMER_IRQ(chip,nr,mask)
asmlinkage void IRQ_NAME(nr);
asmlinkage void FAST_IRQ_NAME(nr);
asmlinkage void BAD_IRQ_NAME(nr);
__asm__(
"
"__ALIGN_STR"
"
SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:
"
SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:
"
SYMBOL_NAME_STR(IRQ) #nr "_interrupt:
"
"pushl $-"#nr"-2
"
SAVE_ALL
ACK_##chip(mask)
"incl "SYMBOL_NAME_STR(intr_count)"
"
"movl %esp,%ebx
"
"pushl %ebx
"
"pushl $" #nr "
"
"call "SYMBOL_NAME_STR(do_IRQ)"
"
"addl $8,%esp
"
"cli
"
UNBLK_##chip(mask)
"decl "SYMBOL_NAME_STR(intr_count)"
"
"jmp ret_from_sys_call
");
2. 时钟中断调用
IRQ0_interrupt->do_IRQ->timer_interrupt->do_timer
->ret_from_sys_call->handle_bottom_half->do_bottom_half@kernel/softirq.c
另1:do_bottom_half会开启中断
asmlinkage void do_bottom_half(void)
{
unsigned long active;
unsigned long mask, left;
void (**bh)(void);
sti();
bh = bh_base;
active = bh_active & bh_mask;
for (mask = 1, left = ~0 ; left & active ; bh++,mask += mask,left += left) {
if (mask & active) {
void (*fn)(void);
bh_active &= ~mask;
fn = *bh;
if (!fn)
goto bad_bh;
fn();
}
}
return;
bad_bh:
printk ("irq.c:bad bottom half entry %08lx
", mask);
}
另2:ret_from_sys_call段如下:
handle_bottom_half:
incl SYMBOL_NAME(intr_count)
call SYMBOL_NAME(do_bottom_half)
decl SYMBOL_NAME(intr_count)
jmp 9f
...
ret_from_sys_call:
cmpl $0,SYMBOL_NAME(intr_count)
jne 2f
9: movl SYMBOL_NAME(bh_mask),%eax
andl SYMBOL_NAME(bh_active),%eax
jne handle_bottom_half
movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are
testl $(VM_MASK),%eax # different then
jne 1f
cmpw $(KERNEL_CS),CS(%esp) # was old code segment supervisor ?
je 2f
1: sti
orl $(IF_MASK),%eax # these just try to make sure
andl $~NT_MASK,%eax # the program doesn't do anything
movl %eax,EFLAGS(%esp) # stupid
cmpl $0,SYMBOL_NAME(need_resched)
jne reschedule
#ifdef __SMP__
GET_PROCESSOR_OFFSET(%eax)
movl SYMBOL_NAME(current_set)(,%eax), %eax
#else
movl SYMBOL_NAME(current_set),%eax
#endif
cmpl SYMBOL_NAME(task),%eax # task[0] cannot have signals
je 2f
movl blocked(%eax),%ecx
movl %ecx,%ebx # save blocked in %ebx for signal handling
notl %ecx
andl signal(%eax),%ecx
jne signal_return
2: RESTORE_ALL