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