+/* 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 ("movl %%esp, %0\n" : "=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. */