00001 // interrupt.h 00002 // Data structures to emulate low-level interrupt hardware. 00003 // 00004 // The hardware provides a routine (SetLevel) to enable or disable 00005 // interrupts. 00006 // 00007 // In order to emulate the hardware, we need to keep track of all 00008 // interrupts the hardware devices would cause, and when they 00009 // are supposed to occur. 00010 // 00011 // This module also keeps track of simulated time. Time advances 00012 // only when the following occur: 00013 // interrupts are re-enabled 00014 // a user instruction is executed 00015 // there is nothing in the ready queue 00016 // 00017 // As a result, unlike real hardware, interrupts (and thus time-slice 00018 // context switches) cannot occur anywhere in the code where interrupts 00019 // are enabled, but rather only at those places in the code where 00020 // simulated time advances (so that it becomes time to invoke an 00021 // interrupt in the hardware simulation). 00022 // 00023 // NOTE: this means that incorrectly synchronized code may work 00024 // fine on this hardware simulation (even with randomized time slices), 00025 // but it wouldn't work on real hardware. 00026 // 00027 // DO NOT CHANGE -- part of the machine emulation 00028 // 00029 // Copyright (c) 1992-1996 The Regents of the University of California. 00030 // All rights reserved. See copyright.h for copyright notice and limitation 00031 // of liability and disclaimer of warranty provisions. 00032 00033 #ifndef INTERRUPT_H 00034 #define INTERRUPT_H 00035 00036 #include "copyright.h" 00037 #include "list.h" 00038 #include "callback.h" 00039 00040 // Interrupts can be disabled (IntOff) or enabled (IntOn) 00041 enum IntStatus { IntOff, IntOn }; 00042 00043 // Nachos can be running kernel code (SystemMode), user code (UserMode), 00044 // or there can be no runnable thread, because the ready list 00045 // is empty (IdleMode). 00046 enum MachineStatus {IdleMode, SystemMode, UserMode}; 00047 00048 // IntType records which hardware device generated an interrupt. 00049 // In Nachos, we support a hardware timer device, a disk, a console 00050 // display and keyboard, and a network. 00051 enum IntType { TimerInt, DiskInt, ConsoleWriteInt, ConsoleReadInt, 00052 NetworkSendInt, NetworkRecvInt}; 00053 00054 // The following class defines an interrupt that is scheduled 00055 // to occur in the future. The internal data structures are 00056 // left public to make it simpler to manipulate. 00057 00058 class PendingInterrupt { 00059 public: 00060 PendingInterrupt(CallBackObj *callOnInt, int time, IntType kind); 00061 // initialize an interrupt that will 00062 // occur in the future 00063 00064 CallBackObj *callOnInterrupt;// The object (in the hardware device 00065 // emulator) to call when the interrupt occurs 00066 00067 int when; // When the interrupt is supposed to fire 00068 IntType type; // for debugging 00069 }; 00070 00071 // The following class defines the data structures for the simulation 00072 // of hardware interrupts. We record whether interrupts are enabled 00073 // or disabled, and any hardware interrupts that are scheduled to occur 00074 // in the future. 00075 00076 class Interrupt { 00077 public: 00078 Interrupt(); // initialize the interrupt simulation 00079 ~Interrupt(); // de-allocate data structures 00080 00081 IntStatus SetLevel(IntStatus level); 00082 // Disable or enable interrupts 00083 // and return previous setting. 00084 00085 void Enable() { (void) SetLevel(IntOn); } 00086 // Enable interrupts. 00087 IntStatus getLevel() {return level;} 00088 // Return whether interrupts 00089 // are enabled or disabled 00090 00091 void Idle(); // The ready queue is empty, roll 00092 // simulated time forward until the 00093 // next interrupt 00094 00095 void Halt(); // quit and print out stats 00096 00097 void YieldOnReturn(); // cause a context switch on return 00098 // from an interrupt handler 00099 00100 MachineStatus getStatus() { return status; } 00101 void setStatus(MachineStatus st) { status = st; } 00102 // idle, kernel, user 00103 00104 void DumpState(); // Print interrupt state 00105 00106 00107 // NOTE: the following are internal to the hardware simulation code. 00108 // DO NOT call these directly. I should make them "private", 00109 // but they need to be public since they are called by the 00110 // hardware device simulators. 00111 00112 void Schedule(CallBackObj *callTo, int when, IntType type); 00113 // Schedule an interrupt to occur 00114 // at time "when". This is called 00115 // by the hardware device simulators. 00116 00117 void OneTick(); // Advance simulated time 00118 00119 private: 00120 IntStatus level; // are interrupts enabled or disabled? 00121 SortedList<PendingInterrupt *> *pending; 00122 // the list of interrupts scheduled 00123 // to occur in the future 00124 bool inHandler; // TRUE if we are running an interrupt handler 00125 bool yieldOnReturn; // TRUE if we are to context switch 00126 // on return from the interrupt handler 00127 MachineStatus status; // idle, kernel mode, user mode 00128 00129 // these functions are internal to the interrupt simulation code 00130 00131 bool CheckIfDue(bool advanceClock); 00132 // Check if any interrupts are supposed 00133 // to occur now, and if so, do them 00134 00135 void ChangeLevel(IntStatus old, // SetLevel, without advancing the 00136 IntStatus now); // simulated time 00137 }; 00138 00139 #endif // INTERRRUPT_H