嵌入式操作系统
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

4.5.5 中断处理程序结束后的线程调度

在V1.0的实现中,在中断上下文中对线程的调度,是发生在时钟中断结束的时候,而在V1.5的实现中,对线程的调度,则发生在任何中断处理程序结束后。而Hello China的中断处理过程是这样的:

① CPU特定的汇编语言处理部分,主要是保存线程硬件上下文等。

② 汇编语言完成硬件上下文的保存后,调用GeneralIntHandler函数,该函数是C语言实现的,从该函数往后,所有的处理动作,都是由C语言完成(不考虑驱动程序内部采用的汇编语言处理)。

③ GeneralIntHandler再调用system对象提供的DispatchInterrupt函数。

④ DispatchInterrupt函数再调用系统中注册的中断处理程序。

在V1.0的实现中,对线程的调度,是发生在时钟中断处理程序之后,返回DispatchInterrupt函数之前的,因此只会在时钟中断中,对系统中的线程进行调度。在V1.5的实现中,把对线程的调度,放在了DispatchInterrupt函数中,该函数完成特定中断处理程序的调用后,将调用ScheduleFromInt函数,重新对线程进行调度。V1.5的实现如下:

  static VOID DispatchInterrupt(__COMMON_OBJECT* lpThis,
                              LPVOID          lpEsp,
                              UCHAR ucVector)
  {
    __INTERRUPT_OBJECT*   lpIntObject=NULL;
    __SYSTEM*            lpSystem  =NULL;
    if((NULL==lpThis) || (NULL==lpEsp))
        return;
    lpSystem=(__SYSTEM*)lpThis;
    lpIntObject=lpSystem->lpInterruptVector[ucVector];
    //POSITION 1
    lpSystem->ucIntNestLevel+=1;   //Increment nesting level.
    if(NULL==lpIntObject)
    //The current interrupt vector has not handler object.
    {
        DefaultIntHandler(lpEsp,ucVector);
        return;
    }
    while(lpIntObject)
          //Travel the whole interrupt list of this vector.
    {
        if(lpIntObject->InterruptHandler(lpEsp,
          lpIntObject->lpHandlerParam))
          //If  an  interrupt  object  handles  the  interrupt,then
returns.
        {
          break;
        }
        lpIntObject=lpIntObject->lpNextInterruptObject;
    }
    //POSITION 2
    lpSystem->ucIntNestLevel-=1;
    if(0==lpSystem->ucIntNestLevel)  //The most outside interrupt.
    {
        KernelThreadManager.ScheduleFromInt(
            (__COMMON_OBJECT*)&KernelThreadManager,
            lpEsp);  //Re-schedule kernel thread.
    }
    else
    {
        BUG();
    }
    return;
}

其中黑体标注部分,是与Hello China V1.0的实现不同的部分。在中断处理程序结束后,会调用ScheduleFromInt函数,完成一次线程调度。需要注意的是,在V1.5的实现中,对System对象也做了少量的修改,引入了一个ucIntNestLevel的成员变量,用于表示中断的嵌套级别。每当进入中断调度程序的时候,该变量会增加1(代码中POSITION1位置处),每当完成一个中断处理程序的调用(退出中断处理程序)的时候,该变量减1 (对应代码中POSITION 2位置处)。若该变量值大于1,说明发生了嵌套中断(即当前中断处理过程中,又被更高优先级的中断打断)。对于核心线程的调度,只有在最外层中断处理程序结束后,才会引发。这样符合实际情况,因为如果在不是最外层的中断处理程序结束后调度线程,可能会导致外层中断无法得到处理,严重情况下会引起系统崩溃。

虽然引入了ucIntNestLevel变量标识中断嵌套级别,但V1.5版本的Hello China没有针对中断嵌套做特殊的优化,因此暂时可做“不支持嵌套中断”的处理。但实际上,经过测试,在中断嵌套的情况下,Hello China V1.5的表现也是很好的。