model: only include the most recent seq_cst write in may_read_from
[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 /**
27  * Provides a startup wrapper for each thread, allowing some initial
28  * model-checking data to be recorded. This method also gets around makecontext
29  * not being 64-bit clean
30  */
31 void thread_startup() {
32         Thread * curr_thread = thread_current();
33
34         /* Add dummy "start" action, just to create a first clock vector */
35         model->switch_to_master(new ModelAction(THREAD_START, memory_order_seq_cst, curr_thread));
36
37         /* Call the actual thread function */
38         curr_thread->start_routine(curr_thread->arg);
39 }
40
41 int Thread::create_context()
42 {
43         int ret;
44
45         ret = getcontext(&context);
46         if (ret)
47                 return ret;
48
49         /* Initialize new managed context */
50         stack = stack_allocate(STACK_SIZE);
51         context.uc_stack.ss_sp = stack;
52         context.uc_stack.ss_size = STACK_SIZE;
53         context.uc_stack.ss_flags = 0;
54         context.uc_link = model->get_system_context();
55         makecontext(&context, thread_startup, 0);
56
57         return 0;
58 }
59
60 int Thread::swap(Thread *t, ucontext_t *ctxt)
61 {
62         return swapcontext(&t->context, ctxt);
63 }
64
65 int Thread::swap(ucontext_t *ctxt, Thread *t)
66 {
67         return swapcontext(ctxt, &t->context);
68 }
69
70 void Thread::complete()
71 {
72         if (state != THREAD_COMPLETED) {
73                 DEBUG("completed thread %d\n", get_id());
74                 state = THREAD_COMPLETED;
75                 if (stack)
76                         stack_free(stack);
77         }
78 }
79
80 Thread::Thread(thrd_t *t, void (*func)(void *), void *a) :
81         start_routine(func),
82         arg(a),
83         user_thread(t),
84         state(THREAD_CREATED),
85         last_action_val(VALUE_NONE)
86 {
87         int ret;
88
89         /* Initialize state */
90         ret = create_context();
91         if (ret)
92                 printf("Error in create_context\n");
93
94         id = model->get_next_id();
95         *user_thread = id;
96         parent = thread_current();
97 }
98
99 Thread::~Thread()
100 {
101         complete();
102         model->remove_thread(this);
103 }
104
105 thread_id_t Thread::get_id()
106 {
107         return id;
108 }