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