bool spage_table_load (struct spage_table_entry *spte, enum spage_types type) { // P3: reduce race condition with frame eviction process. spte->inevictable = true; if (spte->in_memory) return false; if (type == SWAP) { uint8_t *f = frame_alloc (PAL_USER, spte); if (!f) return false; if (!install_page (spte->upage, f, spte->writable)) { frame_free (f); return false; } swap_in (spte->swap_slot_id, spte->upage); spte->in_memory = true; } if (type == FILE || type == MMAP) { enum palloc_flags fg = PAL_USER; if (spte->file_read_bytes == 0) fg |= PAL_ZERO; uint8_t *f = frame_alloc (fg, spte); if (!f) return false; if (spte->file_read_bytes > 0) { lock_acquire (&lock_f); if ((int) spte->file_read_bytes != file_read_at (spte->file, f, spte->file_read_bytes, spte->file_offset)) { lock_release (&lock_f); frame_free (f); return false; } lock_release (&lock_f); memset (f + spte->file_read_bytes, 0, spte->file_zero_bytes); } if (!install_page (spte->upage, f, spte->writable)) { frame_free (f); return false; } spte->in_memory = true; } return true; }
/** * \page_load_demand * \Load page on demand (call only fault occurred) * * \param spte Supplemental page table that fault occurred * \param paddr physical address to be mapped * * \retval true if success * \retval false if failed */ bool page_load_demand (struct page_entry *spte, void *paddr) { /* Read read_bytes from offset written in spte */ if (file_read_at (spte->file, paddr, spte->read_bytes, spte->ofs) != (int) spte->read_bytes) return false; /* Add zero padding */ memset (paddr + spte->read_bytes, 0, spte->zero_bytes); /* Set this page is loaded in memory */ spte->is_loaded = true; /* Install vaddr and paddr mapping into pagedir */ return install_page (spte->vaddr, paddr, spte->writable); }
/*! Read from file */ int read(uint32_t fd, void *buffer, unsigned size) { uint8_t* addr_e; struct supp_table* st; /* Check the validity of given pointer */ if ((!checkva(buffer)) || (!checkva(buffer + size))){ exit(-1); } for (addr_e = (uint8_t*) pg_round_down(buffer); addr_e < (uint8_t*) buffer + size; addr_e += PGSIZE){ st = find_supp_table(addr_e); if (st && !st->writable) exit(-1); } int read_size = 0; if (fd == STDIN_FILENO) { /* If std-in, then read using input_getc() */ unsigned i; for (i = 0; i < size; i++){ *((uint8_t*) buffer) = input_getc(); ++ read_size; ++ buffer; } } else { /* Otherwise, first find the file of this fd. */ struct f_info* f = findfile(fd); /* We should read a dir like a file. */ if (f->isdir) exit(-1); struct file* fin = f->f; off_t pos = f->pos; /* Read from the file at f->pos */ //lock_acquire(&filesys_lock); read_size = (int) file_read_at(fin, buffer, (off_t) size, pos); f->pos += (off_t) read_size; //lock_release(&filesys_lock); } return read_size; }
/** * Loads the frame associated with the given virtual page with actual data either * from associated file or swapped disk or just zeroes */ bool load_frame_with_data (struct supplementary_page_table_entry *page) { // Allocate given supplementary page table entry -> a new physical memory frame page->supplementary_frame_in_memory = allot_frame_for_page_in_memory (page); // No frames are avaible - or unable to evict any frame if (page->supplementary_frame_in_memory == NULL) { return false; } // if this page is associated with any file if (page->sup_file != NULL) { // Read rw_bytes into the physical frame off_t read_bytes = file_read_at ( page->sup_file, page->supplementary_frame_in_memory->base_vir_address, page->rw_bytes, page->file_offset); // Copy this bytes into physical memory frame memset (page->supplementary_frame_in_memory->base_vir_address + read_bytes, 0, PGSIZE - read_bytes); if (read_bytes != page->rw_bytes) { printf ("the number of bytes read are (%"PROTd") != number of bytes " "requested are (%"PROTd")\n", read_bytes, page->rw_bytes); } // Else check if physical frame was swapped to disk } else if (page->area_swap != (block_sector_t) -1) { // If yes, swap it back into physical frame memory swap_page_in_from_disk_to_frame (page); // Else write zeroes to the frame memory } else { memset (page->supplementary_frame_in_memory->base_vir_address, 0, PGSIZE); } // Return the operation status - i.e. it was successful return true; }
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"); }