next up previous contents
Next: Real-Time Clock Interrupts Up: Nachos Machine Previous: Machine Components

Interrupt Management

Nachos simulates interrupts by maintaining an event queue together with a simulated clock. As the clock ticks, the event queue is examined to find events scheduled to take place now. The clock is maintained entirely in software and ticks under the following conditions:

  1. Every time interrupts are restored (and the restored interrupt mask has interrupts enabled), the clock advances one tick. Nachos code frequently disables and restores interrupts for mutual exclusion purposes by making explicit calls to interrupt::SetLevel().
  2. Whenever the MIPS simulator executes one instruction, the clock advances one tick.
  3. Whenever the ready list is empty, the clock advances however many ticks are needed to fast-forward the current time to that of the next scheduled event.

Whenever the clock advances, the event queue is examined and any pending interrupt events are serviced by invoking the procedure associated with the timer event (e.g., the interrupt service routine). All interrupt service routines are run with interrupts disabled, and the interrupt service routine may not re-enable them.

Warning: in interrupt handler may not call any routines that lead to a context switch of the current thread (e.g., scheduler::Run() or SWITCH() ). Doing so may lead to deadlock. This restriction is an artifact of the way interrupts are simulated under Nachos, and should not be taken as an indication of the way things are done on real machines. Specifically, consider the case where multiple events happen to be scheduled at exactly the same time. If the handler for the first event invokes sleep (which calls SWITCH), the others won't be serviced at the right time. In fact, the thread that called sleep may actually be waiting for one of the other events that is supposed to take place now, but is delayed because of the SWITCH. We now have a deadlockgif.

All routines related to interrupt management are provided by the Interrupt object. The main routines of interest include:

void Schedule(VoidFunctionPtr handler, int arg, int when, IntType type)
schedules a future event to take place at time when. When it is time for the scheduled event to take place, Nachos calls the routine handler with the single argument arg.

IntStatus SetLevel(IntStatus level)
Change the interrupt mask to level, returning the previous value. This routine is used to temporarily disable and re-enable interrupts for mutual exclusion purposes. Only two interrupt levels are supported: IntOn and IntOff.

OneTick()
advances the clock one tick and services any pending requests (by calling CheckIfDue). It is called from machine::Run() after each user-level instruction is executed, as well as by SetLevel when the interrupts are restored.

bool CheckIfDue(bool advanceClock)
examines the event queue for events that need servicing now. If it finds any, it services them. It is invoked in such places as OneTick.

Idle()
``advances'' to the clock to the time of the next scheduled event. It is called by the scheduler (actually Sleep()) when there are no more threads on the ready list and we want to ``fast-forward'' the time.


next up previous contents
Next: Real-Time Clock Interrupts Up: Nachos Machine Previous: Machine Components

Thomas Narten
Mon Feb 3 15:00:27 EST 1997