Skip to content

Commit

Permalink
[#48] Define a process hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
hangpark committed Apr 10, 2017
1 parent 97e79a9 commit a911f78
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 11 deletions.
21 changes: 21 additions & 0 deletions src/threads/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ thread_init (void)
init_thread (initial_thread, "main", PRI_DEFAULT);
initial_thread->status = THREAD_RUNNING;
initial_thread->tid = allocate_tid ();
#ifdef USERPROG
(&initial_thread->process)->pid = (pid_t) initial_thread->tid;
(&initial_thread->process)->parent = NULL;
#endif
}

/* Starts preemptive thread scheduling by enabling interrupts.
Expand Down Expand Up @@ -182,6 +186,18 @@ thread_create (const char *name, int priority,
init_thread (t, name, priority);
tid = t->tid = allocate_tid ();

#ifdef USERPROG
struct process *curr_proc = process_current ();
struct process *new_proc = &t->process;

new_proc->pid = t->tid;
new_proc->parent = curr_proc;
new_proc->status = PROCESS_LOADING;
new_proc->exit_status = -1;
new_proc->is_waiting = false;
list_push_back (&curr_proc->child_list, &new_proc->elem);
#endif

/* Stack frame for kernel_thread(). */
kf = alloc_frame (t, sizeof *kf);
kf->eip = NULL;
Expand Down Expand Up @@ -465,6 +481,11 @@ init_thread (struct thread *t, const char *name, int priority)
t->waiting_lock = NULL;
list_init (&t->lock_list);
t->magic = THREAD_MAGIC;

#ifdef USERPROG
list_init (&(&t->process)->child_list);
list_init (&(&t->process)->file_list);
#endif
}

/* Allocates a SIZE-byte frame at the top of thread T's stack and
Expand Down
4 changes: 4 additions & 0 deletions src/threads/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <debug.h>
#include <list.h>
#include <stdint.h>
#ifdef USERPROG
#include "userprog/process.h"
#endif

/* States in a thread's life cycle. */
enum thread_status
Expand Down Expand Up @@ -101,6 +104,7 @@ struct thread

#ifdef USERPROG
/* Owned by userprog/process.c. */
struct process process; /* User process. */
uint32_t *pagedir; /* Page directory. */
#endif

Expand Down
57 changes: 48 additions & 9 deletions src/userprog/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,40 +27,41 @@ struct arguments
};

static thread_func start_process NO_RETURN;
static bool load (struct arguments *args, void (**eip) (void), void **esp);
static bool load (struct arguments *args, void (**eip) (void), void **esp,
struct file **exec_file);
static void argument_parser(char *str, struct arguments *args);

/* Starts a new thread running a user program loaded from
FILENAME. The new thread may be scheduled (and may even exit)
before process_execute() returns. Returns the new process's
thread id, or TID_ERROR if the thread cannot be created. */
tid_t
pid_t
process_execute (const char *file_name)
{
char *fn_copy;
struct arguments *args;
tid_t tid;
pid_t pid;

/* Make a copy of FILE_NAME.
Otherwise there's a race between the caller and load(). */
fn_copy = palloc_get_page (0);
if (fn_copy == NULL)
return TID_ERROR;
return PID_ERROR;
strlcpy (fn_copy, file_name, PGSIZE);

/* Parse argument into the structure. */
args = (struct arguments *) malloc (sizeof (struct arguments));
argument_parser (fn_copy, args);

/* Create a new thread to execute FILE_NAME. */
tid = thread_create (args->argv[0], PRI_DEFAULT, start_process, args);
if (tid == TID_ERROR)
pid = (pid_t) thread_create (args->argv[0], PRI_DEFAULT, start_process, args);
if (pid == TID_ERROR)
{
free(args->argv);
free(args);
palloc_free_page (fn_copy);
}
return tid;
return pid;
}

/* Parse arguments from given string, which removes whole adjacent spaces and replace it
Expand All @@ -85,6 +86,7 @@ static void
start_process (void *arguments)
{
struct arguments *args = arguments;
struct file *exec_file;
struct intr_frame if_;
bool success;

Expand All @@ -93,7 +95,16 @@ start_process (void *arguments)
if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
if_.cs = SEL_UCSEG;
if_.eflags = FLAG_IF | FLAG_MBS;
success = load (args, &if_.eip, &if_.esp);
success = load (args, &if_.eip, &if_.esp, &exec_file);

/* Save load result. */
struct process *curr = process_current ();
if (success)
curr->status |= PROCESS_RUNNING;
else
curr->status |= PROCESS_FAIL;
curr->exec_file = exec_file;
list_init (&curr->file_list);

/* If load failed, quit. */
if (!success)
Expand All @@ -102,6 +113,7 @@ start_process (void *arguments)
free(args);
thread_exit ();
}

/* Start the user process by simulating a return from an
interrupt, implemented by intr_exit (in
threads/intr-stubs.S). Because intr_exit takes all of its
Expand Down Expand Up @@ -168,6 +180,29 @@ process_activate (void)
interrupts. */
tss_update ();
}

/* Returns the current process. */
struct process *
process_current (void)
{
return &thread_current ()->process;
}

/* Returns the child process of the given process with the given pid value. */
struct process *
process_find_child (struct process *proc, pid_t pid)
{
struct process *child;
struct list_elem *e;
for (e = list_begin (&proc->child_list); e != list_end (&proc->child_list);
e = list_next (e))
{
child = list_entry (e, struct process, elem);
if (child->pid == pid)
return child;
}
return NULL;
}

/* We load ELF binaries. The following definitions are taken
from the ELF specification, [ELF1], more-or-less verbatim. */
Expand Down Expand Up @@ -244,7 +279,8 @@ static void push_args_on_stack(struct arguments *args, void **esp);
and its initial stack pointer into *ESP.
Returns true if successful, false otherwise. */
bool
load (struct arguments *args, void (**eip) (void), void **esp)
load (struct arguments *args, void (**eip) (void), void **esp,
struct file **exec_file)
{
struct thread *t = thread_current ();
struct Elf32_Ehdr ehdr;
Expand Down Expand Up @@ -349,6 +385,9 @@ load (struct arguments *args, void (**eip) (void), void **esp)
/* Start address. */
*eip = (void (*) (void)) ehdr.e_entry;

/* Save the executable file. */
*exec_file = file;

success = true;

done:
Expand Down
39 changes: 37 additions & 2 deletions src/userprog/process.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,46 @@
#ifndef USERPROG_PROCESS_H
#define USERPROG_PROCESS_H

#include "threads/thread.h"
#include <list.h>

tid_t process_execute (const char *file_name);
/* Process identifier type. */
typedef int pid_t;
#define PID_ERROR ((pid_t) -1) /* Error value for pid_t. */

/* Process status flags. */
#define PROCESS_LOADING 0 /* Process is loading. */
#define PROCESS_RUNNING 1 /* Process is running. */
#define PROCESS_FAIL 2 /* Process loading failed. */
#define PROCESS_EXIT 4 /* Process has exited. */

/* An user process. */
struct process
{
pid_t pid; /* Process identifier. */
struct process *parent; /* Parent process. */
struct file *exec_file; /* Process executable file. */
struct list child_list; /* List of child processes. */
struct list file_list; /* List of files in use. */
struct list_elem elem; /* List element. */

int status; /* Process status. */
int exit_status; /* Exit status. */
bool is_waiting; /* Whether parent is waiting or not. */
};

/* A file held by some process. */
struct process_file
{
int fd; /* File descriptor. */
struct file *file; /* Open file. */
struct list_elem elem; /* List element. */
};

pid_t process_execute (const char *file_name);
int process_wait (tid_t);
void process_exit (void);
void process_activate (void);
struct process *process_current (void);
struct process *process_find_child (struct process *proc, pid_t pid);

#endif /* userprog/process.h */

0 comments on commit a911f78

Please sign in to comment.