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