static bool install_page (void *upage, void *kpage, bool writable) { struct thread *t = thread_current (); return (pagedir_get_page (t->pagedir, upage) == NULL && pagedir_set_page (t->pagedir, upage, kpage, writable)); }
bool page_load(struct page *p, void *fp_addr) { lock_acquire(&load); p->kpage = get_frame(PAL_USER); lock_release(&load); set_page_frame(p->kpage, p); pin_frame(p->kpage); if(p->kpage == NULL) { unpin_frame(p->kpage); return false; } bool temp = true; if(p->type == S) { temp = swap_load(p->kpage, p); } else if(p->type == F) { temp = file_load(p->kpage, p); } else { temp = zero_load(p->kpage); } if(!temp) { unpin_frame(p->kpage); return false; } pagedir_clear_page(p->dir, fp_addr); if(!pagedir_set_page(p->dir, fp_addr, p->kpage, p->write)) { unpin_frame(p->kpage); return false; } else if(!pagedir_get_page(p->dir, fp_addr)) { unpin_frame(p->kpage); return false; } p->load = true; pagedir_set_dirty(p->dir, fp_addr, false); pagedir_set_accessed(p->dir, fp_addr, true); unpin_frame(p->kpage); return true; }
static bool install_page (void *upage, void *kpage, bool writable) { struct thread *t = thread_current (); /* Verify that there's not already a page at that virtual address, then map our page there. */ return (pagedir_get_page (t->pagedir, upage) == NULL && pagedir_set_page (t->pagedir, upage, kpage, writable)); }
bool add_mapping(void *upage,void *kpage, bool writable,bool setdirty){ lock_acquire(&framelock); struct thread *t = thread_current (); /* Verify that there's not already a page at that virtual address, then map our page there. */ bool status= (pagedir_get_page (t->pagedir, upage) == NULL && pagedir_set_page (t->pagedir, upage, kpage, writable)); if(status){ if(setdirty) pagedir_set_dirty(t->pagedir,upage,true); add_list(kpage,upage); } lock_release(&framelock); return status; }
/* Adds a mapping from user virtual address UPAGE to kernel virtual address KPAGE to the page table. If WRITABLE is true, the user process may modify the page; otherwise, it is read-only. UPAGE must not already be mapped. KPAGE should probably be a page obtained from the user pool with palloc_get_page(). Returns true on success, false if UPAGE is already mapped or if memory allocation fails. */ bool install_page (void *upage, void *kpage, bool writable) { struct thread *t = thread_current (); /* Verify that there's not already a page at that virtual address, then map our page there. */ bool pageset = false; bool isnull = (pagedir_get_page (t->pagedir, upage) == NULL); if(isnull) pageset = pagedir_set_page (t->pagedir, upage, kpage, writable); if(DBG)printf("pageset boolean in install page = %d\n", pageset); if(DBG)printf("isnull boolean in install page = %d\n", isnull); return (isnull && pageset); }
static int sys_mmap( int fd, void *vaddr ) { struct thread *curr = thread_current(); struct list_elem *e; struct opened_file_elem *opened_elem; int check_valid = 0; int count = 0; // mmap_lock_acquire(); // printf("read bytes : %d\n",read_bytes); // printf("aa\n"); if(vaddr==0) { // mmap_lock_release(); return -1; } // printf("%p\n",(int)vaddr&0xfff); if( ((int)vaddr & 0xfff) !=0 || ( (int)vaddr>=PHYS_BASE -8*1024*1024 && (int)vaddr <=PHYS_BASE ) ) { // printf("misalign\n"); // mmap_lock_release(); return -1; } struct page *check_page = page_lookup(curr,vaddr); if( check_page!=NULL&& (check_page->writable == 0 || check_page->type==p_file) ) { // mmap_lock_release(); return -1; } if(fd<2) { // mmap_lock_release(); return -1; } for( e = list_begin(&curr->openfile_list) ; e != list_end(&curr->openfile_list) ; e = list_next(e) ) { opened_elem=list_entry(e,struct opened_file_elem,elem_f); if(opened_elem->fd==fd) { check_valid=1; break; } } if(check_valid==0) { // mmap_lock_release(); return -1; } for( e = list_begin(&curr->mapfile_list) ; e != list_end(&curr->mapfile_list) ; e = list_next(e) ) { // printf("check\n"); struct mapped_file_elem* mapped_elem=list_entry(e,struct mapped_file_elem,elem_m); // printf("%d\n",mapped_elem->size); if( mapped_elem->vaddr<=vaddr && vaddr<=mapped_elem->vaddr+mapped_elem->size) { // mmap_lock_release(); return -1; } } struct mapped_file_elem *mapped_elem = (struct mapped_file_elem*) malloc(sizeof(struct mapped_file_elem)); // char *name = (char*)malloc(strlen(opened_elem->name)); // strlcpy(name, opened_elem->name , strlen(opened_elem->name)+1); int read_bytes = file_length(opened_elem->opened_file); mapped_elem->mapped_file = opened_elem->opened_file; mapped_elem->vaddr = vaddr; mapped_elem->size = read_bytes; mapped_elem->mapid = opened_elem->fd; // mapped_elem->name = name; list_push_back(&curr->mapfile_list,&mapped_elem->elem_m); // printf("mapid: %d\n",opened_elem->mapid); while(read_bytes >0) { // frame_lock_acquire(); int page_read_bytes = read_bytes<PGSIZE ? read_bytes:PGSIZE; // printf("doing mmap\n"); // printf(" read bytes: %d\n",read_bytes); page_allocate(vaddr, true, p_mmap, page_read_bytes, PGSIZE-read_bytes, count*PGSIZE, mapped_elem->mapid); // printf("mapid : %d\n",page_lookup(curr,vaddr)->mapid); if(page_read_bytes < PGSIZE) { void *kpage=frame_elem_allocate(vaddr,true,PAL_USER); file_read_at( mapped_elem->mapped_file, kpage, page_read_bytes, count*PGSIZE ); pagedir_set_page( thread_current()->pagedir,vaddr,kpage,true ); } count+=1; read_bytes-=PGSIZE; vaddr+=PGSIZE; // frame_lock_release(); } // printf(" page allocate num:%d\n",count); // printf("mmap finish\n"); // mmap_lock_release(); return mapped_elem->mapid; }
static void sys_close(int fd) { struct thread *curr = thread_current(); struct list_elem *e; struct list_elem *e_m; struct opened_file_elem *opened_elem; struct mapped_file_elem *mapped_elem; int check_valid=0; int check_map=0; int check_frame=0; int count=0; // printf("close start\n"); if(fd<2) { lock_release(&process_lock); sys_exit(-1); } for( e = list_begin(&curr->openfile_list) ; e != list_end(&curr->openfile_list) ; e = list_next(e) ) { opened_elem=list_entry(e,struct opened_file_elem,elem_f); if(opened_elem->fd==fd) { check_valid=1; break; } } for( e_m = list_begin(&curr->mapfile_list) ; e_m != list_end(&curr->mapfile_list) ; e_m = list_next(e_m) ) { mapped_elem=list_entry(e_m,struct mapped_file_elem,elem_m); if(mapped_elem->mapid==fd) { check_map=1; break; } } // printf("%d clos!\n",fd); // printf("pick\n"); if(check_map!=0) { // printf("find\n"); struct hash_iterator i; hash_first(&i,&curr->pages); while(hash_next(&i)) { // printf("lazy mapping\n"); struct page *pa = hash_entry( hash_cur(&i), struct page, hash_elem); struct list_elem *e_f; struct frame_elem *f; if(pa->mapid == mapped_elem->mapid ) { for(e = list_begin( &frame_table ) ; e != list_end( &frame_table) ; e = list_next (e) ) { f = list_entry( e,struct frame_elem , elem); if(f->vaddr == pa->vaddr) { check_frame=1; break; } } if( check_frame==0 ) { int read_bytes = file_length(opened_elem->opened_file); // printf("adsfmlakdfmkl\n"); while(read_bytes>0) { // frame_lock_acquire(); int page_read_bytes = read_bytes<PGSIZE ? read_bytes:PGSIZE; void *kpage = frame_elem_allocate(pa->vaddr, true,PAL_USER|PAL_ZERO); pagedir_set_page(curr->pagedir, pa->vaddr, kpage, true); file_read_at( opened_elem->opened_file, kpage , page_read_bytes, pa->offset+count*PGSIZE); count+=1; read_bytes-=PGSIZE; // frame_lock_release(); } } } } } if(check_valid==1) { list_remove(&opened_elem->elem_f); file_close(opened_elem->opened_file); // free(opened_elem->name); free(opened_elem); } if(check_valid==0) { lock_release(&process_lock); sys_exit(-1); } // printf("close succeed\n"); }
/*! Obtains and returns a group of PAGE_CNT contiguous free pages starting at START_ADDR. If PAL_USER is set, the pages are obtained from the user pool, otherwise from the kernel pool. If PAL_ZERO is set in FLAGS, then the pages are filled with zeros. If PAL_PIN is set in FLGAS, then the pages are pinned. If too few pages are available, returns a null pointer, unless PAL_ASSERT is set in FLAGS, in which case the kernel panics. If LOAD_TYPE is ZERO_PAGE, then the page data pointer is set to NULL, otherwise it is set to the passed pointer DATA. If LOAD_TYPE is FILE_PAGE, the page's file offset is set to F_OFS. */ void *palloc_make_multiple_addr(void * start_addr, enum palloc_flags flags, size_t page_cnt, enum page_load load_type, void *data, void *f_ofs) { struct list *alloc_page_list; uint32_t i; struct thread *t = thread_current(); uint32_t *pagedir; uint32_t *pte; void *vaddr; void *curr_f_ofs = f_ofs; /* Page data should not be in a frame. */ if (load_type == FRAME_PAGE) { /* TODO: case where it is in a frame. */ ASSERT(false); } /* Use to correct pool based on whether it is paging data or not. */ if (flags & PAL_PAGING) { alloc_page_list = init_page_dir_sup; pagedir = init_page_dir; } else { alloc_page_list = &(t->page_entries); pagedir = t->pagedir; } /* If block at specified address is not open, return NULL. */ if (!palloc_block_open(start_addr, page_cnt)) { if (flags & PAL_ASSERT) { PANIC("palloc: out of pages"); } return NULL; } /* Allocate all pages for the block. */ for (i = 0; i < page_cnt; i++) { /* Create a supplemental entry for the page. */ struct page_entry *page_i = get_page_entry(); ASSERT (page_i != NULL); /* Get the virtual address for the page. */ vaddr = (uint8_t *) (start_addr + (i * PGSIZE)) + PGSIZE * 1000; /* Initialize the page. */ page_i->vaddr = vaddr; page_i->source = load_type; if (load_type == ZERO_PAGE) { page_i->data = NULL; } else { page_i->data = data; } if (load_type == FILE_PAGE) { /* Get the file offset. */ curr_f_ofs += PGSIZE; page_i->f_ofs = curr_f_ofs; } else { page_i->f_ofs = NULL; } /* Add to list of allocated pages in order by address. */ list_insert_ordered(alloc_page_list, &(page_i->elem), palloc_page_less, NULL); if (flags & PAL_USER) { pagedir_set_page(pagedir, vaddr, 0, !(flags & PAL_READO)); } else { if(!pagedir_set_page_kernel(pagedir, vaddr, 0, !(flags & PAL_READO))) { if (flags & PAL_ASSERT) { PANIC("palloc: out of pages"); } return NULL; } } pte = lookup_page(pagedir, vaddr, false); /* Pin the page if necessary. */ if (flags & PAL_PIN) { *pte = *pte | PTE_PIN; } } return start_addr; }