Next: Real-Time Clock Interrupts
Up: Nachos Machine
Previous: Machine Components
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:
- 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().
- Whenever the MIPS simulator executes one instruction, the clock
advances one tick.
- 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 deadlock.
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: Real-Time Clock Interrupts
Up: Nachos Machine
Previous: Machine Components
Thomas Narten
Mon Feb 3 15:00:27 EST 1997