//Mem.h //Stephen Bassoli //CSE 258 #include #include #include #include #include "Token.h" struct page { int virtualPage; int enteredMem; int lastUsed; int numOfUses; int asscJob; }; struct mapElement { bool r; //residence bit int s; //secondary storage address int pageFrame; //page frame in memory }; struct runningJob { int jobID; int* pages; int currPage; int pagesLeft; }; class Mem { public: page memory[20]; //main memory page secondary[30]; //secondary memory mapElement mappingTable[30];//page mapping table page blankPage; //blank page of memory ofstream outfile; //the output file int stepsPerJob[30]; //keeps track of the steps spent on each job int faultsPerJob[30]; //keeps track of the faults for each job int step; //current step int usedPages; //used pages of main memory int currReadyJob; //next ready job to be sent to ready set int** readyJobs; //ready jobs with a pointer to the job's pages runningJob runningJobs[30]; //running job set int numRunningJobs; //number of running jobs int currRunningJobInArray; //current running job that has the CPU int readyJobsLeft; //number of ready jobs left int numOfPageFaults; //total number of page faults Mem(int** jobPages, ofstream& out); void clockEdge(); bool movePageToMem(int pageNum, int jobID); bool movePageToMem(int pageNum, int at, int jobID); bool accessPage(int pageNum); void pageFault(); void clearPage(int at); int deleteRANDOMpage(); int deleteFIFOpage(); int deleteLRUpage(); int deleteLFUpage(); void clearJob(int jobID); void loadJob(); void runJobsWith(int mode); void printMem(); }; //Constructor that takes in Ready set and the outfile Mem::Mem(int** jobPages, ofstream& out) { for (int i = 0 ; i < 20 ; i++) { memory[i].enteredMem = -1; memory[i].lastUsed = -1; memory[i].numOfUses = -1; memory[i].virtualPage = -1; memory[i].asscJob = -1; } for (i = 0 ; i < 30 ; i++) { runningJobs[i].jobID = -1; runningJobs[i].currPage = -1; runningJobs[i].pagesLeft = -1; secondary[i].enteredMem = -1; secondary[i].lastUsed = -1; secondary[i].numOfUses = -1; secondary[i].virtualPage = i + 1; secondary[i].asscJob = -1; stepsPerJob[i] = 0; faultsPerJob[i] = 0; } for (i = 0 ; i < 30 ; i++) { mappingTable[i].pageFrame = -1; mappingTable[i].r = false; mappingTable[i].s = i + 1; } blankPage.enteredMem = -1; blankPage.lastUsed = -1; blankPage.numOfUses = -1; blankPage.virtualPage = -1; blankPage.asscJob = -1; step = 0; usedPages = 0; currReadyJob = 1; numRunningJobs = 0; readyJobs = jobPages; currRunningJobInArray = -1; outfile = out; readyJobsLeft = jobPages[0][0]; numOfPageFaults = 0; } //Increases step void Mem::clockEdge() { step++; } //Move page to primary memory from secondary memory bool Mem::movePageToMem(int pageNum, int at, int jobID) { if (memory[at].virtualPage != -1) return false; memory[at].virtualPage = pageNum; memory[at].enteredMem = step + 3; memory[at].lastUsed = step; memory[at].numOfUses = 0; memory[at].asscJob = jobID; usedPages++; return true; } //Move page to primary memory from secondary memory (overloaded) bool Mem::movePageToMem(int pageNum, int jobID) { for (int i = 0 ; i < 20 ; i++) { if (movePageToMem(pageNum, i, jobID)) return true; } return false; } //Accesses a page in primary memory bool Mem::accessPage(int pageNum) { bool pageInMem = false; for (int loc = 0 ; loc < 20 ; loc++) { if (memory[loc].virtualPage == pageNum) { pageInMem = true; break; } } if (!pageInMem) return false; memory[loc].lastUsed = step; memory[loc].numOfUses++; return true; } //increases step by 3 to emulate a page fault as specified by proj. desc. void Mem::pageFault() { step++; step++; step++; numOfPageFaults++; } //deletes a random page from memory int Mem::deleteRANDOMpage() { int holder; srand(258); clearPage(holder = rand()%20); return holder; } //deletes the first page from main memory to enter memory int Mem::deleteFIFOpage() { int lowest = 1000000000; int pageNum = -1; for (int i = 0 ; i < 20 ; i++) { if (memory[i].enteredMem < lowest) { lowest = memory[i].enteredMem; pageNum = i; } } clearPage(pageNum); return pageNum; } //deletes the first page from main memory that was used the longest ago int Mem::deleteLRUpage() { int lowest = 1000000000; int pageNum = -1; for (int i = 0 ; i < 20 ; i++) { if (memory[i].lastUsed < lowest) { lowest = memory[i].lastUsed; pageNum = i; } } clearPage(pageNum); return pageNum; } //deletes the first page from main memory that was used least frequently int Mem::deleteLFUpage() { int lowest = 1000000000; int pageNum = -1; for (int i = 0 ; i < 20 ; i++) { if (memory[i].numOfUses < lowest) { lowest = memory[i].numOfUses; pageNum = i; } } clearPage(pageNum); return pageNum; } //Clears a page from memory void Mem::clearPage(int at) { memory[at] = blankPage; usedPages--; } //moves a job from the running set to the completed set void Mem::clearJob(int jobID) { if (numRunningJobs == 0) return; for (int i = 0 ; i < 20 ; i++) { if (memory[i].asscJob == jobID) { usedPages--; memory[i] = blankPage; } } for (i = 0 ; i < numRunningJobs ; i++) { if (runningJobs[i].jobID == jobID) break; } for (int j = i ; j < (numRunningJobs - 1); j++) runningJobs[j] = runningJobs[j+1]; numRunningJobs--; currRunningJobInArray--; if (currRunningJobInArray == -1) currRunningJobInArray = 0; } //moves a job from the ready set to the running set void Mem::loadJob() { if (readyJobsLeft !=0) { runningJobs[numRunningJobs].jobID = currReadyJob; runningJobs[numRunningJobs].pages = readyJobs[currReadyJob]; runningJobs[numRunningJobs].currPage = 1; runningJobs[numRunningJobs].pagesLeft = readyJobs[currReadyJob][0]; currRunningJobInArray = numRunningJobs; numRunningJobs++; currReadyJob++; readyJobsLeft--; } } //run the jobs with the specified replacement strategy /* switch (mode) { case 0: deleteRANDOMpage(); break; case 1: deleteFIFOpage(); break; case 2: deleteLRUpage(); break; case 3: deleteLFUpage(); break; default: deleteRANDOMpage(); break; */ void Mem::runJobsWith(int mode) { int startStep = step; while ((step - startStep) < 10) { printMem(); outfile << "Step: " << step << endl; outfile << "Current job: " << runningJobs[currRunningJobInArray].jobID << " accessing virtual page: "<< runningJobs[currRunningJobInArray].pages[runningJobs[currRunningJobInArray].currPage] << " pages left: " << runningJobs[currRunningJobInArray].pagesLeft < 0)||(numRunningJobs > 0))) return; } stepsPerJob[runningJobs[currRunningJobInArray].jobID] += step - startStep; if (runningJobs[currRunningJobInArray].pagesLeft == 0) { clearJob(runningJobs[currRunningJobInArray].jobID); step += 10; //Another round w/ the CPU to complete job } if (usedPages == 20) { if (currRunningJobInArray == (numRunningJobs - 1)) currRunningJobInArray = 0; else currRunningJobInArray++; } else if (readyJobsLeft == 0) { if (currRunningJobInArray == (numRunningJobs - 1)) currRunningJobInArray = 0; else currRunningJobInArray++; } else loadJob(); if ((readyJobsLeft > 0)||(numRunningJobs > 0)) runJobsWith(mode); } //print to out file void Mem::printMem() { for (int i = 0; i < 20 ; i++) { if (memory[i].virtualPage != -1) outfile << "Page: " << i << " \tVirtualPage: " << memory[i].virtualPage << "\tStepCalled: " << memory[i].enteredMem << " \tJobID: " << memory[i].asscJob << "\tLastUsed: " << memory[i].lastUsed << " \tNumOfUses: " << memory[i].numOfUses <