CMSC 412 |
NOTE 2 |
Feb 27, 1999 |
The OS has the following interrupt handlers:
macro UpdateRunQPCB() { /* Called within an OS interupt/trap/syscall handler. Assumes runQ contains PCB of the process last running, cpu.sp points to stack top of runQ.pcb. Stack top has the values of ps and pc just before the interrupt. This pc value points to the next user instruction to execute: - if here by interrupt, then the next instruction after the interrupted instruction, - if here by trap, then the next instruction after the trapped instruction, - if here by syscall, then the next instruction after the syscall instruction, Interrupts disabled. */ runQ.PCB.gpr := cpu.gpr ; runQ.PCB.hi := cpu.ps.hi ; runQ.PCB.lo := cpu.ps.lo ; runQ.PCB.pc/ps := pc/ps values on top of cpu.sp stack ; runQ.PCB.sp := cpu.sp appropriately modified to equal value just prior to interrput ; cpu.sp := top of OS stack // "optional" Update runQ.PCB accounting info ; // No Return_from_function because this is a macro // Why is this a macro and not a function } function Scheduler() { // Called within an OS interrupt handler. // Assumes runQ is empty, interrupts disabled, ... while readyQ is empty do { // busy wait with interrupts enabled cpu.ps.intrptEnabled := ON ; cpu.ps.intrptEnabled := OFF ; }; // readyQ not empty choose a pcb in readyQ ; // based on scheduling discipline move the pcb to runQ ; // dispatch cpu.gpr := runQ.PCB.gpr ; cpu.sp := runQ.PCB.sp ; cpu.hi := runQ.PCB.hi ; cpu.lo := runQ.PCB.lo ; push runQ.PCB.pc/ps on cpu.sp stack ; Return_from_Interrupt ; // pops pc and ps atomically } interruptHandler Syscall( PROC_TERM ) { remove runQ.pcb ; Scheduler() ; } interruptHandler Syscall( IO, params ) { UpdateRunQPCB() ; RunQ.PCB.ioParams := params ; if ioWaitQ is empty // io device not busy then ioDevice.controlReg := params ; // start io move RunQ.PCB to ioWaitQ.PCB ; /* ioWaitQ has one or more PCBs. io device is handling the io request of the PCB at the head of ioWaitQ. */ Scheduler() ; } interruptHandler Trap( INVALID_OP ) { remove runQ.pcb ; Scheduler() ; } interruptHandler HwIntrpt( TIMER ) { /* control here after timer interrupt. Interrupts are disabled, the top of the stack pointed to by cpu.sp has the value of cpu.pc/ps just prior to the interrupt. The interrupted process is a pcb process (WHY?) and its pcb is in runQ */ UpdateRunQPCB() ; move runQ.pcb to readyQ ; Scheduler() ; // no need for Return_from_Interrupt because control never comes here } interruptHandler HwIntrpt( IO ) { /* control here after io device interrupts. The interrupted process is a pcb process and its pcb is in runQ. ioWaitQ is not empty, and the interrupt signals completion of the io request of the pcb process at head of ioWaitQ. */ move ioWaitQ.head.PCB to readyQ ; if ioWaitQ is not empty then // start io of next waiting process ioDevice.controlReg := ioWaitQ.head.pcb.ioParams ; Return_from_Interrupt ; // interrupted process is resumed /* This handler uses the stack of the interrupted process. The interrupt has nothing to do with this process. No context switch is done. */ }