X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Fthread.c;h=f6768c0225432617c92c40e517a00f75f6fd72b9;hb=53a7f5d0952a4595f252247f5ee3d017468eb57e;hp=dc23efb4b2dfb3bb608084940991a3c916d50ae6;hpb=575dc45e34db19ee7808c116e93485b37e0df716;p=pintos-anon diff --git a/src/threads/thread.c b/src/threads/thread.c index dc23efb..f6768c0 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -7,10 +7,10 @@ #include "threads/flags.h" #include "threads/interrupt.h" #include "threads/intr-stubs.h" -#include "threads/mmu.h" #include "threads/palloc.h" #include "threads/switch.h" #include "threads/synch.h" +#include "threads/vaddr.h" #ifdef USERPROG #include "userprog/process.h" #endif @@ -50,6 +50,11 @@ static long long user_ticks; /* # of timer ticks in user programs. */ #define TIME_SLICE 4 /* # of timer ticks to give each thread. */ static unsigned thread_ticks; /* # of timer ticks since last yield. */ +/* If false (default), use round-robin scheduler. + If true, use multi-level feedback queue scheduler. + Controlled by kernel command-line option "-o mlfqs". */ +bool thread_mlfqs; + static void kernel_thread (thread_func *, void *aux); static void idle (void *aux UNUSED); @@ -71,7 +76,10 @@ static tid_t allocate_tid (void); After calling this function, be sure to initialize the page allocator before trying to create any threads with - thread_create(). */ + thread_create(). + + It is not safe to call thread_current() until this function + finishes. */ void thread_init (void) { @@ -92,11 +100,20 @@ thread_init (void) void thread_start (void) { - thread_create ("idle", PRI_MAX, idle, NULL); + /* Create the idle thread. */ + struct semaphore idle_started; + sema_init (&idle_started, 0); + thread_create ("idle", PRI_MIN, idle, &idle_started); + + /* Start preemptive thread scheduling. */ intr_enable (); + + /* Wait for the idle thread to initialize idle_thread. */ + sema_down (&idle_started); } -/* Called by the timer interrupt handler at each timer tick. */ +/* Called by the timer interrupt handler at each timer tick. + Thus, this function runs in an external interrupt context. */ void thread_tick (void) { @@ -277,7 +294,8 @@ thread_yield (void) ASSERT (!intr_context ()); old_level = intr_disable (); - list_push_back (&ready_list, &cur->elem); + if (cur != idle_thread) + list_push_back (&ready_list, &cur->elem); cur->status = THREAD_READY; schedule (); intr_set_level (old_level); @@ -328,11 +346,21 @@ thread_get_recent_cpu (void) return 0; } -/* Idle thread. Executes when no other thread is ready to run. */ +/* Idle thread. Executes when no other thread is ready to run. + + The idle thread is initially put on the ready list by + thread_start(). It will be scheduled once initially, at which + point it initializes idle_thread, "up"s the semaphore passed + to it to enable thread_start() to continue, and immediately + blocks. After that, the idle thread never appears in the + ready list. It is returned by next_thread_to_run() as a + special case when the ready list is empty. */ static void -idle (void *aux UNUSED) +idle (void *idle_started_ UNUSED) { + struct semaphore *idle_started = idle_started_; idle_thread = thread_current (); + sema_up (idle_started); for (;;) { @@ -350,8 +378,9 @@ idle (void *aux UNUSED) one to occur, wasting as much as one clock tick worth of time. - See [IA32-v2a] "HLT", [IA32-v2b] "STI", and [IA32-v3] 7.7. */ - asm ("sti; hlt"); + See [IA32-v2a] "HLT", [IA32-v2b] "STI", and [IA32-v3a] + 7.11.1 "HLT Instruction". */ + asm volatile ("sti; hlt" : : : "memory"); } } @@ -467,12 +496,13 @@ schedule_tail (struct thread *prev) /* If the thread we switched from is dying, destroy its struct thread. This must happen late so that thread_exit() doesn't - pull out the rug under itself. */ - if (prev != NULL && prev->status == THREAD_DYING) + pull out the rug under itself. (We don't free + initial_thread because its memory was not obtained via + palloc().) */ + if (prev != NULL && prev->status == THREAD_DYING && prev != initial_thread) { ASSERT (prev != cur); - if (prev != initial_thread) - palloc_free_page (prev); + palloc_free_page (prev); } }