void allocate_frame(int pid, int type, uint32 vpage) { int i; for (i = 0; i < NFRAMES; i++) { if(invertpagetable[page_head].empty == TRUE) { invertpagetable[page_head].pid = pid; invertpagetable[page_head].type = type; invertpagetable[page_head].empty = FALSE; invertpagetable[page_head].vpage = vpage; return; } page_head = (++page_head) % NFRAMES; } kprintf ("Could not find any empty pages. Must evict\n"); if (policy == FIFO) { kprintf("Eviction Policy: FIFO\n"); uint32 evict_page = (page_head + 1) % NFRAMES; while(invertpagetable[page_head].type != FRAME_REG) { evict_page = (page_head + 1) % NFRAMES; if (evict_page == (page_head + 1) % NFRAMES) { kprintf ("All frames filled by directories or tables!\n"); } } page_head = evict_page; int old_pid = invertpagetable[page_head].pid; int old_type = invertpagetable[page_head].type; int old_vpage = invertpagetable[page_head].vpage; int old_bs = bs_page(old_vpage); int old_pd = pd(old_vpage); int old_pt = pt(old_vpage); struct procent *old_prptr = &proctab[old_pid]; pd_t *old_pd_t = old_prptr->prpagedir; pt_t *old_pt_t = (old_pd_t[old_pd].pd_base << 12); old_pt_t[old_pt].pt_pres = 0; char* addr = (char *)frame2addr(page_head); if(open_bs(old_prptr->prbs) == (uint32)-1 || write_bs(addr, old_prptr->prbs, old_bs)|| close_bs(old_prptr->prbs) == (uint32)-1) { kprintf("Backing store error during eviction!"); return; } invertpagetable[page_head].pid = pid; invertpagetable[page_head].type = type; invertpagetable[page_head].empty = FALSE; invertpagetable[page_head].vpage = vpage; } }
/*------------------------------------------------------------------------ * kill - Kill a process and remove it from the system *------------------------------------------------------------------------ */ syscall kill( pid32 pid /* ID of process to kill */ ) { intmask mask; /* Saved interrupt mask */ struct procent *prptr; /* Ptr to process' table entry */ int32 i; /* Index into descriptors */ mask = disable(); if (isbadpid(pid) || (pid == NULLPROC) || ((prptr = &proctab[pid])->prstate) == PR_FREE) { restore(mask); return SYSERR; } /* * Virtual memory-related cleanup section. */ /* If backing store was allocated, close and deallocate it */ int retries = 4; bsd_t bs = (bsd_t) -1; if(prptr->prbs == -1) { bs = 0; } while(bs == -1 && retries > 0) { bs = deallocate_bs(close_bs(prptr->prbs)); retries --; } if(bs == -1) { kprintf("!!Warning: could not close and deallocate the backing store of pid %d. ",pid); } /* Deallocate all physical frames that the current process holds */ free_proc_frames(pid); /* Free virtual memory free list */ struct vmemblk *next, *cur = prptr->prvmemlist; while(cur!=NULL) { next = cur->mnext; freemem((char*)cur, sizeof(struct vmemblk)); cur = next; } if (--prcount <= 1) { /* Last user process completes */ xdone(); } send(prptr->prparent, pid); for (i=0; i<3; i++) { close(prptr->prdesc[i]); } freestk(prptr->prstkbase, prptr->prstklen); switch (prptr->prstate) { case PR_CURR: prptr->prstate = PR_FREE; /* Suicide */ resched(); case PR_SLEEP: case PR_RECTIM: unsleep(pid); prptr->prstate = PR_FREE; break; case PR_WAIT: semtab[prptr->prsem].scount++; /* Fall through */ case PR_READY: getitem(pid); /* Remove from queue */ /* Fall through */ default: prptr->prstate = PR_FREE; } restore(mask); return OK; }
int free_frame(frame_t * frame) { intmask mask; mask = disable(); //LOG("Freeing"); //print_frame(frame); if(frame->id <5) { LOG(" WHAT THE F**K %d %d", frame->id, frame->type); restore(mask); return OK; } //kprintf("id %d type %d ", frame->id, frame->type); //print_fifo_list(); //kprintf("\n"); if(frame == NULL) { restore(mask); return SYSERR; } else if(!FRAMEID_IS_VALID(frame->id)) { restore(mask); return SYSERR; } else if(frame->type == FREE) { restore(mask); return OK; } else if(frame->type == PAGE){ //print_fifo_list(); //LOG("Got here 0.5"); //3. Using the inverted page table, get vp, the virtual page number of the page to be replaced. uint32 vp = frame->vp_no; //4. Let a be vp*4096 (the first virtual address on page vp). hook_pswap_out(vp, frame->id + FRAME0); uint32 a = vp*PAGE_SIZE; virtual_addr * virt = (virtual_addr *) &a; //5. Let p be the high 10 bits of a. Let q be bits [21:12] of a. uint32 p = virt->page_directory_offset; uint32 q = virt->page_table_offset; //6. Let pid be the process id of the process owning vp. pid32 pid = frame->pid; //7. Let pd point to the page directory of process pid. struct procent *prptr; /* Ptr to process table entry */ prptr = &proctab[pid]; pd_t * pd = prptr->pagedir; if( pd == NULL) { LOG(" pd doesn't exist "); restore(mask); return SYSERR; } bool8 pt_pres = FALSE; pt_pres = (bool8) pd[p].pd_pres; bool8 pg_pres = FALSE; bool8 dirty = FALSE; if(pt_pres) { //8. Let pt point to the pid's p_th page table. pt_t * pt = (pt_t *) ((pd[p].pd_base) * PAGE_SIZE); pg_pres = (bool8) pt[q].pt_pres; uint32 pg_base = (uint32) pt[q].pt_base; if(pg_pres){ if((uint32)FRAMEID_TO_VPAGE(frame->id) == pg_base) { pg_pres = TRUE; dirty = pt[q].pt_dirty; } else { pg_pres = FALSE; } } } if(pg_pres) { frame_t * pt_frame = &frames[(pd[p].pd_base) - FRAME0]; pt_t * pt = (pt_t *) ((pd[p].pd_base) * PAGE_SIZE); //9. Mark the appropriate entry of pt as not present. pt[q].pt_pres = 0; if(pt_frame->type == VPTBL){ decr_frame_refcount(pt_frame); if(pt_frame->refcount == 0){ pd[p].pd_pres = 0; free_frame(pt_frame); } bzero((char *)&pt[q], sizeof(pt_t)); } else if(pt_frame->type == GPTBL) { // kprintf(" Uh OH"); } // If the reference count has reached zero, you should mark the appropriate entry in pd as "not present." // This conserves frames by keeping only page tables which are necessary. //LOG("Got here 1.5"); //If the dirty bit for page vp was set in its page table, you must do the following: //a) Using the backing store map, find the store and page offset within the store, given pid and a. // If the lookup fails, something is wrong. Print an error message and kill the process with id pid. //b) Write the page back to the backing store. //LOG("Got here 2"); if(dirty){ bsd_t bs_store_id; int bs_store_page_offset; if(SYSERR == bs_map_check(pid, vp, &bs_store_id, &bs_store_page_offset)) { kprintf("FATAL :Can't find the bs_map"); restore(mask); kill(currpid); return SYSERR; } //print_frame(frame); if(BACKSTORE_ID_IS_VALID(frame->backstore) && BACKSTORE_OFFSET_IS_VALID(frame->backstore_offset) && frame->backstore == bs_store_id && frame->backstore_offset == bs_store_page_offset) { //LOG("Frame %d was dirty", frame->id); open_bs(frame->backstore); write_bs(FRAMEID_TO_PHYSICALADDR(frame->id), frame->backstore, frame->backstore_offset); close_bs(frame->backstore); } //else //{ // print_frame(frame); // kprintf("Fatal error: Cannot locate backstore for vpage %d to swap out page for pid %d ", vp, pid); // kill(pid); // initialize_frame(frame); // restore(mask); // return SYSERR; //} } else{ //print_frame(frame); } } //LOG("Got here 1"); //10. If the page being removed belongs to the current process, // invalidate the TLB entry for the page vp, using the invlpg instruction (see Intel Manual, volumes II and III for more details on this instruction). // 11. In the inverted page table, decrement the reference count of the frame occupied by pt. //LOG(" Free frame"); //print_frame(frame); enable_paging(); initialize_frame(frame); // Update page table entries associated with this frame // set the frame to be free } else if(frame->type == VPTBL) { evict_from_fifo_list(frame); hook_ptable_delete(frame->id + FRAME0); enable_paging(); initialize_frame(frame); } else if(frame->type == DIR) { struct procent * prptrNULL = &proctab[NULLPROC]; pd_t * null_pg_dir = prptrNULL->pagedir; struct procent *prptr; /* Ptr to process table entry */ prptr = &proctab[currpid]; if(prptr->pagedir!= null_pg_dir) { evict_from_fifo_list(frame); prptr->pagedir = prptrNULL->pagedir; switch_page_directory(prptr->pagedir); enable_paging(); initialize_frame(frame); } } restore(mask); return OK; }