Merge branch 'master' into brian
[c11tester.git] / action.cc
1 #include <stdio.h>
2
3 #include "model.h"
4 #include "action.h"
5 #include "clockvector.h"
6 #include "common.h"
7
8 ModelAction::ModelAction(action_type_t type, memory_order order, void *loc, int value) :
9         type(type),
10         order(order),
11         location(loc),
12         value(value),
13         reads_from(NULL),
14         cv(NULL)
15 {
16         Thread *t = thread_current();
17         this->tid = t->get_id();
18         this->seq_number = model->get_next_seq_num();
19 }
20
21 ModelAction::~ModelAction()
22 {
23         if (cv)
24                 delete cv;
25 }
26
27 bool ModelAction::is_read() const
28 {
29         return type == ATOMIC_READ;
30 }
31
32 bool ModelAction::is_write() const
33 {
34         return type == ATOMIC_WRITE || type == ATOMIC_INIT;
35 }
36
37 bool ModelAction::is_rmw() const
38 {
39         return type == ATOMIC_RMW;
40 }
41
42 bool ModelAction::is_initialization() const
43 {
44         return type == ATOMIC_INIT;
45 }
46
47 bool ModelAction::is_acquire() const
48 {
49         switch (order) {
50         case memory_order_acquire:
51         case memory_order_acq_rel:
52         case memory_order_seq_cst:
53                 return true;
54         default:
55                 return false;
56         }
57 }
58
59 bool ModelAction::is_release() const
60 {
61         switch (order) {
62         case memory_order_release:
63         case memory_order_acq_rel:
64         case memory_order_seq_cst:
65                 return true;
66         default:
67                 return false;
68         }
69 }
70
71 bool ModelAction::is_seqcst() const
72 {
73         return order==memory_order_seq_cst;
74 }
75
76 bool ModelAction::same_var(const ModelAction *act) const
77 {
78         return location == act->location;
79 }
80
81 bool ModelAction::same_thread(const ModelAction *act) const
82 {
83         return tid == act->tid;
84 }
85
86 /** The is_synchronizing method should only explore interleavings if:
87  *  (1) the operations are seq_cst and don't commute or
88  *  (2) the reordering may establish or break a synchronization relation.
89  *  Other memory operations will be dealt with by using the reads_from
90  *  relation.
91  *
92  *  @param act is the action to consider exploring a reordering.
93  *  @return tells whether we have to explore a reordering.
94  */
95
96 bool ModelAction::is_synchronizing(const ModelAction *act) const
97 {
98         //Same thread can't be reordered
99         if (same_thread(act))
100                 return false;
101
102         // Different locations commute
103         if (!same_var(act))
104                 return false;
105
106         // Explore interleavings of seqcst writes to guarantee total order
107         // of seq_cst operations that don't commute
108         if (is_write() && is_seqcst() && act->is_write() && act->is_seqcst())
109                 return true;
110
111         // Explore synchronizing read/write pairs
112         if (is_read() && is_acquire() && act->is_write() && act->is_release())
113                 return true;
114         if (is_write() && is_release() && act->is_read() && act->is_acquire())
115                 return true;
116
117         // Otherwise handle by reads_from relation
118         return false;
119 }
120
121 void ModelAction::create_cv(const ModelAction *parent)
122 {
123         ASSERT(cv == NULL);
124
125         if (parent)
126                 cv = new ClockVector(parent->cv, this);
127         else
128                 cv = new ClockVector(NULL, this);
129 }
130
131 void ModelAction::read_from(const ModelAction *act)
132 {
133         ASSERT(cv);
134         if (act->is_release() && this->is_acquire())
135                 cv->merge(act->cv);
136         reads_from = act;
137         value = act->value;
138 }
139
140 /**
141  * Check whether 'this' happens before act, according to the memory-model's
142  * happens before relation. This is checked via the ClockVector constructs.
143  * @return true if this action's thread has synchronized with act's thread
144  * since the execution of act, false otherwise.
145  */
146 bool ModelAction::happens_before(const ModelAction *act) const
147 {
148         return act->cv->synchronized_since(this);
149 }
150
151 void ModelAction::print(void) const
152 {
153         const char *type_str;
154         switch (this->type) {
155         case THREAD_CREATE:
156                 type_str = "thread create";
157                 break;
158         case THREAD_START:
159                 type_str = "thread start";
160                 break;
161         case THREAD_YIELD:
162                 type_str = "thread yield";
163                 break;
164         case THREAD_JOIN:
165                 type_str = "thread join";
166                 break;
167         case ATOMIC_READ:
168                 type_str = "atomic read";
169                 break;
170         case ATOMIC_WRITE:
171                 type_str = "atomic write";
172                 break;
173         case ATOMIC_RMW:
174                 type_str = "atomic rmw";
175                 break;
176         case ATOMIC_INIT:
177                 type_str = "init atomic";
178                 break;
179         default:
180                 type_str = "unknown type";
181         }
182
183         printf("(%3d) Thread: %-2d    Action: %-13s    MO: %d    Loc: %14p    Value: %-4d",
184                         seq_number, id_to_int(tid), type_str, order, location, value);
185         if (reads_from)
186                 printf(" Rf: %d", reads_from->get_seq_number());
187         if (cv) {
188                 printf("\t");
189                 cv->print();
190         } else
191                 printf("\n");
192 }