/*! Obtain a frame, either through palloc() or through eviction */ struct frame_table_entry *obtain_frame(enum palloc_flags flag, struct supp_table *pte) { void *page; struct frame_table_entry *newframe; page = palloc_get_page(flag); if (!page) page = frame_evict(flag); if (!page) PANIC("run out of frames!\n"); /*! Allocate a frame table entry and initialize it */ newframe = (struct frame_table_entry *)\ malloc(sizeof(struct frame_table_entry)); if (!newframe) PANIC("malloc failure\n"); newframe->physical_addr = page; newframe->owner = thread_current(); newframe->spt = pte; if (f_table.lock.holder != thread_current()) lock_acquire(&f_table.lock); list_push_back(&f_table.table, &newframe->elem); lock_release(&f_table.lock); return newframe; }
/* * Searches for a free frame and returns one if available. * If all frames are full, evict a frame and return pointer to evicted frame. */ void* frame_get_free() { lock_acquire_re(&vm_lock); log_debug("+++ frame_get_free (used: %d, own used: %d) +++\n", frametable.used, frametable.own_used); // TODO if (frametable.used < frametable.size) { // some free frames left while(1) { if (frametable.frametable[frametable.search_ptr].pte == NULL) { // FIXME reserve entry by changing pointer frametable.frametable[frametable.search_ptr].pte = (void*) 0xFFFFFFFF; frametable.used++; void* tmp = pagenum_to_page(frametable.search_ptr); log_debug("### Free page at 0x%08x ###\n", (uint32_t) tmp); lock_release_re(&vm_lock); return tmp; } // jump to next position frametable.search_ptr = (frametable.search_ptr + 1) % frametable.size; } } else { // no free frames left // evict frame void *tmp = frame_evict(); lock_release_re(&vm_lock); return tmp; } NOT_REACHED(); return NULL; }
/* Given a virtual address (page) find a frame to put the page in and return the physical address of the frame */ void* frame_obtain (enum palloc_flags flags, void* uaddr) { struct frame_table_entry* fte; /* Try and obtain frame in user memory */ void *kaddr = palloc_get_page (flags); /* Successfully obtained frame */ if (kaddr != NULL) { /* Create new frame table entry mapping the given page to the allocated frame */ fte = (struct frame_table_entry *) malloc (sizeof (struct frame_table_entry)); fte->owner = thread_current (); fte->kaddr = kaddr; fte->uaddr = pg_round_down (uaddr); lock_acquire (&frame_table_lock); list_push_front (&frame_table, &fte->elem); lock_release (&frame_table_lock); return fte->kaddr; } /* Failed to obtain frame */ else { /* Perform eviction to release a frame and try allocation again */ if (PAGE_EVICTION) { return frame_evict (uaddr); } else { PANIC ("Failed to allocate frame - eviction disabled."); } } }
void * frame_alloc (enum palloc_flags flags, struct SP_entry *page_entry) { if ((flags & PAL_USER) == 0) { return NULL; } void *frame = palloc_get_page (flags); if (frame) { frame_add (frame, page_entry); } else { while (!frame) { frame = frame_evict (flags); } if (!frame) { PANIC ("Frame evict failed. Swap is full!"); } frame_add (frame, page_entry); } return frame; }