void str_free(string_ty *s) { str_hash_ty idx; string_ty **spp; assert(str_valid(s)); if (s->str_references > 1) { s->str_references--; return; } assert(s->str_references == 1); /* * find the hash bucket it was in, * and remove it */ idx = s->str_hash & hash_mask; assert(idx < hash_modulus); for (spp = &hash_table[idx]; *spp; spp = &(*spp)->str_next) { if (*spp == s) { *spp = s->str_next; free(s); --hash_load; return; } } /* should never reach here! */ fatal_raw("attempted to free non-existent string (bug)"); }
static void syscall_handler (struct intr_frame *f) { /* Validate the first addr of the stack frame */ void *esp = utok_addr (f->esp, NULL); if (esp == NULL) { syscall_exit (-1); return; } enum SYSCALL_NUMBER call_number = *(enum SYSCALL_NUMBER *) esp; if (call_number < syscall_first_call || call_number > syscall_last_call) { syscall_exit (-1); return; } /* Buffer the arguments for validation */ int argc = syscall_argc[call_number]; uint32_t argbuf[3]; int i = 0; for (; i < argc; i++) { /* Validate each argument */ void *vaddr = uptr_valid((uint32_t *) f->esp + 1 + i, f->esp); if (vaddr == NULL) { syscall_exit (-1); return; } /* Translate the argument to kernel virtual (== physical) memory */ argbuf[i] = *(uint32_t *) vaddr; } int retval = 0; /* Switch based on call_number to delegate to corresponding syscall. Have not implemented several syscalls as of this project. Use validation methods to check user-provided arguments. */ switch (call_number) { case SYS_HALT: syscall_halt (); break; case SYS_EXIT: syscall_exit ((int) argbuf[0]); break; case SYS_EXEC: if (str_valid ((void *) argbuf[0], f->esp) == NULL) { syscall_exit (-1); return; } retval = syscall_exec ((char *) argbuf[0]); break; case SYS_WAIT: retval = syscall_wait ((int) argbuf[0]); break; case SYS_CREATE: if (str_valid ((char *) argbuf[0], f->esp) == NULL) { syscall_exit (-1); return; } retval = (int) syscall_create ((char *) argbuf[0], (unsigned) argbuf[1]); break; case SYS_REMOVE: if (!uptr_valid ((char *) argbuf[0], f->esp)) { syscall_exit (-1); return; } retval = (int) syscall_remove ((char *) argbuf[0]); break; case SYS_OPEN: if (str_valid ((char *) argbuf[0], f->esp) == NULL) { syscall_exit (-1); return; } retval = (int) syscall_open ((char *) argbuf[0]); break; case SYS_FILESIZE: retval = syscall_filesize ((int) argbuf[0]); break; case SYS_READ: if (buffer_valid ((void *) argbuf[1], f->esp, (unsigned) argbuf[2]) == NULL) { syscall_exit (-1); return; } retval = syscall_read ((int) argbuf[0], (void *) argbuf[1], (unsigned) argbuf[2]); break; case SYS_WRITE: if (buffer_valid ((void *) argbuf[1], f->esp, (unsigned) argbuf[2]) == NULL) { syscall_exit (-1); return; } retval = syscall_write ((int) argbuf[0], (void *) argbuf[1], (unsigned) argbuf[2]); break; case SYS_SEEK: syscall_seek ((int) argbuf[0], (unsigned) argbuf[1]); break; case SYS_TELL: retval = (int) syscall_tell ((int) argbuf[0]); break; case SYS_CLOSE: syscall_close ((int) argbuf[0]); break; #ifdef VM case SYS_MMAP: // addr will be checked internally inside mmap retval = (int) syscall_mmap ((int) argbuf[0], (void *) argbuf[1]); break; case SYS_MUNMAP: syscall_munmap ((int) argbuf[0]); break; #endif default: printf("unhandled system call!\n"); thread_exit(); } f->eax = retval; }