summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustav Sörnäs <gustav@sornas.net>2021-03-12 16:13:28 +0100
committerGustav Sörnäs <gustav@sornas.net>2021-03-12 16:13:28 +0100
commit2c58ceb889efd1483f3986827134135d6d977a4a (patch)
tree48a04d194701dd7683452906545d02c4efeecbcb
parent915fb8305c47881142bd7a70982148ee14f8f6a2 (diff)
downloadpintos-2c58ceb889efd1483f3986827134135d6d977a4a.tar.gz
implement wait
-rw-r--r--src/threads/thread.h5
-rw-r--r--src/userprog/process.c39
-rw-r--r--src/userprog/syscall.c12
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));