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 Thread *thread_current(void)
26 return model->scheduler->get_current_thread();
29 int Thread::create_context()
33 ret = getcontext(&context);
37 /* start_routine == NULL means this is our initial context */
41 /* Initialize new managed context */
42 stack = stack_allocate(STACK_SIZE);
43 context.uc_stack.ss_sp = stack;
44 context.uc_stack.ss_size = STACK_SIZE;
45 context.uc_stack.ss_flags = 0;
46 context.uc_link = &model->system_thread->context;
47 makecontext(&context, start_routine, 1, arg);
52 int Thread::swap(Thread *t)
54 return swapcontext(&this->context, &t->context);
57 void Thread::dispose()
59 DEBUG("completed thread %d\n", thread_current()->get_id());
60 state = THREAD_COMPLETED;
65 * Return 1 if found next thread, 0 otherwise
67 static int thread_system_next(void)
71 curr = thread_current();
72 model->check_current_action();
74 if (curr->get_state() == THREAD_READY)
75 model->scheduler->add_thread(curr);
76 else if (curr->get_state() == THREAD_RUNNING)
77 /* Stopped while running; i.e., completed */
80 DEBUG("ERROR: current thread in unexpected state??\n");
82 next = model->scheduler->next_thread();
84 next->set_state(THREAD_RUNNING);
85 DEBUG("(%d, %d)\n", curr ? curr->get_id() : -1, next ? next->get_id() : -1);
88 return model->system_thread->swap(next);
91 static void thread_wait_finish(void)
96 while (!thread_system_next());
99 int Thread::switch_to_master(ModelAction *act)
104 model->set_current_action(act);
105 state = THREAD_READY;
106 next = model->system_thread;
110 Thread::Thread(thrd_t *t, void (*func)(), void *a) {
114 start_routine = func;
117 /* Initialize state */
118 ret = create_context();
120 printf("Error in create_context\n");
122 state = THREAD_CREATED;
123 model->assign_id(this);
124 model->scheduler->add_thread(this);
127 Thread::Thread(thrd_t *t) {
130 state = THREAD_CREATED;
131 model->assign_id(this);
133 model->add_system_thread(this);
136 static thread_id_t thrd_to_id(thrd_t t)
141 thread_id_t Thread::get_id()
143 return thrd_to_id(*user_thread);
147 * User program API functions
149 int thrd_create(thrd_t *t, void (*start_routine)(), void *arg)
153 ret = model->add_thread(new Thread(t, start_routine, arg));
154 DEBUG("create thread %d\n", thrd_to_id(*t));
158 int thrd_join(thrd_t t)
161 Thread *th = model->get_thread(thrd_to_id(t));
162 while (th->get_state() != THREAD_COMPLETED && !ret)
163 /* seq_cst is just a 'don't care' parameter */
164 ret = thread_current()->switch_to_master(new ModelAction(THREAD_JOIN, memory_order_seq_cst, NULL, VALUE_NONE));
170 /* seq_cst is just a 'don't care' parameter */
171 return thread_current()->switch_to_master(new ModelAction(THREAD_YIELD, memory_order_seq_cst, NULL, VALUE_NONE));
174 thrd_t thrd_current(void)
176 return thread_current()->get_thrd_t();
180 * Main system function
184 thrd_t user_thread, main_thread;
187 model = new ModelChecker();
189 th = new Thread(&main_thread);
191 /* Start user program */
192 thrd_create(&user_thread, &user_main, NULL);
194 /* Wait for all threads to complete */
195 thread_wait_finish();
197 model->print_trace();