X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Fthread.c;h=0861e29533b67a59e3b4a248311735deeb2b6d5b;hb=f0612244c44f4b4f0bc79e3fc882e9f74bd4a3f4;hp=90a4dcd6456f77423a781265737ed823ffbf3dc7;hpb=b82bd44f0327c6853f466fad27edc3d4707aea73;p=pintos-anon diff --git a/src/threads/thread.c b/src/threads/thread.c index 90a4dcd..0861e29 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -2,7 +2,9 @@ #include #include #include +#include #include +#include "threads/flags.h" #include "threads/interrupt.h" #include "threads/intr-stubs.h" #include "threads/mmu.h" @@ -10,6 +12,7 @@ #include "threads/switch.h" #include "threads/synch.h" #ifdef USERPROG +#include "userprog/process.h" #include "userprog/gdt.h" #endif @@ -44,8 +47,8 @@ static void kernel_thread (thread_func *, void *aux); static void idle (void *aux UNUSED); static struct thread *running_thread (void); static struct thread *next_thread_to_run (void); -static struct thread *new_thread (const char *name); -static void init_thread (struct thread *, const char *name); +static struct thread *new_thread (const char *name, int priority); +static void init_thread (struct thread *, const char *name, int priority); static bool is_thread (struct thread *); static void *alloc_frame (struct thread *, size_t size); static void destroy_thread (struct thread *); @@ -71,7 +74,7 @@ thread_init (void) /* Set up a thread structure for the running thread. */ initial_thread = running_thread (); - init_thread (initial_thread, "main"); + init_thread (initial_thread, "main", PRI_DEFAULT); initial_thread->status = THREAD_RUNNING; initial_thread->tid = allocate_tid (); @@ -84,20 +87,26 @@ thread_init (void) void thread_start (void) { - thread_create ("idle", idle, NULL); + thread_create ("idle", PRI_DEFAULT, idle, NULL); intr_enable (); } -/* Creates a new kernel thread named NAME, which executes - FUNCTION passing AUX as the argument, and adds it to the ready - queue. If thread_start() has been called, then the new thread - may be scheduled before thread_create() returns. It could - even exit before thread_create() returns. Use a semaphore or - some other form of synchronization if you need to ensure - ordering. Returns the thread identifier for the new thread, - or TID_ERROR if creation fails. */ +/* Creates a new kernel thread named NAME with the given initial + PRIORITY, which executes FUNCTION passing AUX as the argument, + and adds it to the ready queue. If thread_start() has been + called, then the new thread may be scheduled before + thread_create() returns. It could even exit before + thread_create() returns. Use a semaphore or some other form + of synchronization if you need to ensure ordering. Returns + the thread identifier for the new thread, or TID_ERROR if + creation fails. + + The code provided sets the new thread's `priority' member to + PRIORITY, but no actual priority scheduling is implemented. + Priority scheduling is the goal of Problem 1-3. */ tid_t -thread_create (const char *name, thread_func *function, void *aux) +thread_create (const char *name, int priority, + thread_func *function, void *aux) { struct thread *t; struct kernel_thread_frame *kf; @@ -107,10 +116,10 @@ thread_create (const char *name, thread_func *function, void *aux) ASSERT (function != NULL); - t = new_thread (name); + t = new_thread (name, priority); if (t == NULL) return TID_ERROR; - tid = t->tid = allocate_tid (); + tid = t->tid; /* Stack frame for kernel_thread(). */ kf = alloc_frame (t, sizeof *kf); @@ -132,56 +141,6 @@ thread_create (const char *name, thread_func *function, void *aux) return tid; } -#ifdef USERPROG -/* Starts a new thread running a user program loaded from - FILENAME, and adds it to the ready queue. If thread_start() - has been called, then new thread may be scheduled before - thread_execute() returns.*/ -tid_t -thread_execute (const char *filename) -{ - struct thread *t; - struct intr_frame *if_; - struct switch_entry_frame *ef; - struct switch_threads_frame *sf; - void (*start) (void); - tid_t tid; - - ASSERT (filename != NULL); - - t = new_thread (filename); - if (t == NULL) - return TID_ERROR; - tid = t->tid = allocate_tid (); - - if (!addrspace_load (t, filename, &start)) - PANIC ("%s: program load failed", filename); - - /* Interrupt frame. */ - if_ = alloc_frame (t, sizeof *if_); - if_->es = SEL_UDSEG; - if_->ds = SEL_UDSEG; - if_->eip = start; - if_->cs = SEL_UCSEG; - if_->eflags = FLAG_IF | FLAG_MBS; - if_->esp = PHYS_BASE; - if_->ss = SEL_UDSEG; - - /* Stack frame for switch_entry(). */ - ef = alloc_frame (t, sizeof *ef); - ef->eip = intr_exit; - - /* Stack frame for switch_threads(). */ - sf = alloc_frame (t, sizeof *sf); - sf->eip = switch_entry; - - /* Add to run queue. */ - thread_unblock (t); - - return tid; -} -#endif - /* Transitions a blocked thread T from its current state to the ready-to-run state. This is an error if T is not blocked. (Use thread_yield() to make the running thread ready.) */ @@ -330,31 +289,36 @@ is_thread (struct thread *t) return t != NULL && t->magic == THREAD_MAGIC; } -/* Creates a new thread named NAME and initializes its fields. - Returns the new thread if successful or a null pointer on - failure. */ +/* Creates a new thread named NAME as a child of the running + thread. Returns the new thread if successful or a null + pointer on failure. */ static struct thread * -new_thread (const char *name) +new_thread (const char *name, int priority) { - struct thread *t; - - ASSERT (name != NULL); - - t = palloc_get (PAL_ZERO); - if (t != NULL) - init_thread (t, name); + struct thread *t = palloc_get (PAL_ZERO); + if (t != NULL) + { + init_thread (t, name, priority); + t->tid = allocate_tid (); + } return t; } -/* Initializes T as a new, blocked thread named NAME. */ +/* Does basic initialization of T as a blocked thread named + NAME. */ static void -init_thread (struct thread *t, const char *name) +init_thread (struct thread *t, const char *name, int priority) { + ASSERT (t != NULL); + ASSERT (PRI_MIN <= priority && priority <= PRI_MAX); + ASSERT (name != NULL); + memset (t, 0, sizeof *t); t->status = THREAD_BLOCKED; strlcpy (t->name, name, sizeof t->name); t->stack = (uint8_t *) t + PGSIZE; + t->priority = priority; t->magic = THREAD_MAGIC; } @@ -385,17 +349,15 @@ next_thread_to_run (void) return list_entry (list_pop_front (&ready_list), struct thread, elem); } -/* Destroys T, which must be in the dying state and must not be - the running thread. */ +/* Destroys T, which must not be the running thread. */ static void destroy_thread (struct thread *t) { ASSERT (is_thread (t)); - ASSERT (t->status == THREAD_DYING); ASSERT (t != thread_current ()); #ifdef USERPROG - addrspace_destroy (t); + process_destroy (t); #endif if (t != initial_thread) palloc_free (t); @@ -425,7 +387,7 @@ schedule_tail (struct thread *prev) #ifdef USERPROG /* Activate the new address space. */ - addrspace_activate (cur); + process_activate (); #endif /* If the thread we switched from is dying, destroy it.