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");
}
}
/* 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);
}
}