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; 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 thread_func start_process NO_RETURN;
static bool load (const char *cmdline, void (**eip) (void), void **esp); 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 tid_t
process_execute (const char *cmd) process_execute (const char *cmd)
{ {
char *fn_copy; char *cmd_copy;
tid_t tid; 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(). */ Otherwise there's a race between the caller and load(). */
fn_copy = palloc_get_page (0); cmd_copy = palloc_get_page (0);
if (fn_copy == NULL) if (cmd_copy == NULL)
return TID_ERROR; return TID_ERROR;
/* Imposing implicit limit that the command line arguments /* Imposing implicit limit that the command line arguments
including the user program name fit within a single page. */ 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. */ /* Retrieve first argument of command, which is the file name
tid = thread_create (cmd, PRI_DEFAULT, start_process, fn_copy); 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) if (tid == TID_ERROR)
palloc_free_page (fn_copy); palloc_free_page (cmd_copy);
return tid; return tid;
} }
static bool process_init_stack (char *cmd_saveptr, void **esp, char *file_name); 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); static void *push_to_stack (void **esp, void *data, size_t data_size);
/* A thread function that loads a user process and starts it /* Make the current thread execute 'cmd', passing in a copy of the
running. */ 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 static void
start_process (void *cmd) start_process (void *proc_start_data)
{ {
struct intr_frame if_; struct intr_frame if_;
bool success; bool success;
/* Retrieve first argument of command, which is the file name struct process_start_data *data = proc_start_data;
of the process. */ ASSERT (data->cmd_saveptr != NULL);
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);
/* Initialize interrupt frame and load executable. */ /* Initialize interrupt frame and load executable. */
memset (&if_, 0, sizeof if_); memset (&if_, 0, sizeof if_);
if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
if_.cs = SEL_UCSEG; if_.cs = SEL_UCSEG;
if_.eflags = FLAG_IF | FLAG_MBS; 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 load failed, quit. */
if (!success) if (!success)
{ {
palloc_free_page (cmd); palloc_free_page (data->cmd);
thread_exit (); thread_exit ();
} }
/* Initialize user process stack and free page used to store the /* Initialize user process stack and free page used to store the
command that executed the process. */ command that executed the process. */
success = process_init_stack (saveptr, &if_.esp, file_name); success = process_init_stack (data->cmd_saveptr, &if_.esp, data->file_name);
palloc_free_page (cmd); palloc_free_page (data->cmd);
/* If stack initialization failed, free resources and quit. */ /* If stack initialization failed, free resources and quit. */
if (!success) if (!success)