+/* Random value for struct thread's `magic' member.
+ Used to detect stack overflow. See the big comment at the top
+ of thread.h for details. */
+#define THREAD_MAGIC 0xcd6abf4b
+
+/* List of processes in THREAD_READY state, that is, processes
+ that are ready to run but not actually running. */
+static struct list ready_list;
+
+/* Idle thread. */
+static struct thread *idle_thread;
+
+/* Initial thread, the thread running init.c:main(). */
+static struct thread *initial_thread;
+
+/* Lock used by allocate_tid(). */
+static struct lock tid_lock;
+
+/* Stack frame for kernel_thread(). */
+struct kernel_thread_frame
+ {
+ void *eip; /* Return address. */
+ thread_func *function; /* Function to call. */
+ void *aux; /* Auxiliary data for function. */
+ };
+
+/* Statistics. */
+static long long idle_ticks; /* # of timer ticks spent idle. */
+static long long kernel_ticks; /* # of timer ticks in kernel threads. */
+static long long user_ticks; /* # of timer ticks in user programs. */
+
+/* Scheduling. */
+#define TIME_SLICE 4 /* # of timer ticks to give each thread. */
+static unsigned thread_ticks; /* # of timer ticks since last yield. */
+
+/* If false (default), use round-robin scheduler.
+ If true, use multi-level feedback queue scheduler.
+ Controlled by kernel command-line options "-o mlfqs".
+ Note that the command line is not parsed until well after
+ thread_init() is called. */
+bool thread_mlfqs;
+
+static void kernel_thread (thread_func *, void *aux);
+
+static void idle (void *aux UNUSED);
+static struct thread *running_thread (void);
+static struct thread *next_thread_to_run (void);
+static void init_thread (struct thread *, const char *name, int priority);
+static bool is_thread (struct thread *) UNUSED;
+static void *alloc_frame (struct thread *, size_t size);
+static void schedule (void);
+void schedule_tail (struct thread *prev);
+static tid_t allocate_tid (void);
+
+/* Initializes the threading system by transforming the code
+ that's currently running into a thread. This can't work in
+ general and it is possible in this case only because loader.S
+ was careful to put the bottom of the stack at a page boundary.
+
+ Also initializes the run queue and the tid lock.
+
+ After calling this function, be sure to initialize the page
+ allocator before trying to create any threads with
+ thread_create().
+
+ The kernel command line is not parsed until *after* this
+ function returns, so that when this function runs,
+ thread_mlfqs is always false.
+
+ It is not safe to call thread_current() until this function
+ finishes. */
+void
+thread_init (void)
+{
+ ASSERT (intr_get_level () == INTR_OFF);
+
+ lock_init (&tid_lock);
+ list_init (&ready_list);