+/* Function used as the basis for a kernel thread. */
+static void
+kernel_thread (thread_func *function, void *aux)
+{
+ ASSERT (function != NULL);
+
+ intr_enable (); /* The scheduler runs with interrupts off. */
+ function (aux); /* Execute the thread function. */
+ thread_exit (); /* If function() returns, kill the thread. */
+}
+\f
+/* Returns the running thread. */
+struct thread *
+running_thread (void)
+{
+ uint32_t *esp;
+
+ /* Copy the CPU's stack pointer into `esp', and then round that
+ 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 %%esp, %0" : "=g" (esp));
+ return pg_round_down (esp);
+}
+
+/* Returns true if T appears to point to a valid thread. */
+static bool
+is_thread (struct thread *t)
+{
+ return t != NULL && t->magic == THREAD_MAGIC;
+}
+
+/* Does basic initialization of T as a blocked thread named
+ NAME. */
+static void
+init_thread (struct thread *t, const char *name, int priority)
+{
+ ASSERT (t != NULL);
+ ASSERT (PRI_MIN <= priority && priority <= PRI_MAX);
+ ASSERT (name != NULL);
+
+ memset (t, 0, sizeof *t);
+ t->status = THREAD_BLOCKED;
+ strlcpy (t->name, name, sizeof t->name);
+ t->stack = (uint8_t *) t + PGSIZE;
+ t->priority = priority;
+ t->magic = THREAD_MAGIC;
+}
+
+/* Allocates a SIZE-byte frame at the top of thread T's stack and
+ returns a pointer to the frame's base. */
+static void *
+alloc_frame (struct thread *t, size_t size)
+{
+ /* Stack data is always allocated in word-size units. */
+ ASSERT (is_thread (t));
+ ASSERT (size % sizeof (uint32_t) == 0);
+
+ t->stack -= size;
+ return t->stack;
+}
+
+/* Chooses and returns the next thread to be scheduled. Should
+ return a thread from the run queue, unless the run queue is
+ empty. (If the running thread can continue running, then it
+ will be in the run queue.) If the run queue is empty, return
+ idle_thread. */
+static struct thread *
+next_thread_to_run (void)
+{
+ if (list_empty (&ready_list))
+ return idle_thread;
+ else
+ return list_entry (list_pop_front (&ready_list), struct thread, elem);
+}
+
+/* Completes a thread switch by activating the new thread's page
+ tables, and, if the previous thread is dying, destroying it.
+
+ At this function's invocation, we just switched from thread
+ PREV, the new thread is already running, and interrupts are
+ still disabled. This function is normally invoked by
+ thread_schedule() as its final action before returning, but
+ the first time a thread is scheduled it is called by
+ switch_entry() (see switch.S).
+
+ It's not safe to call printf() until the thread switch is
+ complete. In practice that means that printf()s should be
+ added at the end of the function.
+
+ After this function and its caller returns, the thread switch
+ is complete. */