edit
[c11tester.git] / threads.cc
1 /** @file threads.cc
2  *  @brief Thread functions.
3  */
4
5 #include <string.h>
6
7 #include <threads.h>
8 #include "mutex.h"
9 #include "common.h"
10 #include "threads-model.h"
11 #include "action.h"
12
13 /* global "model" object */
14 #include "model.h"
15 #include "execution.h"
16
17 #ifdef TLS
18 #include <dlfcn.h>
19 uintptr_t get_tls_addr() {
20         uintptr_t addr;
21         asm ("mov %%fs:0, %0" : "=r" (addr));
22         return addr;
23 }
24
25 #include <asm/prctl.h>
26 #include <sys/prctl.h>
27 extern "C" {
28 int arch_prctl(int code, unsigned long addr);
29 }
30 static void set_tls_addr(uintptr_t addr) {
31         arch_prctl(ARCH_SET_FS, addr);
32         asm ("mov %0, %%fs:0" : : "r" (addr) : "memory");
33 }
34 #endif
35
36 /** Allocate a stack for a new thread. */
37 static void * stack_allocate(size_t size)
38 {
39         return Thread_malloc(size);
40 }
41
42 /** Free a stack for a terminated thread. */
43 static void stack_free(void *stack)
44 {
45         Thread_free(stack);
46 }
47
48 /**
49  * @brief Get the current Thread
50  *
51  * Must be called from a user context
52  *
53  * @return The currently executing thread
54  */
55 Thread * thread_current(void)
56 {
57         ASSERT(model);
58         return model->get_current_thread();
59 }
60
61 void main_thread_startup() {
62 #ifdef TLS
63         Thread * curr_thread = thread_current();
64         /* Add dummy "start" action, just to create a first clock vector */
65         model->switch_to_master(new ModelAction(THREAD_START, std::memory_order_seq_cst, curr_thread));
66 #endif
67         thread_startup();
68 }
69
70 /**
71  * Provides a startup wrapper for each thread, allowing some initial
72  * model-checking data to be recorded. This method also gets around makecontext
73  * not being 64-bit clean
74  */
75 void thread_startup()
76 {
77         Thread * curr_thread = thread_current();
78 #ifndef TLS
79         /* Add dummy "start" action, just to create a first clock vector */
80         model->switch_to_master(new ModelAction(THREAD_START, std::memory_order_seq_cst, curr_thread));
81 #endif
82
83         /* Call the actual thread function */
84         if (curr_thread->start_routine != NULL) {
85                 curr_thread->start_routine(curr_thread->arg);
86         } else if (curr_thread->pstart_routine != NULL) {
87                 // set pthread return value
88                 void *retval = curr_thread->pstart_routine(curr_thread->arg);
89                 curr_thread->set_pthread_return(retval);
90         }
91         /* Finish thread properly */
92         model->switch_to_master(new ModelAction(THREAD_FINISH, std::memory_order_seq_cst, curr_thread));
93 }
94
95 #ifdef TLS
96 int real_pthread_mutex_init(pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr) {
97         static int (*pthread_mutex_init_p) (pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr) = NULL;
98         char * error;
99         if (!pthread_mutex_init_p) {
100                 pthread_mutex_init_p = (int (*)(pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr))dlsym(RTLD_NEXT, "pthread_mutex_init");
101                 if ((error = dlerror()) != NULL) {
102                         fputs(error, stderr);
103                         exit(EXIT_FAILURE);
104                 }
105         }
106         return pthread_mutex_init_p(__mutex, __mutexattr);
107 }
108
109 int real_pthread_mutex_lock (pthread_mutex_t *__mutex) {
110         static int (*pthread_mutex_lock_p) (pthread_mutex_t *__mutex) = NULL;
111         char * error;
112         if (!pthread_mutex_lock_p) {
113                 pthread_mutex_lock_p = (int (*)(pthread_mutex_t *__mutex))dlsym(RTLD_NEXT, "pthread_mutex_lock");
114                 if ((error = dlerror()) != NULL) {
115                         fputs(error, stderr);
116                         exit(EXIT_FAILURE);
117                 }
118         }
119         return pthread_mutex_lock_p(__mutex);
120 }
121
122 int real_pthread_mutex_unlock (pthread_mutex_t *__mutex) {
123         static int (*pthread_mutex_unlock_p) (pthread_mutex_t *__mutex) = NULL;
124         char * error;
125         if (!pthread_mutex_unlock_p) {
126                 pthread_mutex_unlock_p = (int (*)(pthread_mutex_t *__mutex))dlsym(RTLD_NEXT, "pthread_mutex_unlock");
127                 if ((error = dlerror()) != NULL) {
128                         fputs(error, stderr);
129                         exit(EXIT_FAILURE);
130                 }
131         }
132         return pthread_mutex_unlock_p(__mutex);
133 }
134
135 int real_pthread_create (pthread_t *__restrict __newthread, const pthread_attr_t *__restrict __attr, void *(*__start_routine)(void *), void *__restrict __arg) {
136         static int (*pthread_create_p) (pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void * __restrict) = NULL;
137         char * error;
138         if (!pthread_create_p) {
139                 pthread_create_p = (int (*)(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict))dlsym(RTLD_NEXT, "pthread_create");
140                 if ((error = dlerror()) != NULL) {
141                         fputs(error, stderr);
142                         exit(EXIT_FAILURE);
143                 }
144         }
145         return pthread_create_p(__newthread, __attr, __start_routine, __arg);
146 }
147
148 int real_pthread_join (pthread_t __th, void ** __thread_return) {
149         static int (*pthread_join_p) (pthread_t __th, void ** __thread_return) = NULL;
150         char * error;
151         if (!pthread_join_p) {
152                 pthread_join_p = (int (*)(pthread_t __th, void ** __thread_return))dlsym(RTLD_NEXT, "pthread_join");
153                 if ((error = dlerror()) != NULL) {
154                         fputs(error, stderr);
155                         exit(EXIT_FAILURE);
156                 }
157         }
158         return pthread_join_p(__th, __thread_return);
159 }
160
161 void finalize_helper_thread() {
162         Thread * curr_thread = thread_current();
163         real_pthread_mutex_lock(&curr_thread->mutex);
164         curr_thread->tls = (char *) get_tls_addr();
165         real_pthread_mutex_unlock(&curr_thread->mutex);
166         //Wait in the kernel until it is time for us to finish
167         real_pthread_mutex_lock(&curr_thread->mutex2);
168         real_pthread_mutex_unlock(&curr_thread->mutex2);
169         //return to helper thread function
170         setcontext(&curr_thread->context);
171 }
172
173 void * helper_thread(void * ptr) {
174         Thread * curr_thread = thread_current();
175
176         //build a context for this real thread so we can take it's context
177         int ret = getcontext(&curr_thread->helpercontext);
178         ASSERT(!ret);
179
180         /* Initialize new managed context */
181         void *helperstack = stack_allocate(STACK_SIZE);
182         curr_thread->helpercontext.uc_stack.ss_sp = helperstack;
183         curr_thread->helpercontext.uc_stack.ss_size = STACK_SIZE;
184         curr_thread->helpercontext.uc_stack.ss_flags = 0;
185         curr_thread->helpercontext.uc_link = model->get_system_context();
186         makecontext(&curr_thread->helpercontext, finalize_helper_thread, 0);
187
188         model_swapcontext(&curr_thread->context, &curr_thread->helpercontext);
189
190         //start the real thread
191         thread_startup();
192
193         //now the real thread has control again
194         stack_free(helperstack);
195
196         return NULL;
197 }
198
199 void setup_context() {
200         Thread * curr_thread = thread_current();
201
202         /* Add dummy "start" action, just to create a first clock vector */
203         model->switch_to_master(new ModelAction(THREAD_START, std::memory_order_seq_cst, curr_thread));
204
205         /* Initialize our lock */
206         real_pthread_mutex_init(&curr_thread->mutex, NULL);
207         real_pthread_mutex_init(&curr_thread->mutex2, NULL);
208         real_pthread_mutex_lock(&curr_thread->mutex2);
209
210         /* Create the real thread */
211         real_pthread_create(&curr_thread->thread, NULL, helper_thread, NULL);
212         bool notdone = true;
213         while(notdone) {
214                 real_pthread_mutex_lock(&curr_thread->mutex);
215                 if (curr_thread->tls != NULL)
216                         notdone = false;
217                 real_pthread_mutex_unlock(&curr_thread->mutex);
218         }
219
220         set_tls_addr((uintptr_t)curr_thread->tls);
221         setcontext(&curr_thread->context);
222 }
223 #endif
224
225 /**
226  * Create a thread context for a new thread so we can use
227  * setcontext/getcontext/swapcontext to swap it out.
228  * @return 0 on success; otherwise, non-zero error condition
229  */
230 int Thread::create_context()
231 {
232         int ret;
233
234         ret = getcontext(&context);
235         if (ret)
236                 return ret;
237
238         /* Initialize new managed context */
239         stack = stack_allocate(STACK_SIZE);
240         context.uc_stack.ss_sp = stack;
241         context.uc_stack.ss_size = STACK_SIZE;
242         context.uc_stack.ss_flags = 0;
243         context.uc_link = model->get_system_context();
244 #ifdef TLS
245         if (model != NULL)
246                 makecontext(&context, setup_context, 0);
247         else
248                 makecontext(&context, main_thread_startup, 0);
249 #else
250         makecontext(&context, thread_startup, 0);
251 #endif
252
253         return 0;
254 }
255
256 /**
257  * Swaps the current context to another thread of execution. This form switches
258  * from a user Thread to a system context.
259  * @param t Thread representing the currently-running thread. The current
260  * context is saved here.
261  * @param ctxt Context to which we will swap. Must hold a valid system context.
262  * @return Does not return, unless we return to Thread t's context. See
263  * swapcontext(3) (returns 0 for success, -1 for failure).
264  */
265 int Thread::swap(Thread *t, ucontext_t *ctxt)
266 {
267         t->set_state(THREAD_READY);
268 #ifdef TLS
269         set_tls_addr((uintptr_t)model->getInitThread()->tls);
270 #endif
271         return model_swapcontext(&t->context, ctxt);
272 }
273
274 /**
275  * Swaps the current context to another thread of execution. This form switches
276  * from a system context to a user Thread.
277  * @param ctxt System context variable to which to save the current context.
278  * @param t Thread to which we will swap. Must hold a valid user context.
279  * @return Does not return, unless we return to the system context (ctxt). See
280  * swapcontext(3) (returns 0 for success, -1 for failure).
281  */
282 int Thread::swap(ucontext_t *ctxt, Thread *t)
283 {
284         t->set_state(THREAD_RUNNING);
285 #ifdef TLS
286         if (t->tls != NULL)
287                 set_tls_addr((uintptr_t)t->tls);
288 #endif
289         return model_swapcontext(ctxt, &t->context);
290 }
291
292
293 /** Terminate a thread and free its stack. */
294 void Thread::complete()
295 {
296         ASSERT(!is_complete());
297         DEBUG("completed thread %d\n", id_to_int(get_id()));
298         state = THREAD_COMPLETED;
299         if (stack)
300                 stack_free(stack);
301 #ifdef TLS
302         if (this != model->getInitThread()) {
303                 modellock = 1;
304                 real_pthread_mutex_unlock(&mutex2);
305                 real_pthread_join(thread, NULL);
306                 modellock = 0;
307         }
308 #endif
309 }
310
311 /**
312  * @brief Construct a new model-checker Thread
313  *
314  * A model-checker Thread is used for accounting purposes only. It will never
315  * have its own stack, and it should never be inserted into the Scheduler.
316  *
317  * @param tid The thread ID to assign
318  */
319 Thread::Thread(thread_id_t tid) :
320         parent(NULL),
321         creation(NULL),
322         pending(NULL),
323         start_routine(NULL),
324         arg(NULL),
325         stack(NULL),
326 #ifdef TLS
327         tls(NULL),
328 #endif
329         user_thread(NULL),
330         id(tid),
331         state(THREAD_READY),    /* Thread is always ready? */
332         last_action_val(0),
333         model_thread(true)
334 {
335         memset(&context, 0, sizeof(context));
336 }
337
338 /**
339  * Construct a new thread.
340  * @param t The thread identifier of the newly created thread.
341  * @param func The function that the thread will call.
342  * @param a The parameter to pass to this function.
343  */
344 Thread::Thread(thread_id_t tid, thrd_t *t, void (*func)(void *), void *a, Thread *parent) :
345         parent(parent),
346         creation(NULL),
347         pending(NULL),
348         start_routine(func),
349         pstart_routine(NULL),
350         arg(a),
351 #ifdef TLS
352         tls(NULL),
353 #endif
354         user_thread(t),
355         id(tid),
356         state(THREAD_CREATED),
357         last_action_val(VALUE_NONE),
358         model_thread(false)
359 {
360         int ret;
361
362         /* Initialize state */
363         ret = create_context();
364         if (ret)
365                 model_print("Error in create_context\n");
366
367         user_thread->priv = this;       // WL
368 }
369
370 /**
371  * Construct a new thread for pthread.
372  * @param t The thread identifier of the newly created thread.
373  * @param func The function that the thread will call.
374  * @param a The parameter to pass to this function.
375  */
376 Thread::Thread(thread_id_t tid, thrd_t *t, void *(*func)(void *), void *a, Thread *parent) :
377         parent(parent),
378         creation(NULL),
379         pending(NULL),
380         start_routine(NULL),
381         pstart_routine(func),
382         arg(a),
383 #ifdef TLS
384         tls(NULL),
385 #endif
386         user_thread(t),
387         id(tid),
388         state(THREAD_CREATED),
389         last_action_val(VALUE_NONE),
390         model_thread(false)
391 {
392         int ret;
393
394         /* Initialize state */
395         ret = create_context();
396         if (ret)
397                 model_print("Error in create_context\n");
398 }
399
400
401 /** Destructor */
402 Thread::~Thread()
403 {
404         if (!is_complete())
405                 complete();
406 }
407
408 /** @return The thread_id_t corresponding to this Thread object. */
409 thread_id_t Thread::get_id() const
410 {
411         return id;
412 }
413
414 /**
415  * Set a thread's THREAD_* state (@see thread_state)
416  * @param s The state to enter
417  */
418 void Thread::set_state(thread_state s)
419 {
420         ASSERT(s == THREAD_COMPLETED || state != THREAD_COMPLETED);
421         state = s;
422 }
423
424 /**
425  * Get the Thread that this Thread is immediately waiting on
426  * @return The thread we are waiting on, if any; otherwise NULL
427  */
428 Thread * Thread::waiting_on() const
429 {
430         if (!pending)
431                 return NULL;
432
433         if (pending->get_type() == THREAD_JOIN)
434                 return pending->get_thread_operand();
435         else if (pending->get_type() == PTHREAD_JOIN)
436                 return pending->get_thread_operand();
437         else if (pending->is_lock())
438                 return (Thread *)pending->get_mutex()->get_state()->locked;
439         return NULL;
440 }
441
442 /**
443  * Check if this Thread is waiting (blocking) on a given Thread, directly or
444  * indirectly (via a chain of waiting threads)
445  *
446  * @param t The Thread on which we may be waiting
447  * @return True if we are waiting on Thread t; false otherwise
448  */
449 bool Thread::is_waiting_on(const Thread *t) const
450 {
451         Thread *wait;
452         for (wait = waiting_on();wait != NULL;wait = wait->waiting_on())
453                 if (wait == t)
454                         return true;
455         return false;
456 }