From 2c58ceb889efd1483f3986827134135d6d977a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Fri, 12 Mar 2021 16:13:28 +0100 Subject: implement wait --- src/userprog/process.c | 39 +++++++++++++++++++++++++++++---------- src/userprog/syscall.c | 12 ++++++++++-- 2 files changed, 39 insertions(+), 12 deletions(-) (limited to 'src/userprog') 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,11 +88,15 @@ 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) { @@ -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)); -- cgit v1.2.1