bug fix
[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
17 #ifdef TLS
18 #include <dlfcn.h>
19 uintptr_t get_tls_addr() {
20         uintptr_t addr;
21         asm ("mov %%fs:0, %0" : "=r" (addr));
22         return addr;
23 }
24
25 #include <asm/prctl.h>
26 #include <sys/prctl.h>
27 extern "C" {
28 int arch_prctl(int code, unsigned long addr);
29 }
30 static void set_tls_addr(uintptr_t addr) {
31         arch_prctl(ARCH_SET_FS, addr);
32         asm ("mov %0, %%fs:0" : : "r" (addr) : "memory");
33 }
34 #endif
35
36 /** Allocate a stack for a new thread. */
37 static void * stack_allocate(size_t size)
38 {
39         return Thread_malloc(size);
40 }
41
42 /** Free a stack for a terminated thread. */
43 static void stack_free(void *stack)
44 {
45         Thread_free(stack);
46 }
47
48 /**
49  * @brief Get the current Thread
50  *
51  * Must be called from a user context
52  *
53  * @return The currently executing thread
54  */
55 Thread * thread_current(void)
56 {
57         ASSERT(model);
58         return model->get_current_thread();
59 }
60
61 void main_thread_startup() {
62 #ifdef TLS
63         Thread * curr_thread = thread_current();
64         /* Add dummy "start" action, just to create a first clock vector */
65         model->switch_to_master(new ModelAction(THREAD_START, std::memory_order_seq_cst, curr_thread));
66 #endif
67         thread_startup();
68 }
69
70 /**
71  * Provides a startup wrapper for each thread, allowing some initial
72  * model-checking data to be recorded. This method also gets around makecontext
73  * not being 64-bit clean
74  */
75 void thread_startup()
76 {
77         Thread * curr_thread = thread_current();
78 #ifndef TLS
79         /* Add dummy "start" action, just to create a first clock vector */
80         model->switch_to_master(new ModelAction(THREAD_START, std::memory_order_seq_cst, curr_thread));
81 #endif
82
83         /* Call the actual thread function */
84         if (curr_thread->start_routine != NULL) {
85                 curr_thread->start_routine(curr_thread->arg);
86         } else if (curr_thread->pstart_routine != NULL) {
87                 // set pthread return value
88                 void *retval = curr_thread->pstart_routine(curr_thread->arg);
89                 curr_thread->set_pthread_return(retval);
90         }
91         /* Finish thread properly */
92         model->switch_to_master(new ModelAction(THREAD_FINISH, std::memory_order_seq_cst, curr_thread));
93 }
94
95 #ifdef TLS
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 void real_init_all() {
127         char * error;
128         if (!pthread_mutex_init_p) {
129                 pthread_mutex_init_p = (int (*)(pthread_mutex_t *__mutex, const pthread_mutexattr_t *__mutexattr))dlsym(RTLD_NEXT, "pthread_mutex_init");
130                 if ((error = dlerror()) != NULL) {
131                         fputs(error, stderr);
132                         exit(EXIT_FAILURE);
133                 }
134         }
135         if (!pthread_mutex_lock_p) {
136                 pthread_mutex_lock_p = (int (*)(pthread_mutex_t *__mutex))dlsym(RTLD_NEXT, "pthread_mutex_lock");
137                 if ((error = dlerror()) != NULL) {
138                         fputs(error, stderr);
139                         exit(EXIT_FAILURE);
140                 }
141         }
142         if (!pthread_mutex_unlock_p) {
143                 pthread_mutex_unlock_p = (int (*)(pthread_mutex_t *__mutex))dlsym(RTLD_NEXT, "pthread_mutex_unlock");
144                 if ((error = dlerror()) != NULL) {
145                         fputs(error, stderr);
146                         exit(EXIT_FAILURE);
147                 }
148         }
149         if (!pthread_create_p) {
150                 pthread_create_p = (int (*)(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict))dlsym(RTLD_NEXT, "pthread_create");
151                 if ((error = dlerror()) != NULL) {
152                         fputs(error, stderr);
153                         exit(EXIT_FAILURE);
154                 }
155         }
156         if (!pthread_join_p) {
157                 pthread_join_p = (int (*)(pthread_t __th, void ** __thread_return))dlsym(RTLD_NEXT, "pthread_join");
158                 if ((error = dlerror()) != NULL) {
159                         fputs(error, stderr);
160                         exit(EXIT_FAILURE);
161                 }
162         }
163 }
164
165 void finalize_helper_thread() {
166         Thread * curr_thread = thread_current();
167         real_pthread_mutex_lock(&curr_thread->mutex);
168         curr_thread->tls = (char *) get_tls_addr();
169         real_pthread_mutex_unlock(&curr_thread->mutex);
170         //Wait in the kernel until it is time for us to finish
171         real_pthread_mutex_lock(&curr_thread->mutex2);
172         real_pthread_mutex_unlock(&curr_thread->mutex2);
173         //return to helper thread function
174         setcontext(&curr_thread->context);
175 }
176
177 void * helper_thread(void * ptr) {
178         Thread * curr_thread = thread_current();
179
180         //build a context for this real thread so we can take it's context
181         int ret = getcontext(&curr_thread->helpercontext);
182         ASSERT(!ret);
183
184         /* Initialize new managed context */
185         void *helperstack = stack_allocate(STACK_SIZE);
186         curr_thread->helpercontext.uc_stack.ss_sp = helperstack;
187         curr_thread->helpercontext.uc_stack.ss_size = STACK_SIZE;
188         curr_thread->helpercontext.uc_stack.ss_flags = 0;
189         curr_thread->helpercontext.uc_link = model->get_system_context();
190         makecontext(&curr_thread->helpercontext, finalize_helper_thread, 0);
191
192         model_swapcontext(&curr_thread->context, &curr_thread->helpercontext);
193
194         //start the real thread
195         thread_startup();
196
197         //now the real thread has control again
198         stack_free(helperstack);
199
200         return NULL;
201 }
202
203 void setup_context() {
204         Thread * curr_thread = thread_current();
205
206         /* Add dummy "start" action, just to create a first clock vector */
207         model->switch_to_master(new ModelAction(THREAD_START, std::memory_order_seq_cst, curr_thread));
208
209         real_init_all();
210         
211         /* Initialize our lock */
212         real_pthread_mutex_init(&curr_thread->mutex, NULL);
213         real_pthread_mutex_init(&curr_thread->mutex2, NULL);
214         real_pthread_mutex_lock(&curr_thread->mutex2);
215
216         /* Create the real thread */
217         real_pthread_create(&curr_thread->thread, NULL, helper_thread, NULL);
218         bool notdone = true;
219         while(notdone) {
220                 real_pthread_mutex_lock(&curr_thread->mutex);
221                 if (curr_thread->tls != NULL)
222                         notdone = false;
223                 real_pthread_mutex_unlock(&curr_thread->mutex);
224         }
225
226         set_tls_addr((uintptr_t)curr_thread->tls);
227         setcontext(&curr_thread->context);
228 }
229 #endif
230
231 /**
232  * Create a thread context for a new thread so we can use
233  * setcontext/getcontext/swapcontext to swap it out.
234  * @return 0 on success; otherwise, non-zero error condition
235  */
236 int Thread::create_context()
237 {
238         int ret;
239
240         ret = getcontext(&context);
241         if (ret)
242                 return ret;
243
244         /* Initialize new managed context */
245         stack = stack_allocate(STACK_SIZE);
246         context.uc_stack.ss_sp = stack;
247         context.uc_stack.ss_size = STACK_SIZE;
248         context.uc_stack.ss_flags = 0;
249         context.uc_link = model->get_system_context();
250 #ifdef TLS
251         if (model != NULL)
252                 makecontext(&context, setup_context, 0);
253         else
254                 makecontext(&context, main_thread_startup, 0);
255 #else
256         makecontext(&context, thread_startup, 0);
257 #endif
258
259         return 0;
260 }
261
262 /**
263  * Swaps the current context to another thread of execution. This form switches
264  * from a user Thread to a system context.
265  * @param t Thread representing the currently-running thread. The current
266  * context is saved here.
267  * @param ctxt Context to which we will swap. Must hold a valid system context.
268  * @return Does not return, unless we return to Thread t's context. See
269  * swapcontext(3) (returns 0 for success, -1 for failure).
270  */
271 int Thread::swap(Thread *t, ucontext_t *ctxt)
272 {
273         t->set_state(THREAD_READY);
274 #ifdef TLS
275         set_tls_addr((uintptr_t)model->getInitThread()->tls);
276 #endif
277         return model_swapcontext(&t->context, ctxt);
278 }
279
280 /**
281  * Swaps the current context to another thread of execution. This form switches
282  * from a system context to a user Thread.
283  * @param ctxt System context variable to which to save the current context.
284  * @param t Thread to which we will swap. Must hold a valid user context.
285  * @return Does not return, unless we return to the system context (ctxt). See
286  * swapcontext(3) (returns 0 for success, -1 for failure).
287  */
288 int Thread::swap(ucontext_t *ctxt, Thread *t)
289 {
290         t->set_state(THREAD_RUNNING);
291 #ifdef TLS
292         if (t->tls != NULL)
293                 set_tls_addr((uintptr_t)t->tls);
294 #endif
295         return model_swapcontext(ctxt, &t->context);
296 }
297
298
299 /** Terminate a thread and free its stack. */
300 void Thread::complete()
301 {
302         ASSERT(!is_complete());
303         DEBUG("completed thread %d\n", id_to_int(get_id()));
304         state = THREAD_COMPLETED;
305         if (stack)
306                 stack_free(stack);
307 #ifdef TLS
308         if (this != model->getInitThread()) {
309                 modellock = 1;
310                 real_pthread_mutex_unlock(&mutex2);
311                 real_pthread_join(thread, NULL);
312                 modellock = 0;
313         }
314 #endif
315 }
316
317 /**
318  * @brief Construct a new model-checker Thread
319  *
320  * A model-checker Thread is used for accounting purposes only. It will never
321  * have its own stack, and it should never be inserted into the Scheduler.
322  *
323  * @param tid The thread ID to assign
324  */
325 Thread::Thread(thread_id_t tid) :
326         parent(NULL),
327         creation(NULL),
328         pending(NULL),
329         start_routine(NULL),
330         arg(NULL),
331         stack(NULL),
332 #ifdef TLS
333         tls(NULL),
334 #endif
335         user_thread(NULL),
336         id(tid),
337         state(THREAD_READY),    /* Thread is always ready? */
338         last_action_val(0),
339         model_thread(true)
340 {
341         memset(&context, 0, sizeof(context));
342 }
343
344 /**
345  * Construct a new thread.
346  * @param t The thread identifier of the newly created thread.
347  * @param func The function that the thread will call.
348  * @param a The parameter to pass to this function.
349  */
350 Thread::Thread(thread_id_t tid, thrd_t *t, void (*func)(void *), void *a, Thread *parent) :
351         parent(parent),
352         creation(NULL),
353         pending(NULL),
354         start_routine(func),
355         pstart_routine(NULL),
356         arg(a),
357 #ifdef TLS
358         tls(NULL),
359 #endif
360         user_thread(t),
361         id(tid),
362         state(THREAD_CREATED),
363         last_action_val(VALUE_NONE),
364         model_thread(false)
365 {
366         int ret;
367
368         /* Initialize state */
369         ret = create_context();
370         if (ret)
371                 model_print("Error in create_context\n");
372
373         user_thread->priv = this;       // WL
374 }
375
376 /**
377  * Construct a new thread for pthread.
378  * @param t The thread identifier of the newly created thread.
379  * @param func The function that the thread will call.
380  * @param a The parameter to pass to this function.
381  */
382 Thread::Thread(thread_id_t tid, thrd_t *t, void *(*func)(void *), void *a, Thread *parent) :
383         parent(parent),
384         creation(NULL),
385         pending(NULL),
386         start_routine(NULL),
387         pstart_routine(func),
388         arg(a),
389 #ifdef TLS
390         tls(NULL),
391 #endif
392         user_thread(t),
393         id(tid),
394         state(THREAD_CREATED),
395         last_action_val(VALUE_NONE),
396         model_thread(false)
397 {
398         int ret;
399
400         /* Initialize state */
401         ret = create_context();
402         if (ret)
403                 model_print("Error in create_context\n");
404 }
405
406
407 /** Destructor */
408 Thread::~Thread()
409 {
410         if (!is_complete())
411                 complete();
412 }
413
414 /** @return The thread_id_t corresponding to this Thread object. */
415 thread_id_t Thread::get_id() const
416 {
417         return id;
418 }
419
420 /**
421  * Set a thread's THREAD_* state (@see thread_state)
422  * @param s The state to enter
423  */
424 void Thread::set_state(thread_state s)
425 {
426         ASSERT(s == THREAD_COMPLETED || state != THREAD_COMPLETED);
427         state = s;
428 }
429
430 /**
431  * Get the Thread that this Thread is immediately waiting on
432  * @return The thread we are waiting on, if any; otherwise NULL
433  */
434 Thread * Thread::waiting_on() const
435 {
436         if (!pending)
437                 return NULL;
438
439         if (pending->get_type() == THREAD_JOIN)
440                 return pending->get_thread_operand();
441         else if (pending->get_type() == PTHREAD_JOIN)
442                 return pending->get_thread_operand();
443         else if (pending->is_lock())
444                 return (Thread *)pending->get_mutex()->get_state()->locked;
445         return NULL;
446 }
447
448 /**
449  * Check if this Thread is waiting (blocking) on a given Thread, directly or
450  * indirectly (via a chain of waiting threads)
451  *
452  * @param t The Thread on which we may be waiting
453  * @return True if we are waiting on Thread t; false otherwise
454  */
455 bool Thread::is_waiting_on(const Thread *t) const
456 {
457         Thread *wait;
458         for (wait = waiting_on();wait != NULL;wait = wait->waiting_on())
459                 if (wait == t)
460                         return true;
461         return false;
462 }