当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++进阶与实例

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

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


 

共5页 首页 上一页 1 2 3 4 5 下一页 尾页 跳转到
相关内容
赞助商链接