it_flags td->td_ithd = NULL; mtx_destroy( mtx_lock( free(ithd, M_ITHREAD);。FreeBSD 5 內(nèi)核源代碼分析之中斷處理( 七 )。" />

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

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


* list of handlers, giving each one a go at it.
*/
for (;;) {
/*
* If we are an orphaned thread, then just die.
*/
if (ithd->it_flags & IT_DEAD) {
CTR3(KTR_INTR, "%s: pid %d: (%s) exiting", __func__,
p->p_pid, p->p_comm);
td->td_ithd = NULL;
mtx_destroy(&ithd->it_lock);
mtx_lock(&Giant);
free(ithd, M_ITHREAD);
kthread_exit(0);
}

如果已經(jīng)刪除當(dāng)前IRQ的中斷處理程序,則需要退出中斷線程 。
代碼:
CTR4(KTR_INTR, "%s: pid %d: (%s) need=%d", __func__,
p->p_pid, p->p_comm, ithd->it_need);
while (ithd->it_need) {
/*
* Service interrupts. If another interrupt
* arrives while we are running, they will set
* it_need to denote that we should make
* another pass.
*/
atomic_store_rel_int(&ithd->it_need, 0);

清除it_need標(biāo)志,當(dāng)清除后又有中斷發(fā)生時(shí),it_need將變成1,從而循環(huán)繼續(xù) 。
代碼:
restart:
TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) {
if (ithd->it_flags & IT_SOFT && !ih->ih_need)
continue;
atomic_store_rel_int(&ih->ih_need, 0);
CTR6(KTR_INTR,
"%s: pid %d ih=%p: %p(%p) flg=%x", __func__,
p->p_pid, (void *)ih,
(void *)ih->ih_handler, ih->ih_argument,
ih->ih_flags);

if ((ih->ih_flags & IH_DEAD) != 0) {
mtx_lock(&ithd->it_lock);
TAILQ_REMOVE(&ithd->it_handlers, ih,
ih_next);
wakeup(ih);
mtx_unlock(&ithd->it_lock);
goto restart;
}
if ((ih->ih_flags & IH_MPSAFE) == 0)
mtx_lock(&Giant);
ih->ih_handler(ih->ih_argument);

調(diào)用設(shè)備驅(qū)動(dòng)的中斷服務(wù)函數(shù) 。所有注冊(cè)到該IRQ的函數(shù)都將被調(diào)用,各個(gè)設(shè)備的函數(shù)將檢查
自己設(shè)備的狀態(tài)以確定是否是自己的設(shè)備產(chǎn)生的中斷 。
代碼:
if ((ih->ih_flags & IH_MPSAFE) == 0)
mtx_unlock(&Giant);
}
}

/*
* Processed all our interrupts. Now get the sched
* lock. This may take a while and it_need may get
* set again, so we have to check it again.
*/
WITNESS_WARN(WARN_PANIC, NULL, "suspending ithread");
mtx_assert(&Giant, MA_NOTOWNED);
mtx_lock_spin(&sched_lock);
if (!ithd->it_need) {
/*
* Should we call this earlier in the loop above?
*/
if (ithd->it_enable != NULL)
ithd->it_enable(ithd->it_vector);
TD_SET_IWAIT(td); /* we"re idle */
p->p_stats->p_ru.ru_nvcsw;
CTR2(KTR_INTR, "%s: pid %d: done", __func__, p->p_pid);
mi_switch();
CTR2(KTR_INTR, "%s: pid %d: resumed", __func__, p->p_pid);
}

如果此時(shí)it_need==1,則說明新來了中斷,繼續(xù)for循環(huán)為該中斷服務(wù),
否則掛起調(diào)度 。
代碼:
mtx_unlock_spin(&sched_lock);
}
}

3,軟件中斷swi

我們將舉例說明軟件中斷swi 。

3.1登記

系統(tǒng)啟動(dòng)時(shí),調(diào)用start_softintr()登記兩個(gè)重要的軟件中斷,
軟時(shí)鐘中斷和VM軟中斷 。
當(dāng)情況需要時(shí),內(nèi)核將調(diào)用swi_sched()來調(diào)度軟件中斷的運(yùn)行 。
代碼:
/*
* Start standard software interrupt threads
*/
static void
start_softintr(void *dummy)
{
struct proc *p;

if (swi_add(&clk_ithd, "clock", softclock, NULL, SWI_CLOCK,
INTR_MPSAFE, &softclock_ih) ||
swi_add(NULL, "vm", swi_vm, NULL, SWI_VM, INTR_MPSAFE, &vm_ih))
panic("died while creating standard software ithreads");

p = clk_ithd->it_td->td_proc;
PROC_LOCK(p);
p->p_flag |= P_NOLOAD;
PROC_UNLOCK(p);
}

int
swi_add(struct ithd **ithdp, const char *name, driver_intr_t handler,
void *arg, int pri, enum intr_type flags, void **cookiep)
{
struct ithd *ithd;
int error;

if (flags & (INTR_FAST | INTR_ENTROPY))
return (EINVAL);

ithd = (ithdp != NULL) ? *ithdp : NULL;

if (ithd != NULL) {
if ((ithd->it_flags & IT_SOFT) == 0)
return(EINVAL);
} else {
error = ithread_create(&ithd, pri, IT_SOFT, NULL, NULL,
"swi%d:", pri);
if (error)
return (error);

if (ithdp != NULL)
*ithdp = ithd;

推薦閱讀