static void init_thread (struct thread *, const char *name, int priority);
static bool is_thread (struct thread *);
static void *alloc_frame (struct thread *, size_t size);
-static void destroy_thread (struct thread *);
static void schedule (void);
void schedule_tail (struct thread *prev);
static tid_t allocate_tid (void);
{
ASSERT (!intr_context ());
+#ifdef USERPROG
+ process_exit ();
+#endif
+
/* Just set our status to dying and schedule another process.
We will be destroyed during the call to schedule_tail(). */
intr_disable ();
return list_entry (list_pop_front (&ready_list), struct thread, elem);
}
-/* Destroys T, which must not be the running thread. */
-static void
-destroy_thread (struct thread *t)
-{
- ASSERT (is_thread (t));
- ASSERT (t != thread_current ());
-
-#ifdef USERPROG
- process_destroy (t);
-#endif
- if (t != initial_thread)
- palloc_free (t);
-}
-
/* Completes a thread switch by activating the new thread's page
tables, and, if the previous thread is dying, destroying it.
process_activate ();
#endif
- /* If the thread we switched from is dying, destroy it.
- This must happen late because it's not a good idea to
- e.g. destroy the page table you're currently using. */
+ /* 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)
- destroy_thread (prev);
+ {
+ ASSERT (prev != cur);
+ if (prev != initial_thread)
+ palloc_free (prev);
+ }
}
/* Schedules a new process. At entry, interrupts must be off and
NOT_REACHED ();
}
-/* Destroys the user address space in T and frees all of its
- resources. */
+/* Free the current process's resources. */
void
-process_destroy (struct thread *t)
+process_exit (void)
{
- ASSERT (t != thread_current ());
-
- if (t->pagedir != NULL)
+ struct thread *cur = thread_current ();
+ uint32_t *pd;
+
+ /* Destroy the current process's page directory and switch back
+ to the kernel-only page directory. We have to set
+ cur->pagedir to NULL before switching page directories, or a
+ timer interrupt might switch back to the process page
+ directory. */
+ pd = cur->pagedir;
+ if (pd != NULL)
{
- pagedir_destroy (t->pagedir);
- t->pagedir = NULL;
+ cur->pagedir = NULL;
+ pagedir_activate (NULL);
+ pagedir_destroy (pd);
}
}
{
struct thread *t = thread_current ();
- /* Activate T's page tables. */
+ /* Activate thread's page tables. */
pagedir_activate (t->pagedir);
- /* Set T's kernel stack for use in processing interrupts. */
+ /* Set thread's kernel stack for use in processing
+ interrupts. */
tss_set_esp0 ((uint8_t *) t + PGSIZE);
}
\f