void page_unload(struct page *p, void *fp_addr) { if (p->type == F) { if(pagedir_is_dirty(p->dir, p->f_addr)) { pin_frame(p->kpage); file_seek(p->f, p->ofs); file_write(p->f, fp_addr, p->read); unpin_frame(p->kpage); } } else if(p->type == S) { p->type = S; p->swap_index = store_swap(fp_addr); } else if(pagedir_is_dirty(p->dir, p->f_addr)) { p->swap_index = store_swap(fp_addr); p->type = S; } p->load = false; p->kpage = NULL; pagedir_clear_page(p->dir, p->f_addr); }
/** * Allocate a new frame, * and return the address of the associated page. */ void* vm_frame_allocate (enum palloc_flags flags, void *upage) { lock_acquire (&frame_lock); void *frame_page = palloc_get_page (PAL_USER | flags); if (frame_page == NULL) { // page allocation failed. /* first, swap out the page */ struct frame_table_entry *f_evicted = pick_frame_to_evict( thread_current()->pagedir ); #if DEBUG printf("f_evicted: %x th=%x, pagedir = %x, up = %x, kp = %x, hash_size=%d\n", f_evicted, f_evicted->t, f_evicted->t->pagedir, f_evicted->upage, f_evicted->kpage, hash_size(&frame_map)); #endif ASSERT (f_evicted != NULL && f_evicted->t != NULL); // clear the page mapping, and replace it with swap ASSERT (f_evicted->t->pagedir != (void*)0xcccccccc); pagedir_clear_page(f_evicted->t->pagedir, f_evicted->upage); bool is_dirty = false; is_dirty = is_dirty || pagedir_is_dirty(f_evicted->t->pagedir, f_evicted->upage); is_dirty = is_dirty || pagedir_is_dirty(f_evicted->t->pagedir, f_evicted->kpage); swap_index_t swap_idx = vm_swap_out( f_evicted->kpage ); vm_supt_set_swap(f_evicted->t->supt, f_evicted->upage, swap_idx); vm_supt_set_dirty(f_evicted->t->supt, f_evicted->upage, is_dirty); vm_frame_do_free(f_evicted->kpage, true); // f_evicted is also invalidated frame_page = palloc_get_page (PAL_USER | flags); ASSERT (frame_page != NULL); // should success in this chance } struct frame_table_entry *frame = malloc(sizeof(struct frame_table_entry)); if(frame == NULL) { // frame allocation failed. a critical state or panic? lock_release (&frame_lock); return NULL; } frame->t = thread_current (); frame->upage = upage; frame->kpage = frame_page; frame->pinned = true; // can't be evicted yet // insert into hash table hash_insert (&frame_map, &frame->helem); list_push_back (&frame_list, &frame->lelem); lock_release (&frame_lock); return frame_page; }
void do_munmap(struct mmap_file *mmap_file) { struct list_elem *e = list_begin(&mmap_file->vme_list); struct list_elem *next; struct vm_entry *entry; struct thread *t = thread_current(); //printf("do_mumap start\n"); while(e != list_end(&mmap_file->vme_list)) { next = list_next(e); entry = list_entry(e,struct vm_entry,mmap_elem); entry->pinned = true; if(entry->is_loaded) // is_loaded true -> page free, false-> pass { if(pagedir_is_dirty(t->pagedir,entry->vaddr)) // dirty -> write, no dirty -> pass { lock_acquire(&file_lock); file_write_at(entry->file,entry->vaddr, entry->read_bytes,entry->offset); lock_release(&file_lock); } free_page(pagedir_get_page(t->pagedir, entry->vaddr)); pagedir_clear_page(t->pagedir,entry->vaddr); } list_remove(e); // remove element on vme_list delete_vme(&t->vm,entry); // remove element on vm (hash) free(entry); e = next; } //printf("mummap end\n"); }
/*! Use the clock algorithm to select a frame to evict and execute the eviction. */ void * frame_evict(enum palloc_flags flag) { struct list_elem *ce; struct thread *ct; struct frame_table_entry *cf; int i; if (f_table.lock.holder != thread_current()) lock_acquire(&f_table.lock); /* Get frame table lock */ if (list_empty(&f_table.table)) { lock_release(&f_table.lock); /* Nothing to evict */ return NULL; } f_table.hand = f_table.hand % list_size(&f_table.table); ce = list_begin(&f_table.table); /* Begin iteration */ for (i = 0; i < f_table.hand; i++) { /* Find where the "hand" points to: that is where the iteration starts */ ce = list_next(ce); } while (true) { cf = list_entry(ce, struct frame_table_entry, elem); ct = cf->owner; if (!cf->spt->pinned) { /* If pinned, skip this frame */ if (pagedir_is_accessed(ct->pagedir, cf->spt->upage)) /* If accessed, clear accessed bit */ pagedir_set_accessed(ct->pagedir, cf->spt->upage, false); else { /* Swap out the page! */ if (cf->spt->type != SPT_MMAP) { cf->spt->fr = NULL; cf->spt->type = SPT_SWAP; cf->spt->swap_index = swap_out(cf->physical_addr); } /* Write the frame back to the map'd file */ else if (cf->spt->type == SPT_MMAP && pagedir_is_dirty(ct->pagedir, cf->spt->upage)) { cf->spt->fr = NULL; file_write_at(cf->spt->file, cf->physical_addr, cf->spt->read_bytes, cf->spt->ofs); } /* Clear the frame */ list_remove(ce); pagedir_clear_page(ct->pagedir, cf->spt->upage); palloc_free_page(cf->physical_addr); free(cf); lock_release(&f_table.lock); return palloc_get_page(flag); } } ce = list_next(ce); ++f_table.hand; if (ce == list_end(&f_table.table)) { /* Iterate circularly */ ce = list_begin(&f_table.table); f_table.hand = 0; } } }
/*! Memory ummap according the given mapid. */ void munmap(mapid_t mapping){ uint32_t f_size, write_bytes, page_write_size, pws2; off_t ofs = 0; struct list_elem *e; struct supp_table* st; /* First find the mmap struct according to the given mapid. */ struct mmap_elem *me = find_mmap_elem(mapping); struct thread* t = thread_current(); /* Get the file length. And set write_bytes as file length.*/ f_size = file_length(me->file); write_bytes = f_size; /* Freeing all the pages in this mmap struct. */ while (!list_empty(&me->s_table)) { e = list_pop_front(&me->s_table); st = list_entry(e, struct supp_table, map_elem); if (st->fr) { /* Set up how many bytes is going to be freed in this page. */ if (write_bytes >= PGSIZE) page_write_size = PGSIZE; else page_write_size = write_bytes; /* If the page is dirty, then write back the data to the file. */ if (pagedir_is_dirty(t->pagedir, st->upage)){ lock_acquire(&filesys_lock); pws2 = file_write_at(st->file, st->fr->physical_addr, st->read_bytes, st->ofs); lock_release(&filesys_lock); ASSERT(pws2 == page_write_size); } /* Update the offset for file writing.*/ ofs += page_write_size; /* Update remaining write_bytes.*/ write_bytes -= page_write_size; } /* Destroy the freed supplemental page entry.*/ spte_destructor_func(&(st->elem), NULL); } /* Close the file. */ file_close(me->file); /* Remove the mmap struct from the mmap list of this process. */ list_remove(&(me->elem)); /* Free the memory of this struct. */ free(me); }
struct list_elem* first_clean(){ struct list_elem *e; for (e = list_rbegin (&framelist); e != list_rend (&framelist); e = list_prev(e)) { struct frame *f = list_entry(e, struct frame , elem); /* printf(" first clean %p %p \n ",f->upage,f->kpage); */ if(!pagedir_is_dirty(thread_current()->pagedir,f->upage) && f->thread==thread_current()) return e; } return NULL; }
void * frame_evict (enum palloc_flags flags) { lock_acquire (&frame_table_lock); struct list_elem *e = list_begin (&frame_table); while (true) { struct frame_entry *frame_entry = list_entry (e, struct frame_entry, elem); struct SP_entry *page_entry = frame_entry->page_entry; if (!page_entry->pinned) { struct thread *t = frame_entry->thread; if (pagedir_is_accessed (t->pagedir, page_entry->page)) { pagedir_set_accessed (t->pagedir, page_entry->page, false); } else { if (pagedir_is_dirty (t->pagedir, page_entry->page) || page_entry->type == SP_SWAP) { if (page_entry->type == SP_MMAP) { lock_acquire (&filesys_lock); file_write_at (page_entry->file, frame_entry->frame, page_entry->read_bytes, page_entry->offset); lock_release (&filesys_lock); } else { page_entry->type = SP_SWAP; page_entry->swap_index = swap_out (frame_entry->frame); } } page_entry->is_loaded = false; list_remove (&frame_entry->elem); pagedir_clear_page (t->pagedir, page_entry->page); palloc_free_page (frame_entry->frame); free (frame_entry); lock_release (&frame_table_lock); return palloc_get_page (flags); } } e = list_next (e); if (e == list_end (&frame_table)) { e = list_begin (&frame_table); } } }
/** * \page_munmap * \unmap the page * * \param table supplemental page table * \param spte supplemental page table entry * \param pagedir pagedirectory of corresponding process * * \retval void */ void page_munmap (struct hash *table, struct page_entry *spte, void *pagedir) { /* If page is loaded in memory, free it */ if (spte->is_loaded) { void *paddr = pagedir_get_page (pagedir, spte->vaddr); /* If this page is dirty, write back to file */ if (pagedir_is_dirty (pagedir, spte->vaddr)) { file_write_at (spte->file, paddr, spte->read_bytes, spte->ofs); } palloc_free_page (paddr); } /* Delete entry and set vaddr regin to be not present */ hash_delete (table, &spte->elem); pagedir_clear_page (pagedir, spte->vaddr); free (spte); }
/* Evicts the page held in F. */ void evict(struct frame *f) { uint32_t *pd = thread_current()->pagedir; ASSERT(lock_held_by_current_thread(&f->evicting)); // lock_acquire(&f->page->moving); /* You should never block here. */ ASSERT(f->page != NULL); ASSERT(lock_held_by_current_thread(&f->page->moving)); /* Clear page to prevent further writes. */ pagedir_clear_page(f->page->thread->pagedir, f->page->vaddr); /* If the page had been written to, the changes must be saved. */ if(pagedir_is_dirty(f->page->thread->pagedir, f->page->vaddr)) { if(f->page->status == PAGE_MAPPED) { /* If the page is mapped, write changes back to file. */ bool have_lock = lock_held_by_current_thread(&fs_lock); if(!have_lock) lock_acquire(&fs_lock); if(file_write_at(f->page->file, f->addr, f->page->read_bytes, f->page->ofs) != f->page->read_bytes) PANIC("Didn't write expected %d bytes.", f->page->read_bytes); if(!have_lock) lock_release(&fs_lock); } else { /* Write page to swap. */ ASSERT(pagedir_is_writeable(f->page->thread->pagedir, f->page->vaddr)); ASSERT(f->page->writeable); swap_out(f); } } /* Unset link the page and frame. */ f->page->current_frame = NULL; lock_release(&f->page->moving); f->page = NULL; }
void evict(){ /* struct list_elem* e= first_clean(); */ /* printf("thread %d ,waiting for flock",thread_current()->tid); */ lock_acquire(&framelock); struct list_elem* e= list_front(&framelist); struct frame *f = list_entry(e, struct frame , elem); bool lock_held=lock_held_by_current_thread(&f->thread->SPT_lock); /* printf("framelock acquired %d %d current:%d \n",f->thread->tid,lock_held,thread_current()->tid); */ ASSERT(!lock_held) lock_acquire(&f->thread->SPT_lock); /* printf("Evict called by %d ,evicted thread,%d evicted address %p and lock_held=%d and after acquire=%d\n",thread_current()->tid,f->thread->tid,f->upage,lock_held,lock_held_by_current_thread(&f->thread->SPT_lock)); */ if (pagedir_is_dirty(f->thread->pagedir,f->upage)) /* if(e==NULL) */ { ASSERT(f!=NULL); /* printf("sector %d \n",sector); */ struct page_data *p = SPT_lookup(f->upage,f->thread); if(p!=NULL){ if(p->loc==mmap1) { printf("removing2\n"); write_back_map(f->upage,p->file,p->offset); remove_mapping(f->upage,f->kpage,e,f->thread); lock_release(&framelock); if(!lock_held)lock_release(&f->thread->SPT_lock); return; } else { ASSERT(p->loc!=swap); SPT_remove(p->vaddr,f->thread); } } int sector= write_page_to_swap(f->kpage); /* printf("evicton 4 \n"); */ struct page_data *p1= malloc(sizeof(struct page_data)); p1->loc= swap; p1->vaddr=f->upage; p1->block_sector=sector; SPT_insert(p1,f->thread); /* printf("evicton 5 \n"); */ /* printf("in evic3 %p , %p thread: %d\n", f->upage,f->kpage,f->thread->tid); */ remove_mapping(f->upage,f->kpage,e,f->thread); } else { /* printf("found a non dirty page \n"); */ remove_mapping(f->upage,f->kpage,e,f->thread); } /* printf("evict end%d and lock held =%d,lock_held2=%d \n",thread_current()->tid,lock_held_by_current_thread(&f->thread->SPT_lock),lock_held); */ lock_release(&f->thread->SPT_lock); lock_release(&framelock); /* PANIC("OUT OF MEMORY"); */ }
static void sys_munmap(int mapid) { struct thread *curr = thread_current(); struct list_elem *e; struct mapped_file_elem *mapped_elem=NULL; int check_valid = 0; // printf("start munmap\n"); if(mapid<2) { // lock_release(&process_lock); // mmap_lock_release(); return -1; // sys_exit(-1); } for( e = list_begin(&curr->mapfile_list) ; e != list_end(&curr->mapfile_list) ; e = list_next(e) ) { mapped_elem=list_entry(e,struct mapped_file_elem,elem_m); if(mapped_elem->mapid==mapid) { // printf("yes here is\n"); check_valid=1; break; } } // printf("here?\n"); if(check_valid==0) { // lock_release(&process_lock); // mmap_lock_release(); return -1; // sys_exit(-1); } // printf("here?\n"); int read_bytes = mapped_elem->size; // printf("before real\n"); struct hash_iterator i; hash_first(&i,&curr->pages); // frame_lock_acquire(); // printf("start real\n"); while( hash_next(&i) ) { struct page *pa = hash_entry( hash_cur(&i), struct page, hash_elem); struct list_elem *e_f; struct frame_elem *f=NULL; if(pa->mapid == mapped_elem->mapid) { // printf("find this\n"); for(e_f = list_begin( &frame_table ) ; e_f != list_end( &frame_table) ; e_f = list_next (e_f) ) { f = list_entry( e_f ,struct frame_elem , elem); if(f->vaddr == pa->vaddr) { // printf("find frame too\n"); break; } } if( pagedir_is_dirty(curr->pagedir,pa->vaddr) ) { // printf("omg\n"); if(mapped_elem != NULL) { // printf("here\n"); // printf("aaa%s\n",f->paddr); file_seek( mapped_elem->mapped_file, pa->offset); // printf("should be 0 %d\n",pa->offset); file_write( mapped_elem->mapped_file, f->paddr ,PGSIZE); } } // frame_lock_acquire(); pagedir_clear_page(curr->pagedir , pa->vaddr); // printf("here?\n"); frame_free_page( f->paddr); // printf("here ???\n"); page_free(pa->vaddr); // printf("here??????\n"); hash_first(&i,&curr->pages); // frame_lock_release(); } } file_seek( mapped_elem->mapped_file, 0); list_remove(&mapped_elem->elem_m); // free(mapped_elem->name); free(mapped_elem); // printf("munmap finish\n"); // mmap_lock_release(); // frame_lock_release(); }
void sys_exit(int status) { struct thread *curr=thread_current(); struct thread *parent=curr->parent; struct child_list_elem *child_elem; struct list_elem *e; printf("%s: exit(%d)\n",curr->name,status); for( e= list_begin(&parent->child_list) ; e != list_end(&parent->child_list) ; e = list_next(e) ) { child_elem=list_entry(e,struct child_list_elem,elem_w); if(child_elem->tid==curr->tid) { child_elem->exit_status[0]=1; child_elem->exit_status[1]=status; } } while(!list_empty( &curr->mapfile_list ) ) { // printf("gogo~\n"); struct list_elem *e = list_pop_front(&curr->mapfile_list); // printf("%d\n",list_entry(e,struct mapped_file_elem, elem_m)->mapid); struct mapped_file_elem *mapped_elem = list_entry(e,struct mapped_file_elem,elem_m); // sys_munmap(mapped_elem->mapid); struct hash_iterator i; hash_first(&i,&curr->pages); // printf("start real\n"); while( hash_next(&i) ) { // printf("dddd\n"); struct page *pa = hash_entry( hash_cur(&i), struct page, hash_elem); struct list_elem *e_f; struct frame_elem *f=NULL; if(pa->mapid == mapped_elem->mapid) { // printf(" %s mapid : %d\n",curr->name,pa->mapid); // printf("find this\n"); for(e_f = list_begin( &frame_table ) ; e_f != list_end( &frame_table) ; e_f = list_next (e_f) ) { f = list_entry( e_f ,struct frame_elem , elem); if(f->vaddr == pa->vaddr) { // printf("find frame too\n"); break; } } if( pagedir_is_dirty(curr->pagedir,pa->vaddr) ) { // printf("omg\n"); if(mapped_elem != NULL) { // printf("here\n"); // printf("aaa%s\n",f->paddr); file_seek( mapped_elem->mapped_file, pa->offset); // printf("should be 0 %d\n",pa->offset); file_write( mapped_elem->mapped_file, f->paddr ,PGSIZE); } } frame_lock_acquire(); pagedir_clear_page(curr->pagedir , pa->vaddr); // printf("here?\n"); // printf("here ???\n"); page_free(pa->vaddr); frame_free_page( f->paddr); frame_lock_release(); // printf("here??????\n"); //sys_munmap(mapped_elem->mapid); hash_first(&i,&curr->pages); } } file_seek( mapped_elem->mapped_file, 0); list_remove(&mapped_elem->elem_m); // free(mapped_elem->name); free(mapped_elem); } thread_exit(); }