// CPUScheduler.h Dave Reed 2/5/05 /////////////////////////////////////////////////////////////////////////////// #include #include #include #include "CPUScheduler.h" #include "Job.h" using namespace std; CPUScheduler::CPUScheduler(int delay, int slice, int min, int max) : randomizer(max-min+1) // Constructor: initializes counters for time slice, load time, and I/O range { loadDelay = delay; timeSlice = slice; IOmin = min; IOmax = max; sliceTimeRemaining = timeSlice; loadTimeRemaining = loadDelay; currentTime = 0; } int CPUScheduler::getTime() const // Returns: current time in the simulation { return currentTime; } bool CPUScheduler::jobsRemaining() const // Returns: true if there is at least one job in either of the ready or wait queues { return (!readyQueue.empty() || !waitQueue.empty()); } void CPUScheduler::addNewJob(Job newJob) // Assumes: time > 0 // Results: adds newJob to the back of the ready queue (at specified time) { readyQueue.push(newJob); cout << setw(4) << currentTime << ": JOB " << newJob.getID() << " ARRIVES" << endl; } void CPUScheduler::execute() // Assumes: time > 0 // Results: executes one CPU cycle (at specified time) -- this may involve moving jobs // from waiting to ready, loading a new job, performing one instruction // execution, and displaying theresults of the execution { currentTime++; while (!waitQueue.empty() && waitQueue.top().getPriority() <= currentTime) { Job newJob = (Job)waitQueue.top(); // MOVE JOBS FROM WAIT QUEUE waitQueue.pop(); // TO READY QUEUE AS NEEDED readyQueue.push(newJob); } if (!readyQueue.empty()) { // IF READY JOB IS AVAILABLE Job & currentJob = readyQueue.front(); // GET THE NEXT JOB if (loadTimeRemaining > 0) { // IF STILL LOADING, IDLE if (loadTimeRemaining == loadDelay) { cout << setw(4) << currentTime << ": LOAD JOB " << currentJob.getID() << " (delay = " << loadDelay << ")" << endl; } loadTimeRemaining--; } else { // OTHERWISE, PROCESS if (sliceTimeRemaining == timeSlice) { // DISPLAY IF NEW JOB cout << setw(4) << currentTime << ": START JOB " << currentJob.getID() << " (burst = " << currentJob.getRemainingBurst() << ")" << endl; } JobStatus status = currentJob.execute(); // EXECUTE THE JOB AND sliceTimeRemaining--; // REDUCE ITS TIME SLICE if (status == DONE) { // IF JOB FINISHED cout << setw(4) << currentTime+1 << ": FINISH JOB " << currentJob.getID() << endl; readyQueue.pop(); // REMOVE FROM QUEUE AND sliceTimeRemaining = timeSlice; // RESET COUNTS loadTimeRemaining = loadDelay; } else if (status == IO) { // IF REQUESTED I/O int wait = getIOLength(); cout << setw(4) << currentTime+1 << ": I/O JOB " << currentJob.getID() << " (wait = " << wait << ")" << endl; PriorityJob waitJob(currentJob, currentTime+1+wait); readyQueue.pop(); // MOVE TO WAIT QUEUE waitQueue.push(waitJob); // USING RANDOM DELAY, sliceTimeRemaining = timeSlice; // AND RESET COUNTS loadTimeRemaining = loadDelay; } else if (sliceTimeRemaining == 0) { // IF TIME SLICE IS UP cout << setw(4) << currentTime+1 << ": TIMEOUT JOB " << currentJob.getID() << endl; Job readyJob = currentJob; readyQueue.pop(); // MOVE TO BACK OF QUEUE readyQueue.push(readyJob); sliceTimeRemaining = timeSlice; // RESET TIME SLICE if (readyQueue.size() > 1) { // IF OTHER JOBS READY, loadTimeRemaining = loadDelay; // RESET LOAD COUNT } } } } } int CPUScheduler::getIOLength() // Returns: a random integer between IOmin and IOmax, inclusive { return randomizer.roll()+IOmin-1; }