PhysicalFrame* findFreePhysicalPage(MMUSim* sim){ Dllist freeFrames; freeFrames = sim->freePhysicalFrames; Dllist usedFrames; usedFrames = sim->usedPhysicalFrames; JRB tree; tree = sim->frameTree; Dllist nil; nil = dll_nil(freeFrames); Dllist ffp; ffp = dll_first(freeFrames); if(ffp != nil){ PhysicalFrame* freeFrame; freeFrame = ffp->val.v; dll_delete_node(ffp); dll_append(usedFrames, new_jval_v(freeFrame)); if(sim->rep == 2){ // LRU, sort by time jrb_insert_int(tree,freeFrame->lastUsed,new_jval_v(freeFrame)); } else if(sim->rep == 3){ // LFU, sort by lowCount jrb_insert_int(tree,freeFrame->useCount,new_jval_v(freeFrame)); } else if (sim->rep == 4){ // MFU, sort by highCount jrb_insert_int(tree,freeFrame->useCount,new_jval_v(freeFrame)); } return freeFrame; } else { return -1; } }
MMUProcess* getProcess(MMUSim* sim, int* pid){ Dllist processList; processList = sim->processes; Dllist nil; nil = dll_nil(processList); Dllist s; s = dll_first(processList); while(s != nil){ MMUProcess* proc; proc = s->val.v; if(proc->pid == pid){ return proc; } s = s->flink; } MMUProcess* ps; ps = malloc(sizeof(MMUProcess)); ps->pid = pid; ps->stats.pid = pid; dll_append(processList, new_jval_v(ps)); PageTable* pageTable = malloc(sizeof(PageTable)); PageTableEntry* pageArray = malloc(sim->pageEntries * sizeof(PageTableEntry)); pageTable->table = pageArray; pageTable->size = sim->pageEntries; ps->pgtbl = pageTable; return ps; }
void *elevator(void *arg){ Elevator *e = (Elevator *) arg; Dllist item, next, pickup; Person *p; int direction = 1; pickup = new_dllist(); while(1){ if(e -> onfloor >= top) direction = -1; else if(e -> onfloor <= 1) direction = 1; //printf("\tElevator[%i] on floor %i going %s:\n", // e -> id, e -> onfloor, direction == 1 ? "up": "down"); /* pick people up */ pthread_mutex_lock(lock); item = dll_first(people); while(!dll_empty(people) && item != dll_nil(people)){ next = dll_next(item); p = (Person *) item -> val.v; //printf("\t\tShould I get %s %s going from %i to %i? ", // p -> fname, p -> lname, p -> from, p -> to); if(e -> onfloor == p -> from){ if(p -> to > e -> onfloor && direction == 1 || p -> to < e -> onfloor && direction == -1){ dll_append(pickup, item -> val); dll_delete_node(item); //printf("yes!\n"); } //else printf("no!\n"); } //else printf("no!\n"); item = next; } pthread_mutex_unlock(lock); item = dll_first(pickup); while(!dll_empty(pickup) && item != dll_nil(pickup)){ next = dll_next(item); p = (Person *) item -> val.v; if(!e -> door_open) open_door(e); pthread_mutex_lock(p -> lock); p -> e = e; pthread_cond_signal(p -> cond); pthread_mutex_lock(e -> lock); pthread_mutex_unlock(p -> lock); pthread_cond_wait(e -> cond, e -> lock); pthread_mutex_unlock(e -> lock); dll_delete_node(item); item = next; } if(e -> door_open) close_door(e); move_to_floor(e, e -> onfloor + direction); /* drop people off */ item = dll_first(e -> people); while(!dll_empty(e -> people) && item != dll_nil(e -> people)){ next = dll_next(item); p = (Person *) item -> val.v; if(p -> to == e -> onfloor){ if(!e -> door_open) open_door(e); pthread_mutex_lock(p -> lock); pthread_cond_signal(p -> cond); pthread_mutex_lock(e -> lock); pthread_mutex_unlock(p -> lock); pthread_cond_wait(e -> cond, e -> lock); pthread_mutex_unlock(e -> lock); } item = next; } //if(e -> door_open) close_door(e); } return NULL; }
void runSim(MMUSim* sim, Dllist* traces){ SimStats* simStats; simStats = &(sim->simStats); Dllist nil; nil = dll_nil(*traces); Dllist t; t = dll_first(*traces); MMUProcess* currProc; while(t != nil){ Trace* trace; trace = t->val.v; MMUProcess* proc; proc = getProcess(sim, trace->pid); if(currProc != proc){ contextSwitch(sim); } currProc = proc; ProcessStats* pStat; pStat = &proc->stats; pStat->memoryRef = pStat->memoryRef + 1; simStats->memoryRef = simStats->memoryRef + 1; unsigned int pageNum; unsigned int pageOffset; getPageNumOffset(sim, trace->address, &pageNum, &pageOffset); int op = trace->op; if(sim->log){ char* operation; if(op == 1) {operation = "Load from";} else if(op == 2) {operation = "Store to";} else if(op == 3) {operation = "Instruction fetch from";} fprintf(stderr, "Process[%u]: %s 0x%x (page: %u, offset: %u)\n", trace->pid, operation, trace->address, pageNum, pageOffset); } // Is the PTE in the TLB? PageTableEntry* tlbHit; retry: tlbHit = checkTLB(sim, pageNum); simStats->overallLat = simStats->overallLat + sim->tlbLat; if((int)tlbHit != -1){ // TLB hit if(sim->log) {fprintf(stderr, "\tTLB hit? yes\n");} simStats->overallLat = simStats->overallLat + sim->memLat; // if write, mark dirty if(op == 2){ // Is a write operation? tlbHit->dirty = 1; } if(sim->log) {fprintf(stderr, "\tpage %d in frame %d\n", pageNum, tlbHit->physicalFrame->num);} touchFrame(sim, tlbHit->physicalFrame); }else{ // TLB miss if(sim->log) {fprintf(stderr, "\tTLB hit? no\n");} pStat->tlbMisses = pStat->tlbMisses + 1; simStats->tlbMisses = simStats->tlbMisses + 1; // Is the Physical Frame of the PTE present? PageTableEntry* pte; pte = checkPageTable(sim, proc->pgtbl, pageNum); if(pte->present){ // Present bit is set if(sim->log) {fprintf(stderr, "\tPage fault? no\n");} addPageToTlb(sim, trace->address, pte); simStats->overallLat = simStats->overallLat + sim->tlbLat; // retry goto retry; } else { // Physical frame is not loaded (present) if(sim->log) {fprintf(stderr, "\tPage fault? yes\n");} pStat->pageFaults = pStat->pageFaults + 1; simStats->pageFaults = simStats->pageFaults + 1; // Is there room? PhysicalFrame* pfn; pfn = findFreePhysicalPage(sim); if(pfn != -1){ // We found a free physical frame if(sim->log) {fprintf(stderr, "\tMain memory eviction? no\n");} } else { // no physical frame was found, need to evict if(sim->log) {fprintf(stderr, "\tMain memory eviction? yes\n");} // Update evicted PTE PhysicalFrame* evPte; // evicted PTE PfEvict(sim); // evict a frame based on the chosen policy evPte = findFreePhysicalPage(sim); // go and find that frame MMUProcess* evProc; evProc = getProcess(sim, evPte->pid); // get the process for the evicted frame PageTableEntry* evPageTable; evPageTable = evProc->pgtbl->table; unsigned int evIndex = evPte->pageNum; PageTableEntry* evPageTableEntry; // evicted PageTableEntry evPageTableEntry = &evPageTable[evIndex]; evPageTableEntry->present = 0; pfn = evPte; // clean eviction? if(evPageTableEntry->dirty){ // the frame in memory is dirty and needs disk write if(sim->log) {fprintf(stderr, "\tProcess %d page %u (dirty) evicted from memory\n", evProc->pid, evPte->pageNum);} pStat->dirtyEvict = pStat->dirtyEvict + 1; simStats->dirtyEvict = simStats->dirtyEvict + 1; // wite to disk + disk access simStats->overallLat = simStats->overallLat + sim->diskLat; } else { // frame is clean if(sim->log) {fprintf(stderr, "\tProcess %d page %u (clean) evicted from memory\n", evProc->pid, evPte->pageNum);} pStat->cleanEvict = pStat->cleanEvict + 1; simStats->cleanEvict = simStats->cleanEvict + 1; } // update PTE } pte->page = pageNum; pte->physicalFrame = pfn; simStats->overallLat = simStats->overallLat + sim->diskLat; pte->pid = proc->pid; pte->present = 1; pfn->pid = proc->pid; pfn->pageNum = pageNum; simStats->overallLat = simStats->overallLat + sim->memLat; // update tlb addPageToTlb(sim, trace->address, pte); simStats->overallLat = simStats->overallLat + sim->tlbLat; goto retry; } } if(sim->log) {fprintf(stderr, "\n");} t = t->flink; } }
void PfEvict(MMUSim* sim){ Dllist freeFrames; Dllist usedFrames; freeFrames = sim->freePhysicalFrames; usedFrames = sim->usedPhysicalFrames; Dllist uNil; uNil = dll_nil(usedFrames); Dllist uFrame; uFrame = dll_first(usedFrames); int rep = sim->rep; PhysicalFrame* evictFrame; if(rep == 1){ // FIFO/////////////////////////////// // nothing is needed, FIFO happens automatically evictFrame = uFrame->val.v; }//////////////////////////END FIFO///////////////// else if(rep == 2){ // LRU/////////////////////////// PhysicalFrame* oldFrame; unsigned int oldTime = UINT_MAX; PhysicalFrame* frameArray; frameArray = sim->physicalFrames; PhysicalFrame* currentFrame; int i; for (i = 0; i < sim->numFrames; i++){ currentFrame = &frameArray[i]; if(currentFrame->lastUsed < oldTime){ oldFrame = currentFrame; oldTime = currentFrame->lastUsed; } } evictFrame = oldFrame; Dllist* ref; ref = evictFrame->listRef; uFrame = *ref; } ////////////////////END LRU////////////////////// else if(rep == 3){ // LFU//////////////////////// PhysicalFrame* oldFrame; int oldUse = INT_MAX; PhysicalFrame* frameArray; frameArray = sim->physicalFrames; PhysicalFrame* currentFrame; int i; for (i = 0; i < sim->numFrames; i++){ currentFrame = &frameArray[i]; if(currentFrame->useCount < oldUse){ oldFrame = currentFrame; oldUse = currentFrame->useCount; } } evictFrame = oldFrame; Dllist* ref; ref = evictFrame->listRef; uFrame = *ref; } /////////////////////END LFU////////////////////// else if(rep == 4){ // MFU///////////////////////// evictFrame = sim->mfuFrame; Dllist* ref; ref = evictFrame->listRef; uFrame = *ref; } ////////////////////END MFU////////////////////// else{ // RANDOM/////////////////////////////////// int max = sim->numFrames - 1; int randomIndex = ((double) rand() / (((double)RAND_MAX)+1)) * (max+1); PhysicalFrame* frameArray; frameArray = sim->physicalFrames; PhysicalFrame* randomFrame; randomFrame = &frameArray[randomIndex]; evictFrame = randomFrame; Dllist* randomRef; randomRef = evictFrame->listRef; uFrame = *randomRef; }///////////////// END RANDOM//////////////////// dll_delete_node(uFrame); dll_append(freeFrames, new_jval_v(evictFrame)); Dllist listItem = dll_last(sim->freePhysicalFrames); evictFrame->listRef = listItem; }