struct frame_table_entry* frame_get_new_page (bool zero){ uint8_t *kpage; struct frame_table_entry *fte = NULL; redo: if(zero){ kpage = palloc_get_page (PAL_USER|PAL_ZERO); }else{ kpage = palloc_get_page (PAL_USER); } if(kpage!=NULL){ ASSERT (is_kernel_vaddr (kpage)); /* * TODO: * add new page into frame control here, * after all info be recorded, return the * page table entry. uaddr should be added * by latter... */ fte = malloc(sizeof(struct frame_table_entry)); fte->kpg_vaddr = kpage; fte->owner = thread_current(); fte->pinned = true; list_push_back (&frame_table, &fte->elem); // printf("thread %d released frame_lock\n",thread_current()->tid); return fte; }else{ //evict a page to swap(0) frame_evict_page(); goto redo; } }
/** * An (internal, private) method -- * Deallocates a frame or page (internal procedure) * MUST BE CALLED with 'frame_lock' held. */ void vm_frame_do_free (void *kpage, bool free_page) { ASSERT (lock_held_by_current_thread(&frame_lock) == true); ASSERT (is_kernel_vaddr(kpage)); ASSERT (pg_ofs (kpage) == 0); // should be aligned // hash lookup : a temporary entry struct frame_table_entry f_tmp; f_tmp.kpage = kpage; struct hash_elem *h = hash_find (&frame_map, &(f_tmp.helem)); if (h == NULL) { PANIC ("The page to be freed is not stored in the table"); } struct frame_table_entry *f; f = hash_entry(h, struct frame_table_entry, helem); hash_delete (&frame_map, &f->helem); list_remove (&f->lelem); // Free resources if(free_page) palloc_free_page(kpage); free(f); }
struct frame* frame_table_set (void* upage, void* kpage){ struct frame* frame_new; ASSERT(is_user_vaddr(upage)); ASSERT(is_kernel_vaddr(kpage)); // TODO: now, frame_find also use frame_lock. This is bad for speed // if kpage frame is already exist, go to else statement lock_acquire(&frame_lock); if(!frame_find(kpage)){ frame_new = malloc(sizeof(struct frame)); frame_new->process = thread_current(); frame_new->upage = (void*)((int)upage&PAGE_MASK); frame_new->kpage = (void*)((int)kpage&PAGE_MASK); list_push_back(&frame_table, &(frame_new->table_elem)); //printf("**** [frame_table_set] frame '%x', upage '%x', kpage '%x'\n",frame_new, frame_new->upage, frame_new->kpage); lock_release(&frame_lock); return frame_new; } else{ lock_release(&frame_lock); return NULL; } }
static void syscall_handler (struct intr_frame *f) { int32_t* esp = (int32_t*)f->esp; /* Any parameters passed to syscall will be above ESP, see illustration below. Number of arguments each syscall expects is in argc[] array above. syscall number is pointed to by ESP. -------------------------------------- PHYS_BASE ................. <param> <param> ESP ---> <syscall_number> -------------------------------------- */ // verify esp pointer is ok, first parameter: current thread if(esp == NULL || verify_fix_length(esp, sizeof(esp)) == false){ sys_exit(-1); } // esp adress belongs to thread if(pagedir_get_page(thread_current()->pagedir, esp) == NULL){ sys_exit(-1); } // ok syscall nr int32_t syscall_nr = *esp; if(syscall_nr < 0 || syscall_nr >= SYS_NUMBER_OF_CALLS){ sys_exit(-1); } // Make sure our data is not overwriting PHYS_BASE. int expected_args = argc[syscall_nr]; unsigned long highest_addr = esp + (expected_args * sizeof(int)); if(highest_addr >= PHYS_BASE){ sys_exit(-1); } if(pagedir_get_page(thread_current()->pagedir, highest_addr) == NULL){ sys_exit(-1); } /* int i = 1; for(; i <= expected_args; i++){ if(verify_fix_length(&esp[i], sizeof(int) ) == false){ sys_exit(-1); } } */ DEBUG_SYSCALL("# SYSCALL received = %s\n", get_system_call_name(syscall_nr)); switch (syscall_nr) { case SYS_HALT: power_off(); break; case SYS_EXEC: { f->eax = SYS_EXEC_handler(esp); } break; case SYS_WAIT: { int child_pid = *(esp + 1); f->eax = process_wait (child_pid); break; } case SYS_EXIT: { if(is_kernel_vaddr(pg_round_up((void*)esp[1]) )){ sys_exit(-1); } int exit_status = *(esp + 1); process_exit(exit_status); thread_exit(); break; } case SYS_PLIST: process_print_list(); break; case SYS_CREATE: { bool success = false; char *name = (char*)*(esp + 1); if(name == NULL){ sys_exit(-1); } unsigned initial_size = *(esp + 2); if(verify_fix_length(esp[1], initial_size) == false){ sys_exit(-1); } if(verify_variable_length(esp[1]) == false){ sys_exit(-1); } success = filesys_create(name, initial_size); if(success) { DEBUG_SYSCALL("#SYS_CREATE - File with name: %s created. \n", name); } else { DEBUG_SYSCALL("#SYS_CREATE - filesys_create failed: file named \'%s\' already exists or internal memory allocation failed \n", name); } f->eax = success; break; } case SYS_OPEN: { char *name = (char*)*(esp + 1); if(name == NULL){ sys_exit(-1); } if(verify_variable_length(esp[1]) == false){ sys_exit(-1); } struct file *file; file = filesys_open(name); int retVal = -1; if(file != NULL) { DEBUG_SYSCALL("# SYS_OPEN - File with name: '%s' created. \n", name); int fd = flist_add_file(file); retVal = fd; } else { DEBUG_SYSCALL("# SYS_OPEN - filesys_open failed: no file named \'%s\' exists or internal memory allocation failed \n", name); retVal = -1; } f->eax = retVal; break; } case SYS_READ: { int retVal = SYS_READ_handler(esp); f->eax = retVal; break; } case SYS_CLOSE: { int retVal = SYS_CLOSE_handler(esp); f->eax = retVal; break; } case SYS_REMOVE: { int retVal = SYS_REMOVE_handler(esp); f->eax = retVal; break; } case SYS_WRITE: { int retVal = SYS_WRITE_handler(esp); f->eax = retVal; break; } case SYS_SEEK: { f->eax = SYS_SEEK_handler(esp); break; } case SYS_TELL: f->eax = SYS_TELL_handler(esp); break; case SYS_FILESIZE: f->eax = SYS_FILESIZE_handler(esp); break; default: { DEBUG_SYSCALL ("Executed an unknown system call (nr: %i)!\n", syscall_nr); DEBUG_SYSCALL ("Stack top + 0: %d\n", esp[0]); DEBUG_SYSCALL ("Stack top + 1: %d\n", esp[1]); thread_exit (); } } }