4 #include "libthreads.h"
8 #define STACK_SIZE (1024 * 1024)
10 static struct thread *current, *main_thread;
12 static void *stack_allocate(size_t size)
17 static void stack_free(void *stack)
22 static int create_context(struct thread *t)
26 memset(&t->context, 0, sizeof(t->context));
27 ret = getcontext(&t->context);
31 /* t->start_routine == NULL means this is our initial context */
32 if (!t->start_routine)
35 /* Initialize new managed context */
36 t->stack = stack_allocate(STACK_SIZE);
37 t->context.uc_stack.ss_sp = t->stack;
38 t->context.uc_stack.ss_size = STACK_SIZE;
39 t->context.uc_stack.ss_flags = 0;
40 t->context.uc_link = &main_thread->context;
41 makecontext(&t->context, t->start_routine, 1, t->arg);
46 static int create_initial_thread(struct thread *t)
48 memset(t, 0, sizeof(*t));
49 return create_context(t);
52 static int thread_swap(struct thread *old, struct thread *new)
54 return swapcontext(&old->context, &new->context);
57 int thread_yield(void)
59 struct thread *old, *next;
63 schedule_add_thread(old);
64 next = schedule_choose_next();
66 DEBUG("(%d, %d)\n", old->index, next->index);
67 return thread_swap(old, next);
70 static void thread_dispose(struct thread *t)
72 DEBUG("completed thread %d\n", thread_current()->index);
77 static void thread_wait_finish(void)
85 thread_dispose(current);
86 next = schedule_choose_next();
88 } while (next && !thread_swap(main_thread, next));
91 int thread_create(struct thread *t, void (*start_routine), void *arg)
93 static int created = 1;
98 memset(t, 0, sizeof(*t));
100 DEBUG("create thread %d\n", t->index);
102 t->start_routine = start_routine;
105 /* Initialize state */
106 ret = create_context(t);
110 schedule_add_thread(t);
114 void thread_join(struct thread *t)
116 while (!t->completed)
120 struct thread *thread_current(void)
127 struct thread user_thread;
129 main_thread = malloc(sizeof(struct thread));
130 create_initial_thread(main_thread);
132 /* Start user program */
133 thread_create(&user_thread, &user_main, NULL);
135 /* Wait for all threads to complete */
136 thread_wait_finish();