Remove duplicate functions
[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 void modelexit() {
63         model->switch_to_master(new ModelAction(THREAD_FINISH, std::memory_order_seq_cst, thread_current()));
64 }
65
66 void initMainThread() {
67         atexit(modelexit);
68         Thread * curr_thread = thread_current();
69         model->switch_to_master(new ModelAction(THREAD_START, std::memory_order_seq_cst, curr_thread));
70 }
71
72 /**
73  * Provides a startup wrapper for each thread, allowing some initial
74  * model-checking data to be recorded. This method also gets around makecontext
75  * not being 64-bit clean
76  */
77 void thread_startup()
78 {
79         Thread * curr_thread = thread_current();
80 #ifndef TLS
81         /* Add dummy "start" action, just to create a first clock vector */
82         model->switch_to_master(new ModelAction(THREAD_START, std::memory_order_seq_cst, curr_thread));
83 #endif
84
85         /* Call the actual thread function */
86         if (curr_thread->start_routine != NULL) {
87                 curr_thread->start_routine(curr_thread->arg);
88         } else if (curr_thread->pstart_routine != NULL) {
89                 // set pthread return value
90                 void *retval = curr_thread->pstart_routine(curr_thread->arg);
91                 curr_thread->set_pthread_return(retval);
92         }
93 #ifndef TLS
94         /* Finish thread properly */
95         model->switch_to_master(new ModelAction(THREAD_FINISH, std::memory_order_seq_cst, curr_thread));
96 #endif
97 }
98
99 static int (*pthread_mutex_init_p)(pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr) = NULL;
100
101 int real_pthread_mutex_init(pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr) {
102         return pthread_mutex_init_p(__mutex, __mutexattr);
103 }
104
105 static int (*pthread_mutex_lock_p) (pthread_mutex_t *__mutex) = NULL;
106
107 int real_pthread_mutex_lock (pthread_mutex_t *__mutex) {
108         return pthread_mutex_lock_p(__mutex);
109 }
110
111 static int (*pthread_mutex_unlock_p) (pthread_mutex_t *__mutex) = NULL;
112
113 int real_pthread_mutex_unlock (pthread_mutex_t *__mutex) {
114         return pthread_mutex_unlock_p(__mutex);
115 }
116
117 static int (*pthread_create_p) (pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void * __restrict) = NULL;
118
119 int real_pthread_create (pthread_t *__restrict __newthread, const pthread_attr_t *__restrict __attr, void *(*__start_routine)(void *), void *__restrict __arg) {
120         return pthread_create_p(__newthread, __attr, __start_routine, __arg);
121 }
122
123 static int (*pthread_join_p) (pthread_t __th, void ** __thread_return) = NULL;
124
125 int real_pthread_join (pthread_t __th, void ** __thread_return) {
126         return pthread_join_p(__th, __thread_return);
127 }
128
129 static void (*pthread_exit_p)(void *) __attribute__((noreturn))= NULL;
130
131 void real_pthread_exit (void * value_ptr) {
132         pthread_exit_p(value_ptr);
133 }
134
135 void real_init_all() {
136         char * error;
137         if (!pthread_mutex_init_p) {
138                 pthread_mutex_init_p = (int (*)(pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr))dlsym(RTLD_NEXT, "pthread_mutex_init");
139                 if ((error = dlerror()) != NULL) {
140                         fputs(error, stderr);
141                         exit(EXIT_FAILURE);
142                 }
143         }
144         if (!pthread_mutex_lock_p) {
145                 pthread_mutex_lock_p = (int (*)(pthread_mutex_t *__mutex))dlsym(RTLD_NEXT, "pthread_mutex_lock");
146                 if ((error = dlerror()) != NULL) {
147                         fputs(error, stderr);
148                         exit(EXIT_FAILURE);
149                 }
150         }
151         if (!pthread_mutex_unlock_p) {
152                 pthread_mutex_unlock_p = (int (*)(pthread_mutex_t *__mutex))dlsym(RTLD_NEXT, "pthread_mutex_unlock");
153                 if ((error = dlerror()) != NULL) {
154                         fputs(error, stderr);
155                         exit(EXIT_FAILURE);
156                 }
157         }
158         if (!pthread_create_p) {
159                 pthread_create_p = (int (*)(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict))dlsym(RTLD_NEXT, "pthread_create");
160                 if ((error = dlerror()) != NULL) {
161                         fputs(error, stderr);
162                         exit(EXIT_FAILURE);
163                 }
164         }
165         if (!pthread_join_p) {
166                 pthread_join_p = (int (*)(pthread_t __th, void ** __thread_return))dlsym(RTLD_NEXT, "pthread_join");
167                 if ((error = dlerror()) != NULL) {
168                         fputs(error, stderr);
169                         exit(EXIT_FAILURE);
170                 }
171         }
172
173         if (!pthread_exit_p) {
174                 *((void (**)(void *)) &pthread_exit_p) = (void (*)(void *))dlsym(RTLD_NEXT, "pthread_exit");
175                 if ((error = dlerror()) != NULL) {
176                         fputs(error, stderr);
177                         exit(EXIT_FAILURE);
178                 }
179         }
180 }
181
182 #ifdef TLS
183 void finalize_helper_thread() {
184         Thread * curr_thread = thread_current();
185         real_pthread_mutex_lock(&curr_thread->mutex);
186         curr_thread->tls = (char *) get_tls_addr();
187         real_pthread_mutex_unlock(&curr_thread->mutex);
188         //Wait in the kernel until it is time for us to finish
189         real_pthread_mutex_lock(&curr_thread->mutex2);
190         real_pthread_mutex_unlock(&curr_thread->mutex2);
191         //return to helper thread function
192         setcontext(&curr_thread->context);
193 }
194
195 void * helper_thread(void * ptr) {
196         Thread * curr_thread = thread_current();
197
198         //build a context for this real thread so we can take it's context
199         int ret = getcontext(&curr_thread->helpercontext);
200         ASSERT(!ret);
201
202         //Setup destructor
203         if (pthread_setspecific(model->get_execution()->getPthreadKey(), (const void *)4)) {
204                 printf("Destructor setup failed\n");
205                 exit(-1);
206         }
207
208
209         /* Initialize new managed context */
210         curr_thread->helper_stack = stack_allocate(STACK_SIZE);
211         curr_thread->helpercontext.uc_stack.ss_sp = curr_thread->helper_stack;
212         curr_thread->helpercontext.uc_stack.ss_size = STACK_SIZE;
213         curr_thread->helpercontext.uc_stack.ss_flags = 0;
214         curr_thread->helpercontext.uc_link = model->get_system_context();
215         makecontext(&curr_thread->helpercontext, finalize_helper_thread, 0);
216
217         model_swapcontext(&curr_thread->context, &curr_thread->helpercontext);
218
219
220         //start the real thread
221         thread_startup();
222
223         return NULL;
224 }
225
226 #ifdef TLS
227 void tlsdestructor(void *v) {
228         uintptr_t count = (uintptr_t) v;
229         if (count > 1) {
230                 if (pthread_setspecific(model->get_execution()->getPthreadKey(), (const void *)(count - 1))) {
231                         printf("Destructor setup failed\n");
232                         exit(-1);
233                 }
234                 return;
235         }
236         /* Finish thread properly */
237         model->switch_to_master(new ModelAction(THREAD_FINISH, std::memory_order_seq_cst, thread_current()));
238 }
239 #endif
240
241 void setup_context() {
242         Thread * curr_thread = thread_current();
243
244         /* Add dummy "start" action, just to create a first clock vector */
245         model->switch_thread(new ModelAction(THREAD_START, std::memory_order_seq_cst, curr_thread));
246
247         real_init_all();
248
249         /* Initialize our lock */
250         real_pthread_mutex_init(&curr_thread->mutex, NULL);
251         real_pthread_mutex_init(&curr_thread->mutex2, NULL);
252         real_pthread_mutex_lock(&curr_thread->mutex2);
253
254         /* Create the real thread */
255         real_pthread_create(&curr_thread->thread, NULL, helper_thread, NULL);
256         bool notdone = true;
257         while(notdone) {
258                 real_pthread_mutex_lock(&curr_thread->mutex);
259                 if (curr_thread->tls != NULL)
260                         notdone = false;
261                 real_pthread_mutex_unlock(&curr_thread->mutex);
262         }
263
264         set_tls_addr((uintptr_t)curr_thread->tls);
265         setcontext(&curr_thread->context);
266 }
267 #endif
268
269 /**
270  * Create a thread context for a new thread so we can use
271  * setcontext/getcontext/swapcontext to swap it out.
272  * @return 0 on success; otherwise, non-zero error condition
273  */
274 int Thread::create_context()
275 {
276         int ret;
277
278         ret = getcontext(&context);
279         if (ret)
280                 return ret;
281
282         /* Initialize new managed context */
283         stack = stack_allocate(STACK_SIZE);
284         context.uc_stack.ss_sp = stack;
285         context.uc_stack.ss_size = STACK_SIZE;
286         context.uc_stack.ss_flags = 0;
287         context.uc_link = model->get_system_context();
288 #ifdef TLS
289         makecontext(&context, setup_context, 0);
290 #else
291         makecontext(&context, thread_startup, 0);
292 #endif
293
294         return 0;
295 }
296
297 /**
298  * Swaps the current context to another thread of execution. This form switches
299  * from a user Thread to a system context.
300  * @param t Thread representing the currently-running thread. The current
301  * context is saved here.
302  * @param ctxt Context to which we will swap. Must hold a valid system context.
303  * @return Does not return, unless we return to Thread t's context. See
304  * swapcontext(3) (returns 0 for success, -1 for failure).
305  */
306 int Thread::swap(Thread *t, ucontext_t *ctxt)
307 {
308         t->set_state(THREAD_READY);
309 #ifdef TLS
310         set_tls_addr((uintptr_t)model->getInitThread()->tls);
311 #endif
312         return model_swapcontext(&t->context, ctxt);
313 }
314
315 /**
316  * Swaps the current context to another thread of execution. This form switches
317  * from a system context to a user Thread.
318  * @param ctxt System context variable to which to save the current context.
319  * @param t Thread to which we will swap. Must hold a valid user context.
320  * @return Does not return, unless we return to the system context (ctxt). See
321  * swapcontext(3) (returns 0 for success, -1 for failure).
322  */
323 int Thread::swap(ucontext_t *ctxt, Thread *t)
324 {
325         t->set_state(THREAD_RUNNING);
326 #ifdef TLS
327         if (t->tls != NULL)
328                 set_tls_addr((uintptr_t)t->tls);
329 #endif
330         return model_swapcontext(ctxt, &t->context);
331 }
332
333 int Thread::swap(Thread *t, Thread *t2)
334 {
335         t->set_state(THREAD_READY);
336         t2->set_state(THREAD_RUNNING);
337 #ifdef TLS
338         if (t2->tls != NULL)
339                 set_tls_addr((uintptr_t)t2->tls);
340 #endif
341         return model_swapcontext(&t->context, &t2->context);
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 }