146 lines
5.1 KiB
C++
146 lines
5.1 KiB
C++
// interrupt.h
|
|
// Data structures to emulate low-level interrupt hardware.
|
|
//
|
|
// The hardware provides a routine (SetLevel) to enable or disable
|
|
// interrupts.
|
|
//
|
|
// In order to emulate the hardware, we need to keep track of all
|
|
// interrupts the hardware devices would cause, and when they
|
|
// are supposed to occur.
|
|
//
|
|
// This module also keeps track of simulated time. Time advances
|
|
// only when the following occur:
|
|
// interrupts are re-enabled
|
|
// a user instruction is executed
|
|
// there is nothing in the ready queue
|
|
//
|
|
// As a result, unlike real hardware, interrupts (and thus time-slice
|
|
// context switches) cannot occur anywhere in the code where interrupts
|
|
// are enabled, but rather only at those places in the code where
|
|
// simulated time advances (so that it becomes time to invoke an
|
|
// interrupt in the hardware simulation).
|
|
//
|
|
// NOTE: this means that incorrectly synchronized code may work
|
|
// fine on this hardware simulation (even with randomized time slices),
|
|
// but it wouldn't work on real hardware.
|
|
//
|
|
// DO NOT CHANGE -- part of the machine emulation
|
|
//
|
|
// Copyright (c) 1992-1996 The Regents of the University of California.
|
|
// All rights reserved. See copyright.h for copyright notice and limitation
|
|
// of liability and disclaimer of warranty provisions.
|
|
|
|
#ifndef INTERRUPT_H
|
|
#define INTERRUPT_H
|
|
|
|
#include "copyright.h"
|
|
#include "list.h"
|
|
#include "callback.h"
|
|
|
|
// Interrupts can be disabled (IntOff) or enabled (IntOn)
|
|
enum IntStatus { IntOff, IntOn };
|
|
|
|
// Nachos can be running kernel code (SystemMode), user code (UserMode),
|
|
// or there can be no runnable thread, because the ready list
|
|
// is empty (IdleMode).
|
|
enum MachineStatus {IdleMode, SystemMode, UserMode};
|
|
|
|
// IntType records which hardware device generated an interrupt.
|
|
// In Nachos, we support a hardware timer device, a disk, a console
|
|
// display and keyboard, and a network.
|
|
enum IntType { TimerInt, DiskInt, ConsoleWriteInt, ConsoleReadInt,
|
|
NetworkSendInt, NetworkRecvInt};
|
|
|
|
// The following class defines an interrupt that is scheduled
|
|
// to occur in the future. The internal data structures are
|
|
// left public to make it simpler to manipulate.
|
|
|
|
class PendingInterrupt {
|
|
public:
|
|
PendingInterrupt(CallBackObj *callOnInt, int time, IntType kind);
|
|
// initialize an interrupt that will
|
|
// occur in the future
|
|
|
|
CallBackObj *callOnInterrupt;// The object (in the hardware device
|
|
// emulator) to call when the interrupt occurs
|
|
|
|
int when; // When the interrupt is supposed to fire
|
|
IntType type; // for debugging
|
|
};
|
|
|
|
// The following class defines the data structures for the simulation
|
|
// of hardware interrupts. We record whether interrupts are enabled
|
|
// or disabled, and any hardware interrupts that are scheduled to occur
|
|
// in the future.
|
|
|
|
class Interrupt {
|
|
public:
|
|
Interrupt(); // initialize the interrupt simulation
|
|
~Interrupt(); // de-allocate data structures
|
|
|
|
IntStatus SetLevel(IntStatus level);
|
|
// Disable or enable interrupts
|
|
// and return previous setting.
|
|
|
|
void Enable() { (void) SetLevel(IntOn); }
|
|
// Enable interrupts.
|
|
IntStatus getLevel() {return level;}
|
|
// Return whether interrupts
|
|
// are enabled or disabled
|
|
|
|
void Idle(); // The ready queue is empty, roll
|
|
// simulated time forward until the
|
|
// next interrupt
|
|
|
|
void Halt(); // quit and print out stats
|
|
|
|
void PrintInt(int number);
|
|
int CreateFile(char *filename);
|
|
|
|
void YieldOnReturn(); // cause a context switch on return
|
|
// from an interrupt handler
|
|
|
|
MachineStatus getStatus() { return status; }
|
|
void setStatus(MachineStatus st) { status = st; }
|
|
// idle, kernel, user
|
|
|
|
void DumpState(); // Print interrupt state
|
|
|
|
|
|
// NOTE: the following are internal to the hardware simulation code.
|
|
// DO NOT call these directly. I should make them "private",
|
|
// but they need to be public since they are called by the
|
|
// hardware device simulators.
|
|
|
|
void Schedule(CallBackObj *callTo, int when, IntType type);
|
|
// Schedule an interrupt to occur
|
|
// at time "when". This is called
|
|
// by the hardware device simulators.
|
|
|
|
void OneTick(); // Advance simulated time
|
|
|
|
private:
|
|
IntStatus level; // are interrupts enabled or disabled?
|
|
SortedList<PendingInterrupt *> *pending;
|
|
// the list of interrupts scheduled
|
|
// to occur in the future
|
|
//int writeFileNo; //UNIX file emulating the display
|
|
bool inHandler; // TRUE if we are running an interrupt handler
|
|
//bool putBusy; // Is a PrintInt operation in progress
|
|
//If so, you cannoot do another one
|
|
bool yieldOnReturn; // TRUE if we are to context switch
|
|
// on return from the interrupt handler
|
|
MachineStatus status; // idle, kernel mode, user mode
|
|
|
|
// these functions are internal to the interrupt simulation code
|
|
|
|
bool CheckIfDue(bool advanceClock);
|
|
// Check if any interrupts are supposed
|
|
// to occur now, and if so, do them
|
|
|
|
void ChangeLevel(IntStatus old, // SetLevel, without advancing the
|
|
IntStatus now); // simulated time
|
|
};
|
|
|
|
#endif // INTERRRUPT_H
|