Incorporate failed predicates in weights
[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_to_master(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
334 /** Terminate a thread and free its stack. */
335 void Thread::complete()
336 {
337         ASSERT(!is_complete());
338         DEBUG("completed thread %d\n", id_to_int(get_id()));
339         state = THREAD_COMPLETED;
340         if (stack)
341                 stack_free(stack);
342 #ifdef TLS
343         if (this != model->getInitThread()) {
344                 ASSERT(thread_current()==NULL);
345                 real_pthread_mutex_unlock(&mutex2);
346                 real_pthread_join(thread, NULL);
347                 stack_free(helper_stack);
348         }
349 #endif
350 }
351
352 /**
353  * @brief Construct a new model-checker Thread
354  *
355  * A model-checker Thread is used for accounting purposes only. It will never
356  * have its own stack, and it should never be inserted into the Scheduler.
357  *
358  * @param tid The thread ID to assign
359  */
360 Thread::Thread(thread_id_t tid) :
361         parent(NULL),
362         creation(NULL),
363         pending(NULL),
364         start_routine(NULL),
365         arg(NULL),
366         stack(NULL),
367 #ifdef TLS
368         tls(NULL),
369 #endif
370         user_thread(NULL),
371         id(tid),
372         state(THREAD_READY),    /* Thread is always ready? */
373         last_action_val(0),
374         model_thread(true)
375 {
376         memset(&context, 0, sizeof(context));
377 }
378
379 /**
380  * Construct a new thread.
381  * @param t The thread identifier of the newly created thread.
382  * @param func The function that the thread will call.
383  * @param a The parameter to pass to this function.
384  */
385 Thread::Thread(thread_id_t tid, thrd_t *t, void (*func)(void *), void *a, Thread *parent) :
386         parent(parent),
387         creation(NULL),
388         pending(NULL),
389         start_routine(func),
390         pstart_routine(NULL),
391         arg(a),
392 #ifdef TLS
393         tls(NULL),
394 #endif
395         user_thread(t),
396         id(tid),
397         state(THREAD_CREATED),
398         last_action_val(VALUE_NONE),
399         model_thread(false)
400 {
401         int ret;
402
403         /* Initialize state */
404         ret = create_context();
405         if (ret)
406                 model_print("Error in create_context\n");
407
408         user_thread->priv = this;       // WL
409 }
410
411 /**
412  * Construct a new thread for pthread.
413  * @param t The thread identifier of the newly created thread.
414  * @param func The function that the thread will call.
415  * @param a The parameter to pass to this function.
416  */
417 Thread::Thread(thread_id_t tid, thrd_t *t, void *(*func)(void *), void *a, Thread *parent) :
418         parent(parent),
419         creation(NULL),
420         pending(NULL),
421         start_routine(NULL),
422         pstart_routine(func),
423         arg(a),
424 #ifdef TLS
425         tls(NULL),
426 #endif
427         user_thread(t),
428         id(tid),
429         state(THREAD_CREATED),
430         last_action_val(VALUE_NONE),
431         model_thread(false)
432 {
433         int ret;
434
435         /* Initialize state */
436         ret = create_context();
437         if (ret)
438                 model_print("Error in create_context\n");
439 }
440
441
442 /** Destructor */
443 Thread::~Thread()
444 {
445         if (!is_complete())
446                 complete();
447 }
448
449 /** @return The thread_id_t corresponding to this Thread object. */
450 thread_id_t Thread::get_id() const
451 {
452         return id;
453 }
454
455 /**
456  * Set a thread's THREAD_* state (@see thread_state)
457  * @param s The state to enter
458  */
459 void Thread::set_state(thread_state s)
460 {
461         ASSERT(s == THREAD_COMPLETED || state != THREAD_COMPLETED);
462         state = s;
463 }
464
465 /**
466  * Get the Thread that this Thread is immediately waiting on
467  * @return The thread we are waiting on, if any; otherwise NULL
468  */
469 Thread * Thread::waiting_on() const
470 {
471         if (!pending)
472                 return NULL;
473
474         if (pending->get_type() == THREAD_JOIN)
475                 return pending->get_thread_operand();
476         else if (pending->get_type() == PTHREAD_JOIN)
477                 return pending->get_thread_operand();
478         else if (pending->is_lock())
479                 return (Thread *)pending->get_mutex()->get_state()->locked;
480         return NULL;
481 }
482
483 /**
484  * Check if this Thread is waiting (blocking) on a given Thread, directly or
485  * indirectly (via a chain of waiting threads)
486  *
487  * @param t The Thread on which we may be waiting
488  * @return True if we are waiting on Thread t; false otherwise
489  */
490 bool Thread::is_waiting_on(const Thread *t) const
491 {
492         Thread *wait;
493         for (wait = waiting_on();wait != NULL;wait = wait->waiting_on())
494                 if (wait == t)
495                         return true;
496         return false;
497 }