fix compilation (includes)
[c11tester.git] / nodestack.cc
1 #include <string.h>
2
3 #include "nodestack.h"
4 #include "action.h"
5 #include "common.h"
6 #include "model.h"
7
8 /**
9  * @brief Node constructor
10  *
11  * Constructs a single Node for use in a NodeStack. Each Node is associated
12  * with exactly one ModelAction (exception: the first Node should be created
13  * as an empty stub, to represent the first thread "choice") and up to one
14  * parent.
15  *
16  * @param act The ModelAction to associate with this Node. May be NULL.
17  * @param par The parent Node in the NodeStack. May be NULL if there is no
18  * parent.
19  * @param nthreads The number of threads which exist at this point in the
20  * execution trace.
21  */
22 Node::Node(ModelAction *act, Node *par, int nthreads, bool *enabled)
23         : action(act),
24         parent(par),
25         num_threads(nthreads),
26         explored_children(num_threads),
27         backtrack(num_threads),
28         numBacktracks(0),
29         may_read_from(),
30         read_from_index(0),
31         future_values(),
32         future_index(-1)
33 {
34         if (act)
35                 act->set_node(this);
36         enabled_array=(bool *)MYMALLOC(sizeof(bool)*num_threads);
37         if (enabled != NULL)
38                 memcpy(enabled_array, enabled, sizeof(bool)*num_threads);
39         else {
40                 for(int i=0;i<num_threads;i++)
41                         enabled_array[i]=false;
42         }
43 }
44
45 /** @brief Node desctructor */
46 Node::~Node()
47 {
48         if (action)
49                 delete action;
50         MYFREE(enabled_array);
51 }
52
53 /** Prints debugging info for the ModelAction associated with this Node */
54 void Node::print()
55 {
56         if (action)
57                 action->print();
58         else
59                 printf("******** empty action ********\n");
60 }
61
62 /** @brief Prints info about may_read_from set */
63 void Node::print_may_read_from()
64 {
65         for (unsigned int i = 0; i < may_read_from.size(); i++)
66                 may_read_from[i]->print();
67 }
68
69 /**
70  * Sets a promise to explore meeting with the given node.
71  * @param i is the promise index.
72  */
73 void Node::set_promise(unsigned int i) {
74         if (i >= promises.size())
75                 promises.resize(i + 1, PROMISE_IGNORE);
76         if (promises[i] == PROMISE_IGNORE)
77                 promises[i] = PROMISE_UNFULFILLED;
78 }
79
80 /**
81  * Looks up whether a given promise should be satisfied by this node.
82  * @param i The promise index.
83  * @return true if the promise should be satisfied by the given model action.
84  */
85 bool Node::get_promise(unsigned int i) {
86         return (i < promises.size()) && (promises[i] == PROMISE_FULFILLED);
87 }
88
89 /**
90  * Increments to the next combination of promises.
91  * @return true if we have a valid combination.
92  */
93 bool Node::increment_promise() {
94         for (unsigned int i = 0; i < promises.size(); i++) {
95                 if (promises[i] == PROMISE_UNFULFILLED) {
96                         promises[i] = PROMISE_FULFILLED;
97                         while (i > 0) {
98                                 i--;
99                                 if (promises[i] == PROMISE_FULFILLED)
100                                         promises[i] = PROMISE_UNFULFILLED;
101                         }
102                         return true;
103                 }
104         }
105         return false;
106 }
107
108 /**
109  * Returns whether the promise set is empty.
110  * @return true if we have explored all promise combinations.
111  */
112 bool Node::promise_empty() {
113         for (unsigned int i = 0; i < promises.size();i++)
114                 if (promises[i] == PROMISE_UNFULFILLED)
115                         return false;
116         return true;
117 }
118
119 /**
120  * Adds a value from a weakly ordered future write to backtrack to.
121  * @param value is the value to backtrack to.
122  */
123 bool Node::add_future_value(uint64_t value, modelclock_t expiration) {
124         int suitableindex=-1;
125         for (unsigned int i = 0; i < future_values.size(); i++) {
126                 if (future_values[i].value == value) {
127                         if (future_values[i].expiration>=expiration)
128                                 return false;
129                         if (future_index < i) {
130                                 suitableindex=i;
131                         }
132                 }
133         }
134
135         if (suitableindex!=-1) {
136                 future_values[suitableindex].expiration=expiration;
137                 return true;
138         }
139         struct future_value newfv={value, expiration};
140         future_values.push_back(newfv);
141         return true;
142 }
143
144 /**
145  * Checks whether the future_values set for this node is empty.
146  * @return true if the future_values set is empty.
147  */
148 bool Node::future_value_empty() {
149         return ((future_index + 1) >= future_values.size());
150 }
151
152 /**
153  * Checks if the Thread associated with this thread ID has been explored from
154  * this Node already.
155  * @param tid is the thread ID to check
156  * @return true if this thread choice has been explored already, false
157  * otherwise
158  */
159 bool Node::has_been_explored(thread_id_t tid)
160 {
161         int id = id_to_int(tid);
162         return explored_children[id];
163 }
164
165 /**
166  * Checks if the backtracking set is empty.
167  * @return true if the backtracking set is empty
168  */
169 bool Node::backtrack_empty()
170 {
171         return (numBacktracks == 0);
172 }
173
174 /**
175  * Checks whether the readsfrom set for this node is empty.
176  * @return true if the readsfrom set is empty.
177  */
178 bool Node::read_from_empty() {
179         return ((read_from_index+1) >= may_read_from.size());
180 }
181
182 /**
183  * Mark the appropriate backtracking information for exploring a thread choice.
184  * @param act The ModelAction to explore
185  */
186 void Node::explore_child(ModelAction *act)
187 {
188         explore(act->get_tid());
189 }
190
191 /**
192  * Records a backtracking reference for a thread choice within this Node.
193  * Provides feedback as to whether this thread choice is already set for
194  * backtracking.
195  * @return false if the thread was already set to be backtracked, true
196  * otherwise
197  */
198 bool Node::set_backtrack(thread_id_t id)
199 {
200         int i = id_to_int(id);
201         if (backtrack[i])
202                 return false;
203         backtrack[i] = true;
204         numBacktracks++;
205         return true;
206 }
207
208 thread_id_t Node::get_next_backtrack()
209 {
210         /** @todo Find next backtrack */
211         unsigned int i;
212         for (i = 0; i < backtrack.size(); i++)
213                 if (backtrack[i] == true)
214                         break;
215         /* Backtrack set was empty? */
216         ASSERT(i != backtrack.size());
217
218         backtrack[i] = false;
219         numBacktracks--;
220         return int_to_id(i);
221 }
222
223 bool Node::is_enabled(Thread *t)
224 {
225         int thread_id=id_to_int(t->get_id());
226         return thread_id < num_threads && enabled_array[thread_id];
227 }
228
229 bool Node::is_enabled(thread_id_t tid)
230 {
231         int thread_id=id_to_int(tid);
232         return thread_id < num_threads && enabled_array[thread_id];
233 }
234
235 /**
236  * Add an action to the may_read_from set.
237  * @param act is the action to add
238  */
239 void Node::add_read_from(const ModelAction *act)
240 {
241         may_read_from.push_back(act);
242 }
243
244 /**
245  * Gets the next 'future_value' value from this Node. Only valid for a node
246  * where this->action is a 'read'.
247  * @return The first element in future_values
248  */
249 uint64_t Node::get_future_value() {
250         ASSERT(future_index<future_values.size());
251         return future_values[future_index].value;
252 }
253
254 modelclock_t Node::get_future_value_expiration() {
255         ASSERT(future_index<future_values.size());
256         return future_values[future_index].expiration;
257 }
258
259
260 int Node::get_read_from_size() {
261         return may_read_from.size();
262 }
263
264 const ModelAction * Node::get_read_from_at(int i) {
265         return may_read_from[i];
266 }
267
268 /**
269  * Gets the next 'may_read_from' action from this Node. Only valid for a node
270  * where this->action is a 'read'.
271  * @return The first element in may_read_from
272  */
273 const ModelAction * Node::get_read_from() {
274         if (read_from_index < may_read_from.size())
275                 return may_read_from[read_from_index];
276         else
277                 return NULL;
278 }
279
280 /**
281  * Increments the index into the readsfrom set to explore the next item.
282  * @return Returns false if we have explored all items.
283  */
284 bool Node::increment_read_from() {
285         read_from_index++;
286         return (read_from_index < may_read_from.size());
287 }
288
289 /**
290  * Increments the index into the future_values set to explore the next item.
291  * @return Returns false if we have explored all values.
292  */
293 bool Node::increment_future_value() {
294         future_index++;
295         return (future_index < future_values.size());
296 }
297
298 void Node::explore(thread_id_t tid)
299 {
300         int i = id_to_int(tid);
301         if (backtrack[i]) {
302                 backtrack[i] = false;
303                 numBacktracks--;
304         }
305         explored_children[i] = true;
306 }
307
308 static void clear_node_list(node_list_t *list, node_list_t::iterator start,
309                                                node_list_t::iterator end)
310 {
311         node_list_t::iterator it;
312
313         for (it = start; it != end; it++)
314                 delete (*it);
315         list->erase(start, end);
316 }
317
318 NodeStack::NodeStack()
319         : total_nodes(0)
320 {
321         node_list.push_back(new Node());
322         total_nodes++;
323         iter = node_list.begin();
324 }
325
326 NodeStack::~NodeStack()
327 {
328         clear_node_list(&node_list, node_list.begin(), node_list.end());
329 }
330
331 void NodeStack::print()
332 {
333         node_list_t::iterator it;
334         printf("............................................\n");
335         printf("NodeStack printing node_list:\n");
336         for (it = node_list.begin(); it != node_list.end(); it++) {
337                 if (it == this->iter)
338                         printf("vvv following action is the current iterator vvv\n");
339                 (*it)->print();
340         }
341         printf("............................................\n");
342 }
343
344 ModelAction * NodeStack::explore_action(ModelAction *act, bool * is_enabled)
345 {
346         DBG();
347
348         ASSERT(!node_list.empty());
349         node_list_t::iterator it=iter;
350         it++;
351
352         if (it != node_list.end()) {
353                 iter++;
354                 return (*iter)->get_action();
355         }
356
357         /* Record action */
358         get_head()->explore_child(act);
359         node_list.push_back(new Node(act, get_head(), model->get_num_threads(), is_enabled));
360         total_nodes++;
361         iter++;
362         return NULL;
363 }
364
365 /**
366  * Empties the stack of all trailing nodes after a given position and calls the
367  * destructor for each. This function is provided an offset which determines
368  * how many nodes (relative to the current replay state) to save before popping
369  * the stack.
370  * @param numAhead gives the number of Nodes (including this Node) to skip over
371  * before removing nodes.
372  */
373 void NodeStack::pop_restofstack(int numAhead)
374 {
375         /* Diverging from previous execution; clear out remainder of list */
376         node_list_t::iterator it = iter;
377         while (numAhead--)
378                 it++;
379         clear_node_list(&node_list, it, node_list.end());
380 }
381
382 Node * NodeStack::get_head()
383 {
384         if (node_list.empty())
385                 return NULL;
386         return *iter;
387 }
388
389 Node * NodeStack::get_next()
390 {
391         node_list_t::iterator it = iter;
392         if (node_list.empty()) {
393                 DEBUG("Empty\n");
394                 return NULL;
395         }
396         it++;
397         if (it == node_list.end()) {
398                 DEBUG("At end\n");
399                 return NULL;
400         }
401         return *it;
402 }
403
404 void NodeStack::reset_execution()
405 {
406         iter = node_list.begin();
407 }