现在的位置: 首页 >> 操作系统 >> FreeBSD >> FreeBSD 5 内核源代码分析之中断处理
添加时间:2005-8-21 来源:网教中国 作者:
FreeBSD 5 内核源代码分析之中断处理

; \
FAKE_MCOUNT(13*4(%esp)) ; /* XXX late to avoid double count */ \
pushl $irq_num; /* pass the IRQ */ \
call atpic_handle_intr ; \
addl $4, %esp ; /* discard the parameter */ \
; \
MEXITCOUNT ; \
jmp doreti

IRQ产生时,系统根据产生中断的IRQ号找到相应的中断向量入口,即此处的IDT_VEC(vec_name),
再这里,构造好函数atpic_handle_intr()的调用栈后,将转到atpic_handle_intr()进行处理。
同系统调用一样,这里的调用栈struct intrframe既是atpic_handle_intr()的参数,也是中断
返回时用以恢复现场的寄存器状态。
代码:

/* Interrupt stack frame */
struct intrframe {
int if_vec;
int if_fs;
int if_es;
int if_ds;
int if_edi;
int if_esi;
int if_ebp;
int :32;
int if_ebx;
int if_edx;
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 %d\n", iframe.if_vec));
isrc = &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_

上一页 [1] [2] [3] [4] [5] [6] [7]  下一页


上一篇:FreeBSD 5内核源代码分析之系统调用过程 下一篇:不直接替换系统调用的kld
大部分文章摘自网上,如有侵犯您的权益请与我们联系,我们会第一时间进行处理,谢谢! [ 打印文章 ] [ 关闭窗口 ]
推荐文章
·FreeBSD handbook中文版 9 配制F
·FreeBSD 升级系统
·Ports & Package
·FreeBSD kernel 编译大法(二)ker
·FreeBSD 上使用Kerberos 5认证
·FreeBSD 5.x 中 gbfs 的修正,及
·FreeBSD 安装Linuxigd
·FreeBSD 使用cvsd创建安全的cvs
·FreeBSD trafcount命令介绍
·FreeBSD入门安装及汉化
相关文章
 
最新文章
·FreeBSD连载(94):基于NAT的负载
·FreeBSD连载(93):反向代理负载
·FreeBSD连载(92):基于DNS的负载
·FreeBSD连载(91):提升静态网页
·FreeBSD连载(90):单服务器性能
·FreeBSD连载(89):CGI和SSI的安
·FreeBSD连载(88):安全连接方式S
·FreeBSD连载(87):基于用户的访
·FreeBSD连载(86):对IP地址和域
·FreeBSD连载(85):配置Apache服(
Google