action: add 'reads_from' member variable
[c11tester.git] / threads.cc
1 #include "libthreads.h"
2 #include "common.h"
3 #include "threads.h"
4
5 /* global "model" object */
6 #include "model.h"
7
8 #define STACK_SIZE (1024 * 1024)
9
10 static void * stack_allocate(size_t size)
11 {
12         return malloc(size);
13 }
14
15 static void stack_free(void *stack)
16 {
17         free(stack);
18 }
19
20 Thread * thread_current(void)
21 {
22         ASSERT(model);
23         return model->scheduler->get_current_thread();
24 }
25
26 /* This method just gets around makecontext not being 64-bit clean */
27
28 void thread_startup() {
29         Thread * curr_thread = thread_current();
30         curr_thread->start_routine(curr_thread->arg);
31 }
32
33 int Thread::create_context()
34 {
35         int ret;
36
37         ret = getcontext(&context);
38         if (ret)
39                 return ret;
40
41         /* Initialize new managed context */
42         stack = stack_allocate(STACK_SIZE);
43         context.uc_stack.ss_sp = stack;
44         context.uc_stack.ss_size = STACK_SIZE;
45         context.uc_stack.ss_flags = 0;
46         context.uc_link = model->get_system_context();
47         makecontext(&context, thread_startup, 0);
48
49         return 0;
50 }
51
52 int Thread::swap(Thread *t, ucontext_t *ctxt)
53 {
54         return swapcontext(&t->context, ctxt);
55 }
56
57 int Thread::swap(ucontext_t *ctxt, Thread *t)
58 {
59         return swapcontext(ctxt, &t->context);
60 }
61
62 void Thread::complete()
63 {
64         if (state != THREAD_COMPLETED) {
65                 DEBUG("completed thread %d\n", get_id());
66                 state = THREAD_COMPLETED;
67                 if (stack)
68                         stack_free(stack);
69         }
70 }
71
72 Thread::Thread(thrd_t *t, void (*func)(void *), void *a) :
73         last_action_val(VALUE_NONE)
74 {
75         int ret;
76
77         user_thread = t;
78         start_routine = func;
79         arg = a;
80
81         /* Initialize state */
82         ret = create_context();
83         if (ret)
84                 printf("Error in create_context\n");
85
86         state = THREAD_CREATED;
87         id = model->get_next_id();
88         *user_thread = id;
89         parent = thread_current();
90 }
91
92 Thread::~Thread()
93 {
94         complete();
95         model->remove_thread(this);
96 }
97
98 thread_id_t Thread::get_id()
99 {
100         return id;
101 }