#include #include #include "DiskSimulate.h" DiskArm::DiskArm(Disk *disk, int index) { this->disk = disk; this->index = index; this->cur_pos = disk->getNumCylinders() / 2; this->time_elapse = 0.0; } void DiskArm::moveTo(int cylinder) { int num_cyls = disk->getNumCylinders(); if(cylinder < 0 || cylinder >= num_cyls) { cerr << "Disk::serveRequest: Bad cylinder " << cylinder << endl; return; } int movement = cylinder - cur_pos; if(movement < 0) movement = -movement; double elapse = ARM_START + (double) ARM_SCAN * movement / num_cyls; time_elapse += elapse; cur_pos = cylinder; } Disk::Disk(int num_arms, int num_cyls) { this->num_cyls = num_cyls; this->num_arms = num_arms; this->arms = new DiskArm*[num_arms]; for(int i = 0; i < num_arms; i++) { arms[i] = new DiskArm(this, i); } } DiskArm *Disk::getArm(int which) { if(which < 0 || which >= num_arms) { cerr << "Disk::getArm: Bad arm " << which << endl; return NULL; } return arms[which]; } void DiskArm::reset() { time_elapse = 0.0; cur_pos = disk->getNumCylinders() / 2; } DiskArm *Disk::getReadyArm(double time) { DiskArm *ret = NULL; double ret_t = 0.0; for(int i = 0; i < num_arms; i++) { double t = getArm(i)->getTimeElapsed(); if(ret == NULL || t < ret_t) { ret = arms[i]; ret_t = t; } } return ret; } void Disk::reset() { for(int i = 0; i < getNumArms(); i++) { getArm(i)->reset(); } } Process::Process(int num_cyls) { this->num_reqs = 0; req = new int[NUM_REQS + 1]; for(int i = 0; i < NUM_REQS; i++) { req[i] = random() % num_cyls; } req[NUM_REQS] = -1; } RequestQueue::RequestQueue(int num_proc, int num_cyls) { if(num_proc <= 0 || num_proc >= MAX_PROCS) { cerr << "RequestQueue::RequestQueue: Invalid number of processes " << num_proc << endl; num_proc = 1; } this->num_proc = num_proc; proc = new Process*[num_proc]; time_begun = new double[num_proc]; for(int i = 0; i < num_proc; i++) { proc[i] = new Process(num_cyls); time_begun[i] = 0.0; } sum_square_wait = 0; num_served = 0; } double RequestQueue::getMeanSquareWait() { return (double) sum_square_wait / num_served; } Process* RequestQueue::getProcess(int which) { if(which < 0 || which >= num_proc) { cerr << "RequestQueue::getRequest: Bad process " << which << endl; return 0; } return proc[which]; } bool RequestQueue::hasRequestsPending() { for(int i = 0; i < getNumProcesses(); i++) { if(!getProcess(i)->isComplete()) { bool found = false; for(int j = 0; j < getNumProcesses(); j++) { if(getProcess(j)->getCurRequest() >= 0) found = true; } if(!found) { cerr << "RequestQueue::hasRequestPending: some are " << "incomplete but none are ready (" << i << ")" << endl; exit(-1); } return true; } } return false; } void RequestQueue::serveRequest(DiskArm *arm, int which) { Disk *disk = arm->getDisk(); if(which < 0 || which >= num_proc) { cerr << "RequestQueue::serveRequest: Bad process " << which << endl; return; } int req = proc[which]->getCurRequest(); if(req < 0) { cerr << "RequestQueue::getRequest: Process " << which << " isn't requesting an access" << endl; return; } arm->moveTo(req); double wait = arm->getTimeElapsed() - time_begun[which]; sum_square_wait += wait * wait; num_served++; time_begun[which] = arm->getTimeElapsed(); proc[which]->nextRequest(); // make sure an arm is ready to go next bool arm_ready = false; for(int i = 0; i < disk->getNumArms(); i++) { if(disk->getArm(i)->getTimeElapsed() <= now) arm_ready = true; } if(!arm_ready) { // no arms were ready; advance time to next ready arm double next = disk->getArm(0)->getTimeElapsed(); for(int i = 1; i < disk->getNumArms(); i++) { double t = disk->getArm(i)->getTimeElapsed(); if(t < next) next = t; } now = next; } while(true) { // Suspend processes which arms are currently reserving; // release processes which arms have already served. bool process_ready = false; for(int i = 0; i < getNumProcesses(); i++) { Process *p = proc[i]; if(!p->isComplete()) { p->setSuspended(time_begun[i] > now); process_ready |= (p->getCurRequest() >= 0); } } if(process_ready) break; // all processes were suspended; advance time to next // ready process. double next = -1.0; for(int i = 0; i < getNumProcesses(); i++) { if(time_begun[i] > now) { if(next < 0.0 || time_begun[i] < next) { next = time_begun[i]; } } } if(next < 0) break; now = next; } }