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