diff --git a/src/threads/thread.c b/src/threads/thread.c index 052302f8d417bbcce955ae4216fc297d956316a6..1b8407b1d072f7eafb977925b2a347b115bc655e 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -59,7 +59,8 @@ static unsigned thread_ticks; /* # of timer ticks since last yield. */ If true, use multi-level feedback queue scheduler. Controlled by kernel command-line option "-o mlfqs". */ bool thread_mlfqs; - +/* file descriptor lock */ +struct lock file_lock; static void kernel_thread (thread_func *, void *aux); static void idle (void *aux UNUSED); @@ -179,6 +180,7 @@ thread_create (const char *name, int priority, struct switch_entry_frame *ef; struct switch_threads_frame *sf; tid_t tid; + enum intr_level old_level; ASSERT (function != NULL); @@ -191,6 +193,11 @@ thread_create (const char *name, int priority, init_thread (t, name, priority); tid = t->tid = allocate_tid (); + /* Prepare thread for first run by initializing its stack. + Do this atomically so intermediate values for the 'stack' + member cannot be observed. */ + old_level = intr_disable (); + /* Stack frame for kernel_thread(). */ kf = alloc_frame (t, sizeof *kf); kf->eip = NULL; @@ -206,6 +213,21 @@ thread_create (const char *name, int priority, sf->eip = switch_entry; sf->ebp = 0; + intr_set_level (old_level); + /* Set Value */ + t->next_fd = 2; + t->file_descriptor = palloc_get_page(0); + if(t->file_descriptor == NULL) + return TID_ERROR; + t->childelem.next = NULL; + t->childelem.prev = NULL; + t->parent_thread = thread_current(); + t->load_success = false; + t->process_exit = false; + sema_init(&(t->load_semaphore),0); + sema_init(&(t->exit_semaphore),0); + list_push_back(&(thread_current()->child_list),&(t->childelem)); + /* Add to run queue. */ thread_unblock (t); diff --git a/src/threads/thread.h b/src/threads/thread.h index f5988dacd053e53c60127da18d60d8655ebe8ca7..e814f6b029d3a8eeabeb42a9f45be0b9306c54dd 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -81,8 +81,9 @@ typedef int tid_t; ready state is on the run queue, whereas only a thread in the blocked state is on a semaphore wait list. */ struct thread - { +{ /* Owned by thread.c. */ + struct list_elem childelem; tid_t tid; /* Thread identifier. */ enum thread_status status; /* Thread state. */ char name[16]; /* Name (for debugging purposes). */ @@ -104,9 +105,16 @@ struct thread /* Owned by thread.c. */ unsigned magic; /* Detects stack overflow. */ /* VALUE */ - bool process_exit; - int process_exit_status; - }; + struct file **file_descriptor; + int next_fd; + bool load_success; + bool process_exit; + int process_exit_status; + struct semaphore load_semaphore; + struct semaphore exit_semaphore; + struct thread *parent_thread; + struct list child_list; +}; /* If false (default), use round-robin scheduler. If true, use multi-level feedback queue scheduler. diff --git a/src/userprog/process.c b/src/userprog/process.c index e0f44086d4f4b6b53d10aafe4fae0993b4308a0d..4cbf0d6cb876caec341ecc27dc893e08b5edcb76 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -20,7 +20,8 @@ static thread_func start_process NO_RETURN; static bool load(const char *cmdline, void (**eip)(void), void **esp); -static void argument_pushing(char **parse, int count, void **esp); + + #define WORD_SIZE 4 /* Starts a new thread running a user program loaded from @@ -56,7 +57,78 @@ process_execute(const char *file_name) } return tid; } - +/* add file to file descriptor */ +int process_add_file(struct file *f) +{ + struct file **fd = NULL; + int nextFd; + + fd = thread_current()->file_descriptor; + nextFd = thread_current()->next_fd; + + if(fd != NULL) + { + fd[nextFd] = f; + thread_current()->next_fd = thread_current()->next_fd+1; + return nextFd; + } + else + { + return -1; + } +} +/* get struct file */ +struct file *process_get_file(int fd) +{ + struct file *pReturn; + if(fd < thread_current()->next_fd) + { + pReturn = thread_current()->file_descriptor[fd]; + return pReturn; + } + else + { + return NULL; + } +} +/* close file function */ +void +process_close_file(int fd) +{ + struct file *delete_file; + delete_file = process_get_file(fd); + if(delete_file != NULL) + { + file_close(delete_file); + thread_current()->file_descriptor[fd] = NULL; + } +} +/* get_child_process */ +struct thread *get_child_process(int pid) +{ + struct list *child_list=&(thread_current()->child_list); + struct thread *child_process = NULL; + struct list_elem *element; + + /* find child process and return */ + for(element=list_begin(child_list); element != list_end(child_list); element=list_next(element)) + { + child_process = list_entry(element,struct thread,childelem); + if(child_process->tid == pid) + return child_process; + } + return NULL; +} +/* remove_child_process */ +void +remove_child_process(struct thread *cp) +{ + if(cp != NULL) + { + list_remove(&(cp->childelem)); + palloc_free_page(cp); + } +} /* A thread function that loads a user process and starts it running. */ static void @@ -88,8 +160,9 @@ start_process(void *file_name_) success = load(parse[0], &if_.eip, &if_.esp); argument_pushing(&parse, count, &if_.esp); + sema_up(&(thread_current()->load_semaphore)); - hex_dump(if_.esp, if_.esp, PHYS_BASE - if_.esp, true); + //hex_dump(if_.esp, if_.esp, PHYS_BASE - if_.esp, true); /* If load failed, quit. */ palloc_free_page(file_name); @@ -451,7 +524,7 @@ load_segment(struct file *file, off_t ofs, uint8_t *upage, return true; } /* References: J,Choi(2014), pintos. Available from: https://github.com/wookayin/pintos [accessed on 23/11/22]*/ -static void +void argument_pushing(char **parse, int count, void **esp) { int i, j; @@ -490,13 +563,13 @@ argument_pushing(char **parse, int count, void **esp) for (i = count - 1; i >= 0; i--) { *esp -= 4; - **(char ***)esp = address[i]; + **(char* **)esp = (char *)address[i]; } /* Set **argv*/ parse0_address = *(unsigned int *)esp; *esp -= 4; - **(char ***)esp = (char *)parse0_address; + **(char* **)esp = (char *)parse0_address; /* Set counter*/ *esp -= 4; @@ -547,3 +620,4 @@ install_page(void *upage, void *kpage, bool writable) } //-------------------------------------------------------------------- + diff --git a/src/userprog/process.h b/src/userprog/process.h index ee8fcf40271ae0bdd733b90d329680cb353ae6ac..86a806dc09e0688efb6bc763eca485a520dada1a 100644 --- a/src/userprog/process.h +++ b/src/userprog/process.h @@ -2,15 +2,21 @@ #define USERPROG_PROCESS_H #include "threads/thread.h" -typedef int pid_t; -typedef int pit_t; -#define PID_ERROR ((pid_t)-1) -#define PID_INITIALIZING ((pid_t) -2) +void argument_pushing(char **parse, int count, void **esp); + +struct thread *get_child_process(int pid); +void remove_child_process(struct thread *cp); +int process_add_file(struct file *f); +struct file *process_get_file(int fd); +void process_close_file(int fd); +void process_exit(void); tid_t process_execute (const char *file_name); int process_wait (tid_t); void process_exit (void); void process_activate (void); + + #endif /* userprog/process.h */ diff --git a/src/userprog/syscall.c b/src/userprog/syscall.c index b83df34cdde93ff78cb1ca37503ddd0304cbb68f..01b74aa46b511befc920115d350c5e596b7e2599 100644 --- a/src/userprog/syscall.c +++ b/src/userprog/syscall.c @@ -5,6 +5,11 @@ #include "threads/interrupt.h" #include "threads/thread.h" #include "threads/vaddr.h" +#include <devices/shutdown.h> +#include <filesys/filesys.h> +#include <filesys/file.h> +#include <userprog/process.h> +#include <devices/input.h> static void syscall_handler (struct intr_frame *); @@ -19,59 +24,41 @@ syscall_init (void) static void syscall_handler (struct intr_frame *f UNUSED) { - /* 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*/ + int argument[5]; + void *esp = f->esp; - /*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; + check_address(esp); + syscall_number = *(int *)esp; switch (syscall_number) { - case SYS_HALT: // 0 - { + case SYS_HALT: // 0 /*Terminate PintOS*/ syscall_halt(); break; - } + case SYS_EXIT: //1 + get_argument(esp,argument,1); + syscall_exit(argument[0]); + 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); + get_argument(esp,argument,1); + f->eax = syscall_wait(argument[0]); 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); + get_argument(esp,argument,2); + check_address((void *)argument[0]); + f->eax = syscall_create((const char *)argument[0],(unsigned)argument[1]); 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; - } + get_argument(esp,argument,1); + check_address((void *)argument[0]); + f->eax=syscall_remove((const char *)argument[0]); + break; + case SYS_WRITE: //5 + get_argument(esp,argument,3); + check_address((void *)argument[1]); + f->eax = syscall_write(argument[0],(void *)argument[1],(unsigned)argument[2]); + break; /* Unimplemented system calls */ default: printf("ERROR: system call ( %d ) has not implemented!\n", syscall_number); @@ -124,31 +111,52 @@ bool syscall_remove(const char* file_name) { return if_removed; } - +/* write file */ +int syscall_write(int fd, void *buffer, unsigned size) +{ + int write_size = 0; + struct file *current_file; + + if(fd == 1) /*stdout */ + { + putbuf((const char *)buffer,size); + write_size = size; + } + else + { + current_file = process_get_file(fd); + if(current_file != NULL) + write_size = file_write(current_file,(const void *)buffer,size); + } + return write_size; +} /****OTHER FUNCTIONS****/ -static int read(void *src, void *dst, size_t bytes) +void +check_address(void *addr) { - 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 - *(char *)(dst + i) = value & 0xff; - } - return (int)bytes; + uint32_t address=(unsigned int)addr; + + uint32_t lowest=0x8048000; + uint32_t highest=0xc0000000; + if(address >= lowest && address < highest){ + return; + } + else{ + syscall_exit(-1); + } } -/* Reads a byte at user virtual address UADDR. - UADDR must be below PHYS_BASE. - Returns the byte value if successful, -1 if a segfault - occurred. */ -static int -get_user (const uint8_t *uaddr) +/* get_argument function */ +void +get_argument(void *esp, int *argument, int count) { - if(!is_user_vaddr(uaddr)) - return -1; - int result; - asm ("movl $1f, %0; movzbl %1, %0; 1:" - : "=&a" (result) : "m" (*uaddr)); - return result; -} + int i; + void *stack_ptr=esp+4; + if(count > 0) + { + for(i=0; i<count; i++){ + check_address(stack_ptr); + argument[i] = *(int *)stack_ptr; + stack_ptr = stack_ptr + 4; + } + } +} \ No newline at end of file diff --git a/src/userprog/syscall.h b/src/userprog/syscall.h index e672e2a04c18790f9f4f2cc808450356061792e5..341169bd8b80edcbcce2148715e4dcf43614c3b9 100644 --- a/src/userprog/syscall.h +++ b/src/userprog/syscall.h @@ -9,21 +9,15 @@ #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); -static int get_user (const uint8_t *uaddr); +void check_address(void *addr); +void get_argument(void *esp, int *arg, int count); 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); +int syscall_write(int fd, void *buffer, unsigned size); #endif /* userprog/syscall.h */