int if_ecx;
int if_eax;
int :32; /* for compat with trap frame - trapno */
int :32; /* for compat with trap frame - err */
/* below portion defined in 386 hardware */
int if_eip;
int if_cs;
int if_eflags;
/* below only when crossing rings (e.g. user to kernel) */
int if_esp;
int if_ss;
};
void
atpic_handle_intr(struct intrframe iframe)
{
struct intsrc *isrc;
KASSERT((uint)iframe.if_vec < ICU_LEN,
("unknown int %dn", iframe.if_vec));
isrc = https://www.rkxy.com.cn/dnjc/&atintrs[iframe.if_vec].at_intsrc;
/*
* If we don"t have an ithread, see if this is a spurious
* interrupt.
*/
if (isrc->is_ithread == NULL &&
(iframe.if_vec == 7 || iframe.if_vec == 15)) {
int port, isr;
/*
* Read the ISR register to see if IRQ 7/15 is really
* pending. Reset read register back to IRR when done.
*/
port = ((struct atpic *)isrc->is_pic)->at_ioaddr;
mtx_lock_spin(&icu_lock);
outb(port, OCW3_SEL | OCW3_RR | OCW3_RIS);
isr = inb(port);
outb(port, OCW3_SEL | OCW3_RR);
mtx_unlock_spin(&icu_lock);
if ((isr & IRQ7) == 0)
return;
}
intr_execute_handlers(isrc, &iframe);
}
经过简单的有关8259A特有的检查,atpic_handle_intr()就转到intr_execute_handlers()
继续处理 。
intr_execute_handlers()是一个重要的函数,它先得到IRQ号,然后判断是否是快速中断,
如果是,则直接在当前线程的上下文中运行,如果不是,则调度对应的中断线程来运行 。
这个处理是被critical_enter()/critical_exit()保护起来的,以保证不会嵌套调度中断线程 。
代码:
void
intr_execute_handlers(struct intsrc *isrc, struct intrframe *iframe)
{
struct thread *td;
struct ithd *it;
struct intrhand *ih;
int error, vector;
td = curthread;
td->td_intr_nesting_level;
/*
* We count software interrupts when we process them. The
* code here follows previous practice, but there"s an
* argument for counting hardware interrupts when they"re
* processed too.
*/
atomic_add_long(isrc->is_count, 1);
atomic_add_int(&cnt.v_intr, 1);
it = isrc->is_ithread;
if (it == NULL)
ih = NULL;
else
ih = TAILQ_FIRST(&it->it_handlers);
/*
* XXX: We assume that IRQ 0 is only used for the ISA timer
* device (clk).
*/
vector = isrc->is_pic->pic_vector(isrc);
if (vector == 0)
clkintr_pending = 1;
critical_enter();
if (ih != NULL && ih->ih_flags & IH_FAST) {
/*
* Execute fast interrupt handlers directly.
* To support clock handlers, if a handler registers
* with a NULL argument, then we pass it a pointer to
* a trapframe as its argument.
*/
TAILQ_FOREACH(ih, &it->it_handlers, ih_next) {
MPASS(ih->ih_flags & IH_FAST);
CTR3(KTR_INTR, "%s: executing handler %p(%p)",
__func__, ih->ih_handler,
ih->ih_argument == NULL ? iframe :
ih->ih_argument);
if (ih->ih_argument == NULL)
ih->ih_handler(iframe);
else
ih->ih_handler(ih->ih_argument);
}
isrc->is_pic->pic_eoi_source(isrc);
error = 0;
凡是总是有例外,fast中断不在中断线程的上下文中运行,而是直接在用户进程的上下文中运行
代码:
} else {
/*
* For stray and threaded interrupts, we mask and EOI the
* source.
*/
isrc->is_pic->pic_disable_source(isrc);
isrc->is_pic->pic_eoi_source(isrc);
if (ih == NULL)
error = EINVAL;
else
error = ithread_schedule(it, !cold);
}
其他的非快速中断则需要调度 。这里先应答中断控制器,然后调度 。
代码:
critical_exit();
if (error == EINVAL) {
atomic_add_long(isrc->is_straycount, 1);
if (*isrc->is_straycount < MAX_STRAY_LOG)
log(LOG_ERR, "stray irq%dn", vector);
else if (*isrc->is_straycount == MAX_STRAY_LOG)
log(LOG_CRIT,
"too many stray irq %d"s: not logging anymoren",
vector);
推荐阅读
- 1、系统安装 FreeBSD网站平台建设全过程
- 用FREEBSD作开发的一些实现方式
- FreeBSD下的内存文件系统
- FreeBSD中/etc下的文件简介
- FreeBSD下Apache2.0运行模型分析及性能调整
- 试用QEMU,安装个FreeBSD 5.3
- FreeBSD下有关分区和mount的一些问题
- RSYNC ON FreeBSD 5.2 HOWTO V1.0
- 系统核心 自订 FreeBSD Kernel
- 一些FreeBSD相关的安全问题