分享
 
 
 

FreeBSD 5 内核源代码分析之中断处理

王朝system·作者佚名  2006-11-23
窄屏简体版  字體: |||超大  

FreeBSD 5 内核中断处理的最大特点是将中断处理程序在线程的上下文中运行。

为此,内核为每个注册的中断源(即vector)准备一个内核线程,即中断线程,

其任务就是等待中断的发生,一旦发生,便运行相应的中断处理程序。

FreeBSD 5这样做,有好处也有坏处。好处是可以简化线程和中断的互斥关系,

并使得中断处理可以阻塞。

坏处是每次响应中断都要进行线程调度,可能有两次线程上下文的切换

(从用户线程切到中断线程再切回来)。未来的想法是进行lazy scheduling,

即尽可能借用当前线程的上下文,只有在中断要阻塞时才进行真正的调度。

与中断有关的源代码主要在

sys/kern/kern_intr.c (与体系结构无关的中断代码)

sys/i386/i386/intr_machdep.c (与i386体系结构相关的中断代码)

sys/i386/isa/atpic.c (与8259A相关的.c代码)

sys/i386/isa/atpic_vector.s (与8259A相关的.s代码)

Contents

1,登记IRQ中断源

1.1 数据结构与函数

1.2 8259A的登记过程

2,IRQ中断的处理过程

3, 软件中断swi

3.1 软件中断的登记

3.2 软件中断的调度

-------------------------------

1,登记IRQ中断源

1.1 数据结构与函数

中断向量表有多个vector,0-31为CPU用,32~32+15对应IRQ0~IRQ15

一个vector对应一个source,数据类型是struct intsrc

代码:

/*

* An interrupt source. The upper-layer code uses the PIC methods to

* control a given source. The lower-layer PIC drivers can store additional

* private data in a given interrupt source such as an interrupt pin number

* or an I/O APIC pointer.

*/

struct intsrc {

struct pic *is_pic;

struct ithd *is_ithread;

u_long *is_count;

u_long *is_straycount;

u_int is_index;

};

其实在vector后面的是中断控制器,如8259A,I/O APIC等,

事实上,对中断源的控制实际上就是对中断控制器的操作,

因此,在struct intsrc中有成员struct pic *is_pic,

即中断控制器的操作函数表,通过这个表,可以为不同的中断控制器

定义不同的操作,达到demultiplex的作用。这里pic是

programmable interrupt controller的意思。

代码:

/*

* Methods that a PIC provides to mask/unmask a given interrupt source,

* "turn on" the interrupt on the CPU side by setting up an IDT entry, and

* return the vector associated with this source.

*/

struct pic {

void (*pic_enable_source)(struct intsrc *);

void (*pic_disable_source)(struct intsrc *);

void (*pic_eoi_source)(struct intsrc *);

void (*pic_enable_intr)(struct intsrc *);

int (*pic_vector)(struct intsrc *);

int (*pic_source_pending)(struct intsrc *);

void (*pic_suspend)(struct intsrc *);

void (*pic_resume)(struct intsrc *);

};

系统中所有的中断源组成一个数组,由于当采用I/O APIC作为中断控制器时,

可以有191个中断号(IRQ),因此该数组大小定义为191。

代码:

static struct intsrc *interrupt_sources[NUM_IO_INTS];

/* With I/O APIC's we can have up to 191 interrupts. */

#define NUM_IO_INTS 191

所谓登记中断源,就是将实际的中断控制器的对应struct intsrc数据结构

添加到该数组中去。同时,系统为每个登记的中断源创建一个中断线程,

中断处理程序就在该线程的上下文中运行,该线程的入口函数为ithread_loop(),

struct intsrc结构成员is_ithread指向描述中断线程的数据结构struct ithd,

而struct ithd结构成员it_td指向真正的线程结构struct thread,从而将中断

与系统的调度单元线程联系起来。

代码:

/*

* Describe an interrupt thread. There is one of these per interrupt vector.

* Note that this actually describes an interrupt source. There may or may

* 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[MAXCOMLEN + 1];

};

/*

* 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有一个成员it_handlers,

指向一个链表,这个链表是中断处理程序的链表。为什么多个中断处理程序会连接在一个链表

中呢?这是因为多个设备可以共享同一个IRQ号,即同一个vertor可以登记多个设备的

中断处理函数。当中断来临时,系统分别调用各个设备的中断处理函数,由他们自己判断是否

是自己的中断。

intr_add_handler()函数就是用来登记中断处理程序的,它从系统中分配一个描述中断处理程序

的数据结构struct intrhand,并将传入的参数,即中断处理函数driver_intr_t handler

保存在结构struct intrhand的成员时ih_handler中。中断发生时真正处理中断事务的就是该函数。

代码:

/*

* 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. */

int ih_flags;

const char *ih_name; /* Name of handler. */

struct ithd *ih_ithread; /* Ithread we are connected to. */

int ih_need; /* Needs service. */

TAILQ_ENTRY(intrhand) ih_next; /* Next handler for this vector. */

u_char ih_pri; /* Priority of this handler. */

};

/* Interrupt handle flags kept in ih_flags */

#define IH_FAST 0x00000001 /* Fast interrupt. */

#define IH_EXCLUSIVE 0x00000002 /* Exclusive interrupt. */

#define IH_ENTROPY 0x00000004 /* Device is a good entropy source. */

#define IH_DEAD 0x00000008 /* Handler should be removed. */

#define IH_MPSAFE 0x80000000 /* Handler does not need Giant. */

这里有几个flag值值得一提。

IH_FAST指示该中断是快速中断,系统将尽快执行该处理函数,

并不将它调度到中断线程的上下文中运行,也就是说这种函数的运行是在中断环境下运行,

没有线程的上下文,是为历史遗留的还未迁移到新中断模式下的驱动程序提供的。

IH_EXCLUSIVE指示该中断是独占IRQ的,即不能和其他设备共享IRQ

IH_MPSAFE表明该中断处理函数是SMP安全的。

代码:

int

intr_add_handler(const char *name, int vector, driver_intr_t handler,

void *arg, enum intr_type flags, void **cookiep)

{

struct intsrc *isrc;

int error;

isrc = intr_lookup_source(vector);

if (isrc == NULL)

return (EINVAL);

error = ithread_add_handler(isrc->is_ithread, name, handler, arg,

ithread_priority(flags), flags, cookiep);

if (error == 0) {

intrcnt_updatename(isrc);

isrc->is_pic->pic_enable_intr(isrc);

isrc->is_pic->pic_enable_source(isrc);

}

return (error);

}

int

ithread_add_handler(struct ithd* ithread, const char *name,

driver_intr_t handler, void *arg, u_char pri, enum intr_type flags,

void **cookiep)

{

struct intrhand *ih, *temp_ih;

if (ithread == NULL || name == NULL || handler == NULL)

return (E

[1] [2] [3] [4] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有