日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

FreeBSD 5 內(nèi)核源代碼分析之中斷處理( 五 )


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);
}

經(jīng)過簡單的有關(guān)8259A特有的檢查,atpic_handle_intr()就轉(zhuǎn)到intr_execute_handlers()
繼續(xù)處理 。

intr_execute_handlers()是一個重要的函數(shù),它先得到IRQ號,然后判斷是否是快速中斷,
如果是,則直接在當(dāng)前線程的上下文中運行,如果不是,則調(diào)度對應(yīng)的中斷線程來運行 。
這個處理是被critical_enter()/critical_exit()保護起來的,以保證不會嵌套調(diào)度中斷線程 。
代碼:
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);
}

其他的非快速中斷則需要調(diào)度 。這里先應(yīng)答中斷控制器,然后調(diào)度 。
代碼:
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);

推薦閱讀