4 #include "libthreads.h"
7 #include "threads_internal.h"
9 /* global "model" object */
12 #define STACK_SIZE (1024 * 1024)
14 static void *stack_allocate(size_t size)
19 static void stack_free(void *stack)
24 static int create_context(struct thread *t)
28 memset(&t->context, 0, sizeof(t->context));
29 ret = getcontext(&t->context);
33 /* t->start_routine == NULL means this is our initial context */
34 if (!t->start_routine)
37 /* Initialize new managed context */
38 t->stack = stack_allocate(STACK_SIZE);
39 t->context.uc_stack.ss_sp = t->stack;
40 t->context.uc_stack.ss_size = STACK_SIZE;
41 t->context.uc_stack.ss_flags = 0;
42 t->context.uc_link = &model->system_thread->context;
43 makecontext(&t->context, t->start_routine, 1, t->arg);
48 static int create_initial_thread(struct thread *t)
50 memset(t, 0, sizeof(*t));
52 return create_context(t);
55 static int thread_swap(struct thread *t1, struct thread *t2)
57 return swapcontext(&t1->context, &t2->context);
60 static void thread_dispose(struct thread *t)
62 DEBUG("completed thread %d\n", thread_current()->id);
63 t->state = THREAD_COMPLETED;
68 * Return 1 if found next thread, 0 otherwise
70 static int thread_system_next(void)
72 struct thread *curr, *next;
74 curr = thread_current();
75 model->check_current_action();
77 if (curr->state == THREAD_READY)
78 model->scheduler->add_thread(curr);
79 else if (curr->state == THREAD_RUNNING)
80 /* Stopped while running; i.e., completed */
83 DEBUG("ERROR: current thread in unexpected state??\n");
85 next = model->scheduler->next_thread();
87 next->state = THREAD_RUNNING;
88 DEBUG("(%d, %d)\n", curr ? curr->id : -1, next ? next->id : -1);
91 return thread_swap(model->system_thread, next);
94 static void thread_wait_finish(void)
99 while (!thread_system_next());
102 int thread_switch_to_master(ModelAction *act)
104 struct thread *old, *next;
107 model->set_current_action(act);
108 old = thread_current();
109 old->state = THREAD_READY;
110 next = model->system_thread;
111 return thread_swap(old, next);
115 * User program API functions
117 int thread_create(struct thread *t, void (*start_routine)(), void *arg)
123 memset(t, 0, sizeof(*t));
125 DEBUG("create thread %d\n", t->id);
127 t->start_routine = start_routine;
130 /* Initialize state */
131 ret = create_context(t);
135 t->state = THREAD_CREATED;
137 model->scheduler->add_thread(t);
141 int thread_join(struct thread *t)
144 while (t->state != THREAD_COMPLETED && !ret)
145 /* seq_cst is just a 'don't care' parameter */
146 ret = thread_switch_to_master(new ModelAction(THREAD_JOIN, memory_order_seq_cst, NULL, VALUE_NONE));
150 int thread_yield(void)
152 /* seq_cst is just a 'don't care' parameter */
153 return thread_switch_to_master(new ModelAction(THREAD_YIELD, memory_order_seq_cst, NULL, VALUE_NONE));
156 struct thread *thread_current(void)
158 return model->scheduler->get_current_thread();
162 * Main system function
166 struct thread user_thread;
167 struct thread *main_thread;
169 model = new ModelChecker();
171 main_thread = (struct thread *)myMalloc(sizeof(*main_thread));
172 create_initial_thread(main_thread);
173 model->add_system_thread(main_thread);
175 /* Start user program */
176 thread_create(&user_thread, &user_main, NULL);
178 /* Wait for all threads to complete */
179 thread_wait_finish();
181 model->print_trace();