diff --git a/src/userprog/process.c b/src/userprog/process.c index 27a46ba..fb421c5 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -47,6 +47,9 @@ struct process_start_data tokens while maintaining state. */ char file_name[FNAME_MAX_LEN + 1]; /* Name of the file of the process to be started. */ + struct semaphore load_sema; + + bool success; }; static thread_func start_process NO_RETURN; @@ -62,11 +65,7 @@ process_execute (const char *cmd) char *cmd_copy; tid_t tid; - struct process_start_data *data = malloc (sizeof (struct process_start_data)); - if (data == NULL) - { - return TID_ERROR; - } + struct process_start_data data; /* Make a copy of command. Otherwise there's a race between the caller and load(). */ @@ -80,7 +79,7 @@ process_execute (const char *cmd) /* Retrieve first argument of command, which is the file name of the process. */ - char *file_name = strtok_r (cmd_copy, " ", &data->cmd_saveptr); + char *file_name = strtok_r (cmd_copy, " ", &data.cmd_saveptr); /* NOTE: Currently, the file being executed is closed in load () and then reopened here. Because load is an exported public function, this @@ -95,12 +94,24 @@ process_execute (const char *cmd) /* Create a new thread to execute the command, by initializing it running the function 'start_process' with the appropriate arguments. For details of arguments, see 'start_process'. */ - data->cmd = cmd_copy; - strlcpy (data->file_name, file_name, FNAME_MAX_LEN + 1); + data.cmd = cmd_copy; + strlcpy (data.file_name, file_name, FNAME_MAX_LEN + 1); + sema_init (&data.load_sema, 0); + data.success = false; + + tid = thread_create (file_name, PRI_DEFAULT, start_process, &data); - tid = thread_create (file_name, PRI_DEFAULT, start_process, data); if (tid == TID_ERROR) - palloc_free_page (cmd_copy); + { + palloc_free_page (cmd_copy); + } + else + { + sema_down (&data.load_sema); + if (!data.success) + tid = TID_ERROR; + } + return tid; } @@ -118,7 +129,6 @@ static void start_process (void *proc_start_data) { struct intr_frame if_; - bool success; struct process_start_data *data = proc_start_data; @@ -136,21 +146,22 @@ start_process (void *proc_start_data) file_deny_write (exec_file); lock_release (&filesys_lock); - success = load (data->file_name, &if_.eip, &if_.esp); + data->success = load (data->file_name, &if_.eip, &if_.esp); /* If load failed, free process startup data and quit. */ - if (!success) + if (!data->success) { palloc_free_page (data->cmd); - free (data); + sema_up (&data->load_sema); thread_exit (); } /* Initialize user process stack and free page used to store the command that executed the process. */ - success = process_init_stack (data->cmd_saveptr, &if_.esp, data->file_name); + bool success = process_init_stack (data->cmd_saveptr, &if_.esp, data->file_name); palloc_free_page (data->cmd); - free (data); + data->success = success; + sema_up (&data->load_sema); /* If stack initialization failed, free process resources and quit. */ if (!success) @@ -297,7 +308,6 @@ process_wait (tid_t child_tid UNUSED) } if (child_result == NULL) { - printf ("-1 due to: child_result == NULL\n"); return -1; } /* Wait for child to die. */ @@ -314,11 +324,6 @@ process_wait (tid_t child_tid UNUSED) lock_release (&child_result->lock); free (child_result); - if (exit_status == -1) - { - printf ("-1 due to: child exit status wrong!\n"); - } - return exit_status; } @@ -327,16 +332,15 @@ void process_exit (void) { - printf("(%d) EXIT STATUS: %d\n", thread_current ()->tid, thread_current ()->exit_status); struct thread *cur = thread_current (); uint32_t *pd; printf ("%s: exit(%d)\n", cur->name, cur->exit_status); + if (cur->exec_file != NULL) { lock_acquire (&filesys_lock); - file_allow_write (cur->exec_file); file_close (cur->exec_file); lock_release (&filesys_lock); } @@ -364,10 +368,11 @@ process_exit (void) /* Free child process results or signal parent's death. */ struct list_elem *e; for (e = list_begin (&cur->child_results); - e != list_end (&cur->child_results); e = list_next (e)) + e != list_end (&cur->child_results);) { struct process_result *result = list_entry (e, struct process_result, elem); + struct list_elem *next = list_next (e); lock_acquire (&result->lock); /* Child has died (and was not waited for). Free the result. */ if (sema_try_down (&result->sema)) @@ -381,6 +386,7 @@ process_exit (void) sema_up (&result->sema); lock_release (&result->lock); } + e = next; } /* Destroy the current process's page directory and switch back