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