X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Fthread.c;h=ca8a8b07e3fa54769d2068e482a2cb019c2ef563;hb=d51aeb9e448d8a05d4263a7459c857ff2fb9d3b2;hp=7a5c726a096c2c36c38652308ae02359678141e3;hpb=615bf3b3d2a8573ed6fb9ddc0055745e163ac999;p=pintos-anon diff --git a/src/threads/thread.c b/src/threads/thread.c index 7a5c726..ca8a8b0 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -92,11 +92,12 @@ thread_init (void) void thread_start (void) { - thread_create ("idle", PRI_MAX, idle, NULL); + thread_create ("idle", PRI_MIN, idle, NULL); intr_enable (); } -/* 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) { @@ -328,10 +329,24 @@ 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 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) { + /* Initialize idle_thread. + + Until we run for the first time, idle_thread remains a null + pointer. That's okay because we know that, at that point, + the ready list has at least one element (the idle thread), + so next_thread_to_run() will not attempt to return the idle + thread. */ idle_thread = thread_current (); for (;;) @@ -350,7 +365,8 @@ 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. */ + See [IA32-v2a] "HLT", [IA32-v2b] "STI", and [IA32-v3a] + 7.11.1 "HLT Instruction". */ asm ("sti; hlt"); } } @@ -376,7 +392,7 @@ running_thread (void) down to the start of a page. Because `struct thread' is always at the beginning of a page and the stack pointer is somewhere in the middle, this locates the curent thread. */ - asm ("mov %0, %%esp" : "=g" (esp)); + asm ("mov %%esp, %0" : "=g" (esp)); return pg_round_down (esp); } @@ -467,12 +483,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); } }