Refactor process initialization to obtain name of process file in process_execute

This commit is contained in:
Themis Demetriades
2024-11-10 13:41:08 +00:00
parent 795d81b7ad
commit 0ac46db2e4

View File

@@ -34,6 +34,18 @@ struct arg_elem
struct list_elem elem;
};
/* Holds the data required to be passed from a kernel thread to a thread
that executes process_start for the purpose of starting a user process. */
struct process_start_data
{
char *cmd; /* Pointer to a copy of the command used to execute the process.
Allocated a page that must be freed by process_start. */
char *cmd_saveptr; /* Value pointed to by 'saveptr' argument used by
successive calls to strtok_r to split 'cmd' into
tokens while maintaining state. */
char *file_name; /* Name of the file of the process to be started. */
};
static thread_func start_process NO_RETURN;
static bool load (const char *cmdline, void (**eip) (void), void **esp);
@@ -44,66 +56,73 @@ static bool load (const char *cmdline, void (**eip) (void), void **esp);
tid_t
process_execute (const char *cmd)
{
char *fn_copy;
char *cmd_copy;
tid_t tid;
struct process_start_data data;
/* Make a copy of FILE_NAME.
/* Make a copy of command.
Otherwise there's a race between the caller and load(). */
fn_copy = palloc_get_page (0);
if (fn_copy == NULL)
cmd_copy = palloc_get_page (0);
if (cmd_copy == NULL)
return TID_ERROR;
/* Imposing implicit limit that the command line arguments
including the user program name fit within a single page. */
strlcpy (fn_copy, cmd, PGSIZE);
strlcpy (cmd_copy, cmd, PGSIZE);
/* Create a new thread to execute FILE_NAME. */
tid = thread_create (cmd, PRI_DEFAULT, start_process, fn_copy);
/* Retrieve first argument of command, which is the file name
of the process. */
char *file_name = strtok_r (cmd_copy, " ", &data.cmd_saveptr);
if (strlen (file_name) > FNAME_MAX_LEN)
file_name[FNAME_MAX_LEN + 1] = '\n';
/* 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;
data.file_name = file_name;
tid = thread_create (file_name, PRI_DEFAULT, start_process, &data);
if (tid == TID_ERROR)
palloc_free_page (fn_copy);
palloc_free_page (cmd_copy);
return tid;
}
static bool process_init_stack (char *cmd_saveptr, void **esp, char *file_name);
static void *push_to_stack (void **esp, void *data, size_t data_size);
/* A thread function that loads a user process and starts it
running. */
/* Make the current thread execute 'cmd', passing in a copy of the
command string used for processing, the saveptr used by strtok_r
(in order to further tokenize the same command and retrieve its
arguments), as well as the name of the file being executed. This
involves loading the specified file and starting it running. */
static void
start_process (void *cmd)
start_process (void *proc_start_data)
{
struct intr_frame if_;
bool success;
/* Retrieve first argument of command, which is the file name
of the process. */
char *saveptr;
char *file_name = strtok_r (cmd, " ", &saveptr);
if (strlen (file_name) > FNAME_MAX_LEN)
file_name[FNAME_MAX_LEN + 1] = '\n';
/* TODO: Move naming of thread to process_execute, so start
tokenizing there. */
strlcpy (thread_current ()->name, file_name, FNAME_MAX_LEN + 1);
struct process_start_data *data = proc_start_data;
ASSERT (data->cmd_saveptr != NULL);
/* Initialize interrupt frame and load executable. */
memset (&if_, 0, sizeof if_);
if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
if_.cs = SEL_UCSEG;
if_.eflags = FLAG_IF | FLAG_MBS;
success = load (file_name, &if_.eip, &if_.esp);
success = load (data->file_name, &if_.eip, &if_.esp);
/* If load failed, quit. */
if (!success)
{
palloc_free_page (cmd);
palloc_free_page (data->cmd);
thread_exit ();
}
/* Initialize user process stack and free page used to store the
command that executed the process. */
success = process_init_stack (saveptr, &if_.esp, file_name);
palloc_free_page (cmd);
success = process_init_stack (data->cmd_saveptr, &if_.esp, data->file_name);
palloc_free_page (data->cmd);
/* If stack initialization failed, free resources and quit. */
if (!success)