10 uint32_t thread_stack_ofs = offsetof (struct thread, stack);
12 static struct list run_queue;
14 struct thread *thread_switch (struct thread *cur, struct thread *next);
19 list_init (&run_queue);
23 thread_root (void (*function) (void *aux), void *aux)
25 ASSERT (function != NULL);
32 thread_create (const char *name, void (*function) (void *aux), void *aux)
36 ASSERT (name != NULL);
37 ASSERT (function != NULL);
44 strlcpy (t->name, name, sizeof t->name);
47 t->stack = (uint32_t *) ((uint8_t *) t + NBPG);
48 *--t->stack = (uint32_t) aux;
49 *--t->stack = (uint32_t) function;
51 *--t->stack = (uint32_t) thread_root;
54 /* Add to run_queue. */
55 t->status = THREAD_BLOCKED;
61 static struct thread *
62 stack_to_thread (uint32_t *stack)
64 return (struct thread *) ((uint32_t) (stack - 1) & ~((uint32_t) NBPG - 1));
71 asm ("movl %%esp, %0\n" : "=g" (esp));
72 return stack_to_thread (esp);
77 thread_execute (const char *filename)
79 struct thread *t = thread_current ();
81 if (!addrspace_load (&t->addrspace, filename))
82 panic ("%s: program load failed", filename);
83 panic ("%s: loaded", filename);
88 thread_ready (struct thread *t)
90 if (t->status != THREAD_READY)
92 list_push_back (&run_queue, &t->rq_elem);
93 t->status = THREAD_READY;
97 static struct thread *
98 find_next_to_run (void)
100 if (list_empty (&run_queue))
103 return list_entry (list_pop_front (&run_queue), struct thread, rq_elem);
115 thread_destroy (struct thread *t)
117 ASSERT (t->status == THREAD_DYING);
118 ASSERT (t != thread_current ());
124 thread_schedule (void)
126 struct thread *cur, *next, *prev;
128 ASSERT (intr_get_level () == IF_OFF);
130 cur = thread_current ();
131 ASSERT (cur->status != THREAD_RUNNING);
133 while ((next = find_next_to_run ()) == NULL)
136 next->status = THREAD_RUNNING;
137 prev = thread_switch (cur, next);
139 /* Prevent GCC from reordering anything around the thread
141 asm volatile ("" : : : "memory");
143 if (prev != NULL && prev->status == THREAD_DYING)
144 thread_destroy (prev);
152 ASSERT (!intr_context ());
155 thread_ready (thread_current ());
160 thread_start (struct thread *t)
162 ASSERT (intr_get_level () == IF_OFF);
164 if (t->status == THREAD_READY)
165 list_remove (&t->rq_elem);
166 t->status = THREAD_RUNNING;
167 thread_switch (NULL, t);
173 ASSERT (!intr_context ());
176 thread_current ()->status = THREAD_DYING;
183 ASSERT (!intr_context ());
184 ASSERT (intr_get_level () == IF_OFF);
186 thread_current ()->status = THREAD_BLOCKED;
191 tfunc (void *aux UNUSED)
196 if (random_ulong () % 5 == 0)
198 printk ("%s exiting\n", thread_current ()->name);
201 count = random_ulong () % 25 * 10000;
202 printk ("%s waiting %zu: ", thread_current ()->name, count);
203 for (i = 0; i < count; i++);
204 printk ("%s\n", thread_current ()->name);
209 thread_self_test (void)
214 for (i = 0; i < 4; i++)
219 t = thread_create (name, tfunc, NULL);