Refactor process initialization to obtain name of process file in process_execute
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user