//run the main loop void run(void){ if(v) printf("CURRENT LINE NUME: %d\n", program.runNumber); pageRequested = grabPTE(line.currentAddress); if(pageRequested != -1){ //check if it was in the TLB int TLBCheck = checkTLB(pageRequested); if(!TLBCheck){ //check if it was in the page table int pageTableCheck = checkMainMemory(pageRequested); if(pageTableCheck == -1){ numPageFaults = markWSPage(&processWorkingSets[line.processId], 1); if(v){ puts("PAGE FAULT"); printf("Addding %d ns for a disk hit\n", DISKtime); } pageFault(pageRequested); redo = 1; } else {//checkPageTable if(!redo) numPageFaults = markWSPage(&processWorkingSets[line.processId], 0); if(v){ puts("FOUND IT IN THE PAGE TABLE"); printf("Adding %d ns for a memory hit\n", MMtime); } redo = 0; } } else {//checkTLB numPageFaults = markWSPage(&processWorkingSets[line.processId], 0); if(v){ puts("FOUND IT IN THE CACHE"); printf("Adding %d ns for a cache hit\n", TLBtime); } } } else printf("ERROR: SEG FAULT\n"); if(program.runNumber > WSW){ if ( numPageFaults < minPageFault ) { // remove allocated pages from the working set for that process processWorkingSets[line.processId].availWorkingSet--; int idx = evictPage(); struct frame *thisFrame = &mainMemory[idx]; thisFrame->vAddress = -1; thisFrame->dirtyBit = 0; thisFrame->referenceBit = 0; thisFrame->processId = -1; } if ( numPageFaults > maxPageFault ) { // add free pages to the working set for that process processWorkingSets[line.processId].availWorkingSet++; } } if (!v) progressBar(); }//run
/* * This function is the controller function which maps virtual addresses to physical frames. */ static L4_Word_t mapAddress(L4_ThreadId_t tid, L4_Fpage_t fpage, int swapIndex) { // allocate a new frame int evicted_not_dirty = 0; L4_Word_t physAddress = frame_alloc(); int i = 0; //int head = 0, oldHead = 0; if(physAddress == 0) { int evicted = evictPage(); //If page replacement aborted if all pages in page table are currently being updated, abort if(evicted == -1) { return -1; } if(page_table[evicted].dirty == 1) { //We need to write it to swap writeToSwap(evicted,swapIndex,tid,fpage); } else { evicted_not_dirty = 1; } i = evicted; } else { i = (physAddress - new_low)/PAGESIZE; } if(physAddress != 0 || evicted_not_dirty) { //We have a frame avialable to us or a swapout is not necessary if(swapIndex != -1) { //We need to read from the swap and overwrite the physical frame with it //We need to read from the swap and signal to it that there was no swapout readFromSwap(swapIndex,i,0,tid,fpage); } else { //We do not have to read from swap, we just overwrite the frame //Page was not swapped out neither swapped in page_table[i].tid = tid; page_table[i].pageNo = fpage; page_table[i].being_updated = 0; page_table[i].referenced = 1; page_table[i].dirty = 0; send = 1; L4_Set_Rights(&fpage,L4_Readable); L4_PhysDesc_t phys = L4_PhysDesc(new_low + i * PAGESIZE, L4_DefaultMemory); //update the size of the process table update_process_table_size(tid,1); L4_MapFpage(tid, fpage,phys); } } return physAddress; }
//run the aging simulation void simulateAging(bit32 numFrames, const char *fileName, bit32 refresh) { struct agingFrame *frames; //memory frames struct memRef *memList, *curr; //pointer to the current memory reference bit32 *pageTable; //page table bit32 numRefs = 0, numFaults = 0, numWrites = 0; //stat counters bit32 i, pageNo; //current page number and loop control bit32 usedFrames = 0; //used frames - for compulsory misses //set up page table and ensure all bits are 0 pageTable = (bit32 *) malloc(NUM_PAGES * sizeof(bit32)); memset(pageTable, 0, sizeof(bit32) * NUM_PAGES); //set up the memory frames frames = (struct agingFrame *) malloc(numFrames * sizeof(struct agingFrame)); for(i = 0; i < numFrames; i++) { frames[i].pageNo = ZERO; frames[i].age = 0; } //read the file in and store the references and future uses of the references readFile(&memList, fileName); curr = memList; while(curr != NULL) { //if we have hit the end of the refresh period, shift the ref bit in to the age of each frame //also unreference each frame if(numRefs % refresh == 0) { for(i = 0; i < numFrames; i++) { frames[i].age = frames[i].age >> 1; if(isRef(pageTable, frames[i].pageNo)) { frames[i].age = frames[i].age | AGING_REF; } pageTable[frames[i].pageNo] = pageTable[frames[i].pageNo] & CLEAR_REF; } } pageNo = getPageNumber(curr->reference); if(isValid(pageTable, pageNo)) { //page already already valid/in a frame - hit pageHitSetBits(pageTable, pageNo, curr->mode); //set appropriate bits printf("%i\thit\n", numRefs + 1); } else { //page is not in frame yet - miss numFaults++; //compulsory miss - will only happen numFrames times if(usedFrames < numFrames) { frames[usedFrames].pageNo = pageNo; //store the page number in the frame //update the page table entry placePageInFrame(pageTable, pageNo, usedFrames, curr->mode); //map current page to frame usedFrames++; printf("%i\tpage fault - no eviction\n", numRefs + 1); } else { //capacity miss - frames are full and page is not in a frame - will need to evict bit32 oldestFrame = 0; unsigned short int min = NINE_BITS; for(i = 0; i < numFrames; i++) { //find the oldest frame unsigned short int age = frames[i].age; if(isRef(pageTable, frames[i].pageNo)) { //if page is referenced, shift on the 9th bit age = age | AGING_REF; } if(age < min) { oldestFrame = i; min = age; } } //ends for //evict the oldest frame if(isDirty(pageTable, frames[oldestFrame].pageNo)) { numWrites++; printf("%i\tpage fault - evict dirty\n", numRefs + 1); } else { printf("%i\tpage fault - evict clean\n", numRefs + 1); } evictPage(pageTable, frames[oldestFrame].pageNo); frames[oldestFrame].pageNo = pageNo; //store the page number in the frame //update the page table entry placePageInFrame(pageTable, pageNo, oldestFrame, curr->mode); //map current page to frame } } //increment number of references and move to next reference numRefs++; curr = curr->next; } //print stats printf("\nAging\n"); printf("Number of frames:\t%i\n", numFrames); printf("Total memory accesses:\t%i\n", numRefs); printf("Total page faults:\t%i\n", numFaults); printf("Total writes to disk:\t%i\n\n", numWrites); //clean up memory free(frames); }
//run the NRU algorithm simulation void simulateNRU(bit32 numFrames, const char *fileName, bit32 refresh) { bit32 *frames; //list of frames bit32 *pageTable; //page table bit32 numFaults = 0, numWrites = 0, numRefs = 0; //stat counters bit32 usedFrames = 0, pageNo, i; //number of frames used and the page number, loop counter struct memRef *memList, *curr; //pointer to current memory reference //set up page table and ensure all bits are 0 pageTable = (bit32 *) malloc(NUM_PAGES * sizeof(bit32)); memset(pageTable, 0, sizeof(bit32) * NUM_PAGES); //set up the memory frames frames = (bit32 *) malloc(numFrames * sizeof(bit32)); //seed the random number generator srand(time(NULL)); //read the file in and store the references and future uses of the references readFile(&memList, fileName); curr = memList; while(curr != NULL) { //if we've hit the refresh mark, mark all pages unreferenced if((numRefs % refresh) == 0) { for(i = 0; i < usedFrames; i++) { pageTable[frames[i]] = pageTable[frames[i]] & CLEAR_REF; } } pageNo = getPageNumber(curr->reference); if(isValid(pageTable, pageNo)) { //page already already valid/in a frame - hit pageHitSetBits(pageTable, pageNo, curr->mode); //set appropriate bits printf("%i\thit\n", numRefs + 1); } else { //page is not in a frame yet - miss numFaults++; //compulsory miss - will only happen numFrames times if(usedFrames < numFrames) { frames[usedFrames] = pageNo; //store the page number in the frame placePageInFrame(pageTable, pageNo, usedFrames, curr->mode); //map current page to frame usedFrames++; printf("%i\tpage fault - no eviction\n", numRefs + 1); } else { //capacity miss - frames are full and page is not in a frame - will need to evict bit32 frameToEvict = -1; bit32 *cleanUnref, *dirtyUnref, *cleanRef; //stores the indicies of each class of eviction candidate bit32 numCleanUnref = 0, numDirtyUnref = 0, numCleanRef = 0; //stores the number of candidates in each class //set up eviction candidate arrays cleanUnref = (bit32 *) malloc(sizeof(bit32) * numFrames); dirtyUnref = (bit32 *) malloc(sizeof(bit32) * numFrames); cleanRef = (bit32 *) malloc(sizeof(bit32) * numFrames); //find the number and place of each eviction candidate for(i = 0; i < numFrames; i++) { if(!isRef(pageTable, frames[i]) && !isDirty(pageTable, frames[i])) { //page in current frame is not referenced and not dirty cleanUnref[numCleanUnref] = i; numCleanUnref++; } else if(!isRef(pageTable, frames[i]) && isDirty(pageTable, frames[i])) { //page in current frame is not referenced, but is dirty - second best solution dirtyUnref[numDirtyUnref] = i; numDirtyUnref++; } else if(isRef(pageTable, frames[i]) && !isDirty(pageTable, frames[i])) { //page is referenced, but not dirty - third best solution cleanRef[numCleanRef] = i; numCleanRef++; } } if(numCleanUnref > 0) { //choose random number i = rand() % numCleanUnref; frameToEvict = cleanUnref[i]; } else if(numDirtyUnref > 0) { //choose random number i = rand() % numDirtyUnref; frameToEvict = dirtyUnref[i]; } else if(numCleanRef > 0) { //choose random number i = rand() % numCleanRef; frameToEvict = cleanRef[i]; } else { //all frames were referenced and dirty - choose any random frame frameToEvict = rand() % numFrames; } //free memory of arrays - frame to evict has been found free(cleanUnref); free(dirtyUnref); free(cleanRef); //evict the frame if(isDirty(pageTable, frames[frameToEvict])) { numWrites++; printf("%i\tpage fault - evict dirty\n", numRefs + 1); } else { printf("%i\tpage fault - evict clean\n", numRefs + 1); } evictPage(pageTable, frames[frameToEvict]); frames[frameToEvict] = pageNo; //store the page number in the frame placePageInFrame(pageTable, pageNo, frameToEvict, curr->mode); //map current page to frame } } //increment number of references and move to next reference numRefs++; curr = curr->next; } //ends while //print stats printf("\nNRU\n"); printf("Number of frames:\t%i\n", numFrames); printf("Total memory accesses:\t%i\n", numRefs); printf("Total page faults:\t%i\n", numFaults); printf("Total writes to disk:\t%i\n\n", numWrites); //clean up memory free(frames); } //ends NRU simulation
//run the clock simulation void simulateClock(bit32 numFrames, const char *fileName) { struct clockFrame *frames, *currFrame; //pointers to the frame list and the current frame bit32 *pageTable; //page table struct memRef *memList, *currRef; //pointer to current memory reference bit32 numFaults = 0, numWrites = 0, numRefs = 0; //stat counters bit32 usedFrames = 0, pageNo, i; //number of used frames, loop counter //set up page table and ensure all bits are 0 pageTable = (bit32 *) malloc(NUM_PAGES * sizeof(bit32)); memset(pageTable, 0, sizeof(bit32) * NUM_PAGES); //set up the frame clock for(i = 0; i < numFrames; i++) { struct clockFrame *temp = (struct clockFrame *) malloc(sizeof(struct clockFrame)); temp->frameNo = i; temp->pageNo = ZERO; temp->next = NULL; if(i == 0) { frames = temp; //if its the first time through, we've created the first frame } else { currFrame->next = temp; //if it's not the first, temp frame should be pointed to by previous frame } currFrame = temp; //update curr } currFrame->next = frames; currFrame = frames; //read the file in and store the references and future uses of the references readFile(&memList, fileName); currRef = memList; while(currRef != NULL) { pageNo = getPageNumber(currRef->reference); if(isValid(pageTable, pageNo)) { //page already valid/in a frame - hit pageHitSetBits(pageTable, pageNo, currRef->mode); //set appropriate bits printf("%i\thit\n", numRefs + 1); } else { //page is not in a frame yet - miss numFaults++; if(usedFrames < numFrames) { //compulsory miss - add the page to the next frame currFrame->pageNo = pageNo; currFrame = currFrame->next; placePageInFrame(pageTable, pageNo, currFrame->frameNo, currRef->mode); //map current page to frame usedFrames++; printf("%i\tpage fault - no eviction\n", numRefs + 1); } else { //capacity miss - frames are full and page is not in a frame - will need to evict //find an unreferenced page, clearing referenced pages along the way while(isRef(pageTable, currFrame->pageNo)) { pageTable[currFrame->pageNo] = pageTable[currFrame->pageNo] & CLEAR_REF; currFrame = currFrame->next; } //currFrame now points to an unreferenced page - evict the frame if(isDirty(pageTable, currFrame->pageNo)) { numWrites++; printf("%i\tpage fault - evict dirty\n", numRefs + 1); } else { printf("%i\tpage fault - evict clean\n", numRefs + 1); } evictPage(pageTable, currFrame->pageNo); currFrame->pageNo = pageNo; //store the page number in the frame placePageInFrame(pageTable, pageNo, currFrame->frameNo, currRef->mode); //map current page to frame //move curr to the next frame currFrame = currFrame->next; } } //increment number of references and move to next reference numRefs++; currRef = currRef->next; } //print stats printf("\nClock\n"); printf("Number of frames:\t%i\n", numFrames); printf("Total memory accesses:\t%i\n", numRefs); printf("Total page faults:\t%i\n", numFaults); printf("Total writes to disk:\t%i\n\n", numWrites); //clean up memory currFrame = frames; for(i = 0; i < numFrames; i++) { frames = currFrame->next; free(currFrame); currFrame = frames; } } //ends clock simulation
//run the OPT algorithm simulation void simulateOpt(bit32 numFrames, const char *fileName) { struct memRef *memList, *curr; //list of memory references bit32 *pageTable; //page table struct nextUse **future; //array of nextUse structures struct nextUse *tempFuture; //used to deallocate nodes of future use bit32 numFaults = 0, numWrites = 0, numRefs = 0; //stat counters struct optFrame *frames; //frame structure bit32 i, pageNo, frameNo, usedFrames = 0; //loop control, page number, frame number, and number of used frames //set up page table and ensure all bits are 0 pageTable = (bit32 *) malloc(NUM_PAGES * sizeof(bit32)); memset(pageTable, 0, sizeof(bit32) * NUM_PAGES); //set up the future array future = (struct nextUse **) malloc(sizeof(struct nextUse *) * NUM_PAGES); for(i = 0; i < NUM_PAGES; i++) { struct nextUse *temp = (struct nextUse *) malloc(sizeof(struct nextUse)); temp->time = MAX_UINT; temp->next = NULL; temp->tail = NULL; *(future + i) = temp; } //read the file in and store the references and future uses of the references readOptFile(&memList, future, fileName); //set up memory frames frames = (struct optFrame *) malloc(sizeof(struct optFrame) * numFrames); for(i = 0; i < numFrames; i++) { frames[i].pageNo = MAX_UINT; frames[i].next = *(future + i); } curr = memList; while(curr != NULL) { pageNo = getPageNumber(curr->reference); if(isValid(pageTable, pageNo)) { //page already already valid/in a frame - hit pageHitSetBits(pageTable, pageNo, curr->mode); //set appropriate bits frameNo = getFrameNumber(pageTable, pageNo); //get the frame number for this page tempFuture = future[pageNo]; //store current use for deallocation future[pageNo] = future[pageNo]->next; //move the next use down one frames[frameNo].next = future[pageNo]; //update the future array with next use of this page free(tempFuture); //deallocate printf("%i\thit\n", numRefs + 1); } else { //page is not in a frame yet - miss numFaults++; //compulsory miss - will only happen numFrames times if(usedFrames < numFrames) { frames[usedFrames].pageNo = pageNo; //store the page number in the frame tempFuture = future[pageNo]; //store current use for deallocation future[pageNo] = future[pageNo]->next; //move the next use of this page down frames[usedFrames].next = future[pageNo]; //update the link to future use in the frame table free(tempFuture); //deallocate the current use placePageInFrame(pageTable, pageNo, usedFrames, curr->mode); //map current page to frame usedFrames++; printf("%i\tpage fault - no eviction\n", numRefs + 1); } else { //capacity miss - evict page not used until furthest in future bit32 furthest = 0; //index of the page with the furthest future use bit32 ptIndex; //page number of the page used furthest in the future i = 0; if(frames[i].next == NULL) { //there is not future use of this page - we were lucky, can avoid loop furthest = i; } else { for(i = 1; i < numFrames; i++) { if(frames[i].next == NULL) { //there is no future use of this page - can safely remove furthest = i; //printf("\tNULL FOUND: furthest = %i", furthest); i = numFrames; //exit loop } else { //find the furthest future use of a page if(frames[i].next->time > frames[furthest].next->time) { furthest = i; } } } } //evict page in frame[furthest] - page used furthest in future ptIndex = frames[furthest].pageNo; if(isDirty(pageTable, ptIndex)) { numWrites++; printf("%i\tpage fault - evict dirty\n", numRefs + 1); } else { printf("%i\tpage fault - evict clean\n", numRefs + 1); } evictPage(pageTable, ptIndex); frames[furthest].pageNo = pageNo; //store the page number in the frame tempFuture = future[pageNo]; //store current use for deallocation future[pageNo] = future[pageNo]->next; //move future use down to next use frames[furthest].next = future[pageNo]; //update the frames reference to the future table free(tempFuture); //deallocate memory placePageInFrame(pageTable, pageNo, furthest, curr->mode); //map current page to frame } } //increment number of references and move to next reference numRefs++; curr = curr->next; } //print stats printf("\nNRU\n"); printf("Number of frames:\t%i\n", numFrames); printf("Total memory accesses:\t%i\n", numRefs); printf("Total page faults:\t%i\n", numFaults); printf("Total writes to disk:\t%i\n\n", numWrites); //clean up memory free(frames); free(future); }