diff --git a/src/threads/thread.h b/src/threads/thread.h index c1e7aabf2019e439c3433ecd8268c357a68ff7eb..f5988dacd053e53c60127da18d60d8655ebe8ca7 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -96,6 +96,9 @@ struct thread #ifdef USERPROG /* Owned by userprog/process.c. */ uint32_t *pagedir; /* Page directory. */ + uint8_t *current_esp; /* The current value of the user program’s stack pointer. + A page fault might occur in the kernel, so we might + need to store esp on transition to kernel mode*/ #endif /* Owned by thread.c. */ diff --git a/src/userprog/process.c b/src/userprog/process.c index 859343107d05d4cc54dfa2101b6bb39c676941e7..e0f44086d4f4b6b53d10aafe4fae0993b4308a0d 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -45,7 +45,7 @@ process_execute(const char *file_name) /* Parse first argument as program name */ strlcpy(program, file_name, file_name_length); strtok_r(program, " ", &ptr); - printf("\nProgram name: %s\n", program) ; + printf("\nProgram name: %s\n\n", program) ; /* Create a new thread to execute FILE_NAME. */ tid = thread_create(file_name, PRI_DEFAULT, start_process, file_copy); diff --git a/src/userprog/syscall.c b/src/userprog/syscall.c index 04635159d30520fa11296dc922e622f2ad2553d5..e32359c44826fcfd461f22eaa1c6298b568df68c 100644 --- a/src/userprog/syscall.c +++ b/src/userprog/syscall.c @@ -1,4 +1,5 @@ #include "userprog/syscall.h" +#include <stdbool.h> #include <stdio.h> #include <syscall-nr.h> #include "threads/interrupt.h" @@ -6,16 +7,135 @@ static void syscall_handler (struct intr_frame *); +/*System call initializer*/ void syscall_init (void) { intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); } - +/*Handler for system commands.*/ static void syscall_handler (struct intr_frame *f UNUSED) { - printf ("system call!\n"); - thread_exit (); + /* References: J,Choi(2014), pintos. Available from: https://github.com/wookayin/pintos [accessed on 27/11/22]*/ + int syscall_number; + ASSERT( sizeof(syscall_number) == 4 ); /*assuming x86*/ + + /*The system call number is in the 32-bit word at the caller's stack pointer.*/ + read(f->esp, &syscall_number, sizeof(syscall_number)); + + /*Store the esp, which is needed in the page fault handler.*/ + thread_current()->current_esp = f->esp; + + switch (syscall_number) { + case SYS_HALT: // 0 + { + /*Terminate PintOS*/ + syscall_halt(); + break; + } + case SYS_WAIT: // 2 + { + tid_t tid; + /*Get argument*/ + read(f->esp + 4, &tid, sizeof(tid_t)); + /*Wait for child process*/ + f->eax = syscall_wait(tid); + break; + } + + case SYS_CREATE: // 3 + { + const char* file_name; + unsigned initial_size; + + /*Get file name and size*/ + read(f->esp + 4, &file_name, sizeof(file_name)); + read(f->esp + 8, &initial_size, sizeof(initial_size)); + + /*Create file*/ + f->eax = syscall_create(file_name, initial_size); + break; + } + + case SYS_REMOVE: // 4 + { + const char* file_name; + bool return_code; + + /*Get file name*/ + read(f->esp + 4, &file_name, sizeof(file_name)); + + /*Remove file*/ + f->eax = syscall_remove(file_name); + break; + } + /* Unimplemented system calls */ + default: + printf("ERROR: system call ( %d ) has not implemented!\n", syscall_number); + + /* Terminate. */ + syscall_exit(-1); + break; + } +} + + +/********SYSTEMCALLS********/ + +/* Halt */ +void syscall_halt(void) { + shutdown_power_off(); /* From shutdown.h */ +} + +/* Exit */ +void syscall_exit(int status) { + struct thread *current_process=thread_current(); + current_process->process_exit_status = status; + + printf("%s: exit(%d)\n",current_process->name,status); + + thread_exit(); +} + +/* Wait */ +int syscall_wait(tid_t tid) +{ + return process_wait(tid); +} + +/* Create File */ +bool syscall_create(const char* file_name, unsigned initial_size) { + bool if_created = false; + if( filesys_create(file_name, initial_size)==true){ + if_created = true; + } + return if_created; +} + +/* Remove File */ +bool syscall_remove(const char* file_name) { + bool if_removed = false; + if( filesys_remove(file_name)==true){ + if_removed = true; + } + return if_removed; +} + + +/****OTHER FUNCTIONS****/ +static int read(void *src, void *dst, size_t bytes) +{ + int32_t value; + size_t i; + for (i = 0; i < bytes; i++) + { + value = get_user(src + i); + if (value == -1) // segfault or invalid memory access + fail_invalid_access(); + + *(char *)(dst + i) = value & 0xff; + } + return (int)bytes; } diff --git a/src/userprog/syscall.h b/src/userprog/syscall.h index 90590967a9f96f9ea359d15c672b815dfb4379cb..7289c248f8d431828c0ef068ade6c810cf1fb974 100644 --- a/src/userprog/syscall.h +++ b/src/userprog/syscall.h @@ -1,6 +1,17 @@ #ifndef USERPROG_SYSCALL_H #define USERPROG_SYSCALL_H +#include "threads/thread.h" +#include <stdbool.h> +#include <stddef.h> void syscall_init (void); +void syscall_halt(void); +void syscall_exit(int status); +int syscall_wait(tid_t tid); +bool syscall_create(const char* file_name, unsigned initial_size); +bool syscall_remove(const char* file_name); + +static int read(void *src, void *dst, size_t bytes); + #endif /* userprog/syscall.h */