diff options
| author | Gustav Sörnäs <gustav@sornas.net> | 2021-03-12 16:13:28 +0100 |
|---|---|---|
| committer | Gustav Sörnäs <gustav@sornas.net> | 2021-03-12 16:13:28 +0100 |
| commit | 2c58ceb889efd1483f3986827134135d6d977a4a (patch) | |
| tree | 48a04d194701dd7683452906545d02c4efeecbcb | |
| parent | 915fb8305c47881142bd7a70982148ee14f8f6a2 (diff) | |
| download | pintos-2c58ceb889efd1483f3986827134135d6d977a4a.tar.gz | |
implement wait
| -rw-r--r-- | src/threads/thread.h | 5 | ||||
| -rw-r--r-- | src/userprog/process.c | 39 | ||||
| -rw-r--r-- | src/userprog/syscall.c | 12 |
3 files changed, 42 insertions, 14 deletions
diff --git a/src/threads/thread.h b/src/threads/thread.h index fdaba60..4b33d7d 100644 --- a/src/threads/thread.h +++ b/src/threads/thread.h @@ -30,10 +30,10 @@ struct parent_child { struct list_elem elem; // owned by the parent - // struct semaphore exit_sema; + struct semaphore exit_sema; + int exit_status; struct lock l; - int exit_status; int alive_count; tid_t child_tid; }; @@ -116,6 +116,7 @@ struct thread /* Owned by userprog/process.c. */ uint32_t *pagedir; /* Page directory. */ struct file **fds; /* Pointer to array of file descriptors. */ + bool load_success; struct parent_child *parent; // one parent struct list children; // multiple children diff --git a/src/userprog/process.c b/src/userprog/process.c index 589b48b..fadd14d 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -93,11 +93,12 @@ start_process (void *args_) if_.eflags = FLAG_IF | FLAG_MBS; success = load (args->file_name, &if_.eip, &if_.esp); args->success = success; + t->load_success = success; if (success) { t->parent = malloc (sizeof (struct parent_child)); - // sema_init (&t->parent.exit_sema, 0); + sema_init (&t->parent->exit_sema, 0); lock_init (&t->parent->l); t->parent->child_tid = t->tid; @@ -132,9 +133,22 @@ start_process (void *args_) This function will be implemented in problem 2-2. For now, it does nothing. */ int -process_wait (tid_t child_tid UNUSED) +process_wait (tid_t child_tid) { - for (;;) {} + struct thread *t = thread_current (); + struct list_elem *e; + for (e = list_begin (&t->children); e != list_end (&t->children); + e = list_next (e)) + { + struct parent_child *pc = list_entry (e, struct parent_child, elem); + if (child_tid == pc->child_tid) { + sema_down (&pc->exit_sema); + int exit_status = pc->exit_status; + pc->exit_status = -1; + return exit_status; + } + } + return -1; } static void @@ -157,14 +171,18 @@ process_exit (void) struct thread *cur = thread_current (); uint32_t *pd; - free_pc (cur->parent); + if (cur->load_success) { + sema_up (&cur->parent->exit_sema); + free_pc (cur->parent); + printf("%s: exit(%d)\n", cur->name, cur->parent->exit_status); - struct list_elem *e; - struct parent_child *child; - while (!list_empty (&cur->children)) { - e = list_pop_front (&cur->children); - child = list_entry (e, struct parent_child, elem); - free_pc (child); + struct list_elem *e; + struct parent_child *child; + while (!list_empty (&cur->children)) { + e = list_pop_front (&cur->children); + child = list_entry (e, struct parent_child, elem); + free_pc (child); + } } /* Destroy the current process's page directory and switch back @@ -318,6 +336,7 @@ load (const char *file_name, void (**eip) (void), void **esp) } file_name = esp_cmd; + strlcpy (thread_current ()->name, file_name, 16); /* argv entries are pointers so they need to be aligned to the pointer size. */ size_t psize = sizeof (char *); diff --git a/src/userprog/syscall.c b/src/userprog/syscall.c index 177cf02..52526aa 100644 --- a/src/userprog/syscall.c +++ b/src/userprog/syscall.c @@ -88,12 +88,16 @@ exit (int status) thread->parent->exit_status = status; lock_release (&thread->parent->l); - printf("%s: exit(%d)\n", thread->name, status); - thread_exit (); } static int +wait (tid_t child_tid) +{ + return process_wait (child_tid); +} + +static int read (int fd_i, void *buf, unsigned size) { struct thread *thread = thread_current (); @@ -178,6 +182,10 @@ syscall_handler (struct intr_frame *f UNUSED) // exec f->eax = exec (INTR_ESP (1, char *)); break; + case 3: + // wait + f->eax = wait (INTR_ESP (1, tid_t)); + break; case 4: // create f->eax = create (INTR_ESP (1, char *), INTR_ESP (2, off_t)); |
