threads: allocate Threads in via userMalloc()
[cdsspec-compiler.git] / threads.cc
1 #include <stdlib.h>
2
3 #include "libthreads.h"
4 #include "schedule.h"
5 #include "common.h"
6 #include "threads.h"
7
8 /* global "model" object */
9 #include "model.h"
10
11 #define STACK_SIZE (1024 * 1024)
12
13 static void * stack_allocate(size_t size)
14 {
15         return userMalloc(size);
16 }
17
18 static void stack_free(void *stack)
19 {
20         userFree(stack);
21 }
22
23 Thread * thread_current(void)
24 {
25         return model->scheduler->get_current_thread();
26 }
27
28 int Thread::create_context()
29 {
30         int ret;
31
32         ret = getcontext(&context);
33         if (ret)
34                 return ret;
35
36         /* start_routine == NULL means this is our initial context */
37         if (!start_routine)
38                 return 0;
39
40         /* Initialize new managed context */
41         stack = stack_allocate(STACK_SIZE);
42         context.uc_stack.ss_sp = stack;
43         context.uc_stack.ss_size = STACK_SIZE;
44         context.uc_stack.ss_flags = 0;
45         context.uc_link = &model->system_thread->context;
46         makecontext(&context, start_routine, 1, arg);
47
48         return 0;
49 }
50
51 int Thread::swap(Thread *t)
52 {
53         return swapcontext(&this->context, &t->context);
54 }
55
56 void Thread::complete()
57 {
58         if (state != THREAD_COMPLETED) {
59                 DEBUG("completed thread %d\n", get_id());
60                 state = THREAD_COMPLETED;
61                 if (stack)
62                         stack_free(stack);
63         }
64 }
65
66 void * Thread::operator new(size_t size) {
67         return userMalloc(size);
68 }
69
70 void Thread::operator delete(void *ptr) {
71         userFree(ptr);
72 }
73
74 Thread::Thread(thrd_t *t, void (*func)(), void *a) {
75         int ret;
76
77         user_thread = t;
78         start_routine = func;
79         arg = a;
80
81         /* Initialize state */
82         ret = create_context();
83         if (ret)
84                 printf("Error in create_context\n");
85
86         state = THREAD_CREATED;
87         id = model->get_next_id();
88         *user_thread = id;
89 }
90
91 Thread::Thread(thrd_t *t) {
92         /* system thread */
93         user_thread = t;
94         start_routine = NULL;
95         arg = NULL;
96
97         create_context();
98         stack = NULL;
99         state = THREAD_CREATED;
100         id = model->get_next_id();
101         *user_thread = id;
102         model->add_system_thread(this);
103 }
104
105 Thread::~Thread()
106 {
107         complete();
108         model->remove_thread(this);
109 }
110
111 thread_id_t Thread::get_id()
112 {
113         return id;
114 }
115
116 /*
117  * Return 1 if found next thread, 0 otherwise
118  */
119 static int thread_system_next(void)
120 {
121         Thread *curr, *next;
122
123         curr = thread_current();
124         model->check_current_action();
125         if (curr) {
126                 if (curr->get_state() == THREAD_READY)
127                         model->scheduler->add_thread(curr);
128                 else if (curr->get_state() == THREAD_RUNNING)
129                         /* Stopped while running; i.e., completed */
130                         curr->complete();
131                 else
132                         DEBUG("ERROR: current thread in unexpected state??\n");
133         }
134         next = model->scheduler->next_thread();
135         if (next)
136                 next->set_state(THREAD_RUNNING);
137         DEBUG("(%d, %d)\n", curr ? curr->get_id() : -1, next ? next->get_id() : -1);
138         if (!next)
139                 return 1;
140         return model->system_thread->swap(next);
141 }
142
143 static void thread_wait_finish(void)
144 {
145
146         DBG();
147
148         while (!thread_system_next());
149 }
150
151 /*
152  * Main system function
153  */
154 int main()
155 {
156         thrd_t user_thread, main_thread;
157         Thread *th;
158
159         model = new ModelChecker();
160
161         th = new Thread(&main_thread);
162
163         do {
164                 /* Start user program */
165                 thrd_create(&user_thread, &user_main, NULL);
166
167                 /* Wait for all threads to complete */
168                 thread_wait_finish();
169         } while (model->next_execution());
170
171         delete th;
172         delete model;
173
174         DEBUG("Exiting\n");
175         return 0;
176 }