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

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


* not be an actual kernel thread attached to a given source.
*/
struct ithd {
struct mtx it_lock;
struct thread *it_td; /* Interrupt process. */
LIST_ENTRY(ithd) it_list; /* All interrupt threads. */
TAILQ_HEAD(, intrhand) it_handlers; /* Interrupt handlers. */
struct ithd *it_interrupted; /* Who we interrupted. */
void (*it_disable)(uintptr_t); /* Enable interrupt source. */
void (*it_enable)(uintptr_t); /* Disable interrupt source. */
void *it_md; /* Hook for MD interrupt code. */
int it_flags; /* Interrupt-specific flags. */
int it_need; /* Needs service. */
uintptr_t it_vector;
char it_name[MAXCOMLEN1];
};

/*
* Register a new interrupt source with the global interrupt system.
* The global interrupts need to be disabled when this function is
* called.
*/
int
intr_register_source(struct intsrc *isrc)
{
int error, vector;

vector = isrc->is_pic->pic_vector(isrc);
if (interrupt_sources[vector] != NULL)
return (EEXIST);
error = ithread_create(&isrc->is_ithread, (uintptr_t)isrc, 0,
(mask_fn)isrc->is_pic->pic_disable_source,
(mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector);
if (error)
return (error);
mtx_lock_spin(&intr_table_lock);
if (interrupt_sources[vector] != NULL) {
mtx_unlock_spin(&intr_table_lock);
ithread_destroy(isrc->is_ithread);
return (EEXIST);
}
intrcnt_register(isrc);
interrupt_sources[vector] = isrc;
mtx_unlock_spin(&intr_table_lock);
return (0);
}

int
ithread_create(struct ithd **ithread, uintptr_t vector, int flags,
void (*disable)(uintptr_t), void (*enable)(uintptr_t), const char *fmt, ...)
{
struct ithd *ithd;
struct thread *td;
struct proc *p;
int error;
va_list ap;

/* The only valid flag during creation is IT_SOFT. */
if ((flags & ~IT_SOFT) != 0)
return (EINVAL);

ithd = malloc(sizeof(struct ithd), M_ITHREAD, M_WAITOK | M_ZERO);
ithd->it_vector = vector;
ithd->it_disable = disable;
ithd->it_enable = enable;
ithd->it_flags = flags;
TAILQ_INIT(&ithd->it_handlers);
mtx_init(&ithd->it_lock, "ithread", NULL, MTX_DEF);

va_start(ap, fmt);
vsnprintf(ithd->it_name, sizeof(ithd->it_name), fmt, ap);
va_end(ap);

error = kthread_create(ithread_loop, ithd, &p, RFSTOPPED | RFHIGHPID,
0, "%s", ithd->it_name);
if (error) {
mtx_destroy(&ithd->it_lock);
free(ithd, M_ITHREAD);
return (error);
}
td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */
mtx_lock_spin(&sched_lock);
td->td_ksegrp->kg_pri_class = PRI_ITHD;
td->td_priority = PRI_MAX_ITHD;
TD_SET_IWAIT(td);
mtx_unlock_spin(&sched_lock);
ithd->it_td = td;
td->td_ithd = ithd;
if (ithread != NULL)
*ithread = ithd;
CTR2(KTR_INTR, "%s: created %s", __func__, ithd->it_name);
return (0);
}

中斷源登記完成后,便可以登記中斷處理程序了 。struct ithd有一個(gè)成員it_handlers,
指向一個(gè)鏈表,這個(gè)鏈表是中斷處理程序的鏈表 。為什么多個(gè)中斷處理程序會(huì)連接在一個(gè)鏈表
中呢?這是因?yàn)槎鄠€(gè)設(shè)備可以共享同一個(gè)IRQ號(hào),即同一個(gè)vertor可以登記多個(gè)設(shè)備的
中斷處理函數(shù) 。當(dāng)中斷來(lái)臨時(shí),系統(tǒng)分別調(diào)用各個(gè)設(shè)備的中斷處理函數(shù),由他們自己判斷是否
是自己的中斷 。

intr_add_handler()函數(shù)就是用來(lái)登記中斷處理程序的,它從系統(tǒng)中分配一個(gè)描述中斷處理程序
的數(shù)據(jù)結(jié)構(gòu)struct intrhand,并將傳入的參數(shù),即中斷處理函數(shù)driver_intr_t handler
保存在結(jié)構(gòu)struct intrhand的成員時(shí)ih_handler中 。中斷發(fā)生時(shí)真正處理中斷事務(wù)的就是該函數(shù) 。
代碼:
/*
* Describe a hardware interrupt handler.
*
* Multiple interrupt handlers for a specific vector can be chained
* together.
*/
struct intrhand {
driver_intr_t *ih_handler; /* Handler function. */
void *ih_argument; /* Argument to pass to handler. */

推薦閱讀