Major revisions to documentation.
[pintos-anon] / src / threads / thread.c
index 196ffafcf7276315f8d861244f0801cc45c31622..8d9f33558bb5313b1e137250479b5103a88db689 100644 (file)
@@ -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
@@ -92,7 +92,7 @@ thread_init (void)
 void
 thread_start (void) 
 {
-  thread_create ("idle", PRI_MAX, idle, NULL);
+  thread_create ("idle", PRI_MIN, idle, NULL);
   intr_enable ();
 }
 
@@ -329,10 +329,24 @@ thread_get_recent_cpu (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 (;;) 
@@ -351,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");
     }
 }
@@ -468,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);
     }
 }