Refactor process_wait to add more comments and improve readability
This commit is contained in:
@@ -210,7 +210,8 @@ process_init_stack (char *cmd_saveptr, void **esp, char *file_name)
|
|||||||
so we can safely use strlen here. Filename has already been
|
so we can safely use strlen here. Filename has already been
|
||||||
split from the command line arguments. */
|
split from the command line arguments. */
|
||||||
push_to_stack (esp, arg, strlen (arg) + 1);
|
push_to_stack (esp, arg, strlen (arg) + 1);
|
||||||
|
|
||||||
|
/* Try to allocate memory for the argument pointer. */
|
||||||
struct arg_elem *arg_elem = malloc (sizeof (struct arg_elem));
|
struct arg_elem *arg_elem = malloc (sizeof (struct arg_elem));
|
||||||
if (arg_elem == NULL)
|
if (arg_elem == NULL)
|
||||||
{
|
{
|
||||||
@@ -219,9 +220,11 @@ process_init_stack (char *cmd_saveptr, void **esp, char *file_name)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store the argument pointer in the linked list. */
|
||||||
arg_elem->arg = *esp;
|
arg_elem->arg = *esp;
|
||||||
list_push_front (&arg_list, &arg_elem->elem);
|
list_push_front (&arg_list, &arg_elem->elem);
|
||||||
|
|
||||||
|
/* Increment the argument count and get the next argument. */
|
||||||
arg_count++;
|
arg_count++;
|
||||||
arg = strtok_r (NULL, " ", &cmd_saveptr);
|
arg = strtok_r (NULL, " ", &cmd_saveptr);
|
||||||
}
|
}
|
||||||
@@ -242,7 +245,10 @@ process_init_stack (char *cmd_saveptr, void **esp, char *file_name)
|
|||||||
int overflow_bytes = (PHYS_BASE - *esp) + remaining_size - PGSIZE;
|
int overflow_bytes = (PHYS_BASE - *esp) + remaining_size - PGSIZE;
|
||||||
if (overflow_bytes > 0)
|
if (overflow_bytes > 0)
|
||||||
{
|
{
|
||||||
|
/* Calculate the number of pages needed to allocate. */
|
||||||
int pages_needed = DIV_CEIL (overflow_bytes, PGSIZE);
|
int pages_needed = DIV_CEIL (overflow_bytes, PGSIZE);
|
||||||
|
|
||||||
|
/* Allocate the pages and map them to the user process. */
|
||||||
for (int i = 1; i < pages_needed + 1; i++)
|
for (int i = 1; i < pages_needed + 1; i++)
|
||||||
{
|
{
|
||||||
uint8_t *kpage = palloc_get_page (PAL_USER | PAL_ZERO);
|
uint8_t *kpage = palloc_get_page (PAL_USER | PAL_ZERO);
|
||||||
@@ -307,11 +313,12 @@ push_to_stack (void **esp, void *data, size_t data_size)
|
|||||||
* This function will be implemented in task 2.
|
* This function will be implemented in task 2.
|
||||||
* For now, it does nothing. */
|
* For now, it does nothing. */
|
||||||
int
|
int
|
||||||
process_wait (tid_t child_tid UNUSED)
|
process_wait (tid_t child_tid)
|
||||||
{
|
{
|
||||||
struct process_result *child_result = NULL;
|
struct process_result *child_result = NULL;
|
||||||
struct list_elem *e;
|
struct list_elem *e;
|
||||||
struct thread *cur = thread_current ();
|
struct thread *cur = thread_current ();
|
||||||
|
|
||||||
for (e = list_begin (&cur->child_results);
|
for (e = list_begin (&cur->child_results);
|
||||||
e != list_end (&cur->child_results); e = list_next (e))
|
e != list_end (&cur->child_results); e = list_next (e))
|
||||||
{
|
{
|
||||||
@@ -319,27 +326,40 @@ process_wait (tid_t child_tid UNUSED)
|
|||||||
= list_entry (e, struct process_result, elem);
|
= list_entry (e, struct process_result, elem);
|
||||||
if (result->tid == child_tid)
|
if (result->tid == child_tid)
|
||||||
{
|
{
|
||||||
|
/* Found the child process. */
|
||||||
child_result = result;
|
child_result = result;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* List is ordered, allowing us to break early. */
|
|
||||||
|
/* List is ordered, allowing us to break early if the child_tid is
|
||||||
|
greater than the current result's tid. */
|
||||||
else if (result->tid > child_tid)
|
else if (result->tid > child_tid)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the child process was not found, return -1. */
|
||||||
if (child_result == NULL)
|
if (child_result == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Wait for child to die. */
|
/* Wait for child to die. */
|
||||||
sema_down (&child_result->sema);
|
sema_down (&child_result->sema);
|
||||||
|
|
||||||
/* We need lock release in process_exit, so we need to acquire (and possibly
|
/* We need lock release in process_exit, so we need to acquire (and possibly
|
||||||
wait) for it here to ensure we don't free the lock memory before it is
|
wait) for it here to ensure we don't free the lock memory before it is
|
||||||
released in process_exit. */
|
released in process_exit. */
|
||||||
lock_acquire (&child_result->lock);
|
lock_acquire (&child_result->lock);
|
||||||
|
|
||||||
/* To prevent waiting for child twice, remove it from the list.
|
/* To prevent waiting for child twice, remove it from the list.
|
||||||
No need to use lock since this is the only thread with access to
|
No need to use lock since this is the only thread with access to
|
||||||
the struct process_result now. */
|
the struct process_result now. */
|
||||||
list_remove (&child_result->elem);
|
list_remove (&child_result->elem);
|
||||||
|
|
||||||
|
/* Get the exit status of the child */
|
||||||
int exit_status = child_result->exit_status;
|
int exit_status = child_result->exit_status;
|
||||||
|
|
||||||
|
/* Release the lock */
|
||||||
lock_release (&child_result->lock);
|
lock_release (&child_result->lock);
|
||||||
|
|
||||||
free (child_result);
|
free (child_result);
|
||||||
return exit_status;
|
return exit_status;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user