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