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)
{
return 0;
}
\f
-/* 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 (;;)
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");
}
}
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);
}
/* 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);
}
}