action: bugfix - reads-from value should be VALUE_NONE for new actions
[c11tester.git] / nodestack.cc
1 #define __STDC_FORMAT_MACROS
2 #include <inttypes.h>
3
4 #include <string.h>
5
6 #include "nodestack.h"
7 #include "action.h"
8 #include "common.h"
9 #include "model.h"
10 #include "threads-model.h"
11 #include "modeltypes.h"
12
13 /**
14  * @brief Node constructor
15  *
16  * Constructs a single Node for use in a NodeStack. Each Node is associated
17  * with exactly one ModelAction (exception: the first Node should be created
18  * as an empty stub, to represent the first thread "choice") and up to one
19  * parent.
20  *
21  * @param act The ModelAction to associate with this Node. May be NULL.
22  * @param par The parent Node in the NodeStack. May be NULL if there is no
23  * parent.
24  * @param nthreads The number of threads which exist at this point in the
25  * execution trace.
26  */
27 Node::Node(ModelAction *act, Node *par, int nthreads, Node *prevfairness) :
28         read_from_status(READ_FROM_PAST),
29         action(act),
30         parent(par),
31         num_threads(nthreads),
32         explored_children(num_threads),
33         backtrack(num_threads),
34         fairness(num_threads),
35         numBacktracks(0),
36         enabled_array(NULL),
37         read_from_past(),
38         read_from_past_idx(0),
39         read_from_promises(),
40         read_from_promise_idx(-1),
41         future_values(),
42         future_index(-1),
43         resolve_promise(),
44         resolve_promise_idx(-1),
45         relseq_break_writes(),
46         relseq_break_index(0),
47         misc_index(0),
48         misc_max(0)
49 {
50         ASSERT(act);
51         act->set_node(this);
52         int currtid = id_to_int(act->get_tid());
53         int prevtid = prevfairness ? id_to_int(prevfairness->action->get_tid()) : 0;
54
55         if (model->params.fairwindow != 0) {
56                 for (int i = 0; i < num_threads; i++) {
57                         ASSERT(i < ((int)fairness.size()));
58                         struct fairness_info *fi = &fairness[i];
59                         struct fairness_info *prevfi = (parent && i < parent->get_num_threads()) ? &parent->fairness[i] : NULL;
60                         if (prevfi) {
61                                 *fi = *prevfi;
62                         }
63                         if (parent && parent->is_enabled(int_to_id(i))) {
64                                 fi->enabled_count++;
65                         }
66                         if (i == currtid) {
67                                 fi->turns++;
68                                 fi->priority = false;
69                         }
70                         /* Do window processing */
71                         if (prevfairness != NULL) {
72                                 if (prevfairness->parent->is_enabled(int_to_id(i)))
73                                         fi->enabled_count--;
74                                 if (i == prevtid) {
75                                         fi->turns--;
76                                 }
77                                 /* Need full window to start evaluating
78                                  * conditions
79                                  * If we meet the enabled count and have no
80                                  * turns, give us priority */
81                                 if ((fi->enabled_count >= model->params.enabledcount) &&
82                                                 (fi->turns == 0))
83                                         fi->priority = true;
84                         }
85                 }
86         }
87 }
88
89 /** @brief Node desctructor */
90 Node::~Node()
91 {
92         delete action;
93         if (enabled_array)
94                 model_free(enabled_array);
95 }
96
97 /** Prints debugging info for the ModelAction associated with this Node */
98 void Node::print() const
99 {
100         action->print();
101         model_print("          backtrack: %s", backtrack_empty() ? "empty" : "non-empty ");
102         for (int i = 0; i < (int)backtrack.size(); i++)
103                 if (backtrack[i] == true)
104                         model_print("[%d]", i);
105         model_print("\n");
106
107         model_print("          read from past: %s", read_from_past_empty() ? "empty" : "non-empty ");
108         for (int i = read_from_past_idx + 1; i < (int)read_from_past.size(); i++)
109                 model_print("[%d]", read_from_past[i]->get_seq_number());
110         model_print("\n");
111
112         model_print("          read-from promises: %s", read_from_promise_empty() ? "empty" : "non-empty ");
113         for (int i = read_from_promise_idx + 1; i < (int)read_from_promises.size(); i++)
114                 model_print("[%d]", read_from_promises[i]->get_seq_number());
115         model_print("\n");
116
117         model_print("          future values: %s", future_value_empty() ? "empty" : "non-empty ");
118         for (int i = future_index + 1; i < (int)future_values.size(); i++)
119                 model_print("[%#" PRIx64 "]", future_values[i].value);
120         model_print("\n");
121
122         model_print("          promises: %s\n", promise_empty() ? "empty" : "non-empty");
123         model_print("          misc: %s\n", misc_empty() ? "empty" : "non-empty");
124         model_print("          rel seq break: %s\n", relseq_break_empty() ? "empty" : "non-empty");
125 }
126
127 /*********************************** promise **********************************/
128
129 /**
130  * Sets a promise to explore meeting with the given node.
131  * @param i is the promise index.
132  */
133 void Node::set_promise(unsigned int i)
134 {
135         if (i >= resolve_promise.size())
136                 resolve_promise.resize(i + 1, false);
137         resolve_promise[i] = true;
138 }
139
140 /**
141  * Looks up whether a given promise should be satisfied by this node.
142  * @param i The promise index.
143  * @return true if the promise should be satisfied by the given ModelAction.
144  */
145 bool Node::get_promise(unsigned int i) const
146 {
147         return (i < resolve_promise.size()) && (int)i == resolve_promise_idx;
148 }
149
150 /**
151  * Increments to the next promise to resolve.
152  * @return true if we have a valid combination.
153  */
154 bool Node::increment_promise()
155 {
156         DBG();
157         if (resolve_promise.empty())
158                 return false;
159         int prev_idx = resolve_promise_idx;
160         resolve_promise_idx++;
161         for ( ; resolve_promise_idx < (int)resolve_promise.size(); resolve_promise_idx++)
162                 if (resolve_promise[resolve_promise_idx])
163                         return true;
164         resolve_promise_idx = prev_idx;
165         return false;
166 }
167
168 /**
169  * Returns whether the promise set is empty.
170  * @return true if we have explored all promise combinations.
171  */
172 bool Node::promise_empty() const
173 {
174         for (int i = resolve_promise_idx + 1; i < (int)resolve_promise.size(); i++)
175                 if (i >= 0 && resolve_promise[i])
176                         return false;
177         return true;
178 }
179
180 /** @brief Clear any promise-resolution information for this Node */
181 void Node::clear_promise_resolutions()
182 {
183         resolve_promise.clear();
184         resolve_promise_idx = -1;
185 }
186
187 /******************************* end promise **********************************/
188
189 void Node::set_misc_max(int i)
190 {
191         misc_max = i;
192 }
193
194 int Node::get_misc() const
195 {
196         return misc_index;
197 }
198
199 bool Node::increment_misc()
200 {
201         return (misc_index < misc_max) && ((++misc_index) < misc_max);
202 }
203
204 bool Node::misc_empty() const
205 {
206         return (misc_index + 1) >= misc_max;
207 }
208
209 /**
210  * Checks if the Thread associated with this thread ID has been explored from
211  * this Node already.
212  * @param tid is the thread ID to check
213  * @return true if this thread choice has been explored already, false
214  * otherwise
215  */
216 bool Node::has_been_explored(thread_id_t tid) const
217 {
218         int id = id_to_int(tid);
219         return explored_children[id];
220 }
221
222 /**
223  * Checks if the backtracking set is empty.
224  * @return true if the backtracking set is empty
225  */
226 bool Node::backtrack_empty() const
227 {
228         return (numBacktracks == 0);
229 }
230
231 /**
232  * Mark the appropriate backtracking information for exploring a thread choice.
233  * @param act The ModelAction to explore
234  */
235 void Node::explore_child(ModelAction *act, enabled_type_t *is_enabled)
236 {
237         if (!enabled_array)
238                 enabled_array = (enabled_type_t *)model_malloc(sizeof(enabled_type_t) * num_threads);
239         if (is_enabled != NULL)
240                 memcpy(enabled_array, is_enabled, sizeof(enabled_type_t) * num_threads);
241         else {
242                 for (int i = 0; i < num_threads; i++)
243                         enabled_array[i] = THREAD_DISABLED;
244         }
245
246         explore(act->get_tid());
247 }
248
249 /**
250  * Records a backtracking reference for a thread choice within this Node.
251  * Provides feedback as to whether this thread choice is already set for
252  * backtracking.
253  * @return false if the thread was already set to be backtracked, true
254  * otherwise
255  */
256 bool Node::set_backtrack(thread_id_t id)
257 {
258         int i = id_to_int(id);
259         ASSERT(i < ((int)backtrack.size()));
260         if (backtrack[i])
261                 return false;
262         backtrack[i] = true;
263         numBacktracks++;
264         return true;
265 }
266
267 thread_id_t Node::get_next_backtrack()
268 {
269         /** @todo Find next backtrack */
270         unsigned int i;
271         for (i = 0; i < backtrack.size(); i++)
272                 if (backtrack[i] == true)
273                         break;
274         /* Backtrack set was empty? */
275         ASSERT(i != backtrack.size());
276
277         backtrack[i] = false;
278         numBacktracks--;
279         return int_to_id(i);
280 }
281
282 void Node::clear_backtracking()
283 {
284         for (unsigned int i = 0; i < backtrack.size(); i++)
285                 backtrack[i] = false;
286         for (unsigned int i = 0; i < explored_children.size(); i++)
287                 explored_children[i] = false;
288         numBacktracks = 0;
289 }
290
291 bool Node::is_enabled(Thread *t) const
292 {
293         int thread_id = id_to_int(t->get_id());
294         return thread_id < num_threads && (enabled_array[thread_id] != THREAD_DISABLED);
295 }
296
297 enabled_type_t Node::enabled_status(thread_id_t tid) const
298 {
299         int thread_id = id_to_int(tid);
300         if (thread_id < num_threads)
301                 return enabled_array[thread_id];
302         else
303                 return THREAD_DISABLED;
304 }
305
306 bool Node::is_enabled(thread_id_t tid) const
307 {
308         int thread_id = id_to_int(tid);
309         return thread_id < num_threads && (enabled_array[thread_id] != THREAD_DISABLED);
310 }
311
312 bool Node::has_priority(thread_id_t tid) const
313 {
314         return fairness[id_to_int(tid)].priority;
315 }
316
317 /*********************************** read from ********************************/
318
319 /**
320  * Get the current state of the may-read-from set iteration
321  * @return The read-from type we should currently be checking (past or future)
322  */
323 read_from_type_t Node::get_read_from_status()
324 {
325         if (read_from_status == READ_FROM_PAST && read_from_past.empty())
326                 increment_read_from();
327         return read_from_status;
328 }
329
330 /**
331  * Iterate one step in the may-read-from iteration. This includes a step in
332  * reading from the either the past or the future.
333  * @return True if there is a new read-from to explore; false otherwise
334  */
335 bool Node::increment_read_from()
336 {
337         clear_promise_resolutions();
338         if (increment_read_from_past()) {
339                read_from_status = READ_FROM_PAST;
340                return true;
341         } else if (increment_read_from_promise()) {
342                 read_from_status = READ_FROM_PROMISE;
343                 return true;
344         } else if (increment_future_value()) {
345                 read_from_status = READ_FROM_FUTURE;
346                 return true;
347         }
348         read_from_status = READ_FROM_NONE;
349         return false;
350 }
351
352 /**
353  * @return True if there are any new read-froms to explore
354  */
355 bool Node::read_from_empty() const
356 {
357         return read_from_past_empty() &&
358                 read_from_promise_empty() &&
359                 future_value_empty();
360 }
361
362 /**
363  * Get the total size of the may-read-from set, including both past and future
364  * values
365  * @return The size of may-read-from
366  */
367 unsigned int Node::read_from_size() const
368 {
369         return read_from_past.size() +
370                 read_from_promises.size() +
371                 future_values.size();
372 }
373
374 /******************************* end read from ********************************/
375
376 /****************************** read from past ********************************/
377
378 /** @brief Prints info about read_from_past set */
379 void Node::print_read_from_past()
380 {
381         for (unsigned int i = 0; i < read_from_past.size(); i++)
382                 read_from_past[i]->print();
383 }
384
385 /**
386  * Add an action to the read_from_past set.
387  * @param act is the action to add
388  */
389 void Node::add_read_from_past(const ModelAction *act)
390 {
391         read_from_past.push_back(act);
392 }
393
394 /**
395  * Gets the next 'read_from_past' action from this Node. Only valid for a node
396  * where this->action is a 'read'.
397  * @return The first element in read_from_past
398  */
399 const ModelAction * Node::get_read_from_past() const
400 {
401         if (read_from_past_idx < read_from_past.size())
402                 return read_from_past[read_from_past_idx];
403         else
404                 return NULL;
405 }
406
407 const ModelAction * Node::get_read_from_past(int i) const
408 {
409         return read_from_past[i];
410 }
411
412 int Node::get_read_from_past_size() const
413 {
414         return read_from_past.size();
415 }
416
417 /**
418  * Checks whether the readsfrom set for this node is empty.
419  * @return true if the readsfrom set is empty.
420  */
421 bool Node::read_from_past_empty() const
422 {
423         return ((read_from_past_idx + 1) >= read_from_past.size());
424 }
425
426 /**
427  * Increments the index into the readsfrom set to explore the next item.
428  * @return Returns false if we have explored all items.
429  */
430 bool Node::increment_read_from_past()
431 {
432         DBG();
433         if (read_from_past_idx < read_from_past.size()) {
434                 read_from_past_idx++;
435                 return read_from_past_idx < read_from_past.size();
436         }
437         return false;
438 }
439
440 /************************** end read from past ********************************/
441
442 /***************************** read_from_promises *****************************/
443
444 /**
445  * Add an action to the read_from_promises set.
446  * @param reader The read which generated the Promise; we use the ModelAction
447  * instead of the Promise because the Promise does not last across executions
448  */
449 void Node::add_read_from_promise(const ModelAction *reader)
450 {
451         read_from_promises.push_back(reader);
452 }
453
454 /**
455  * Gets the next 'read-from-promise' from this Node. Only valid for a node
456  * where this->action is a 'read'.
457  * @return The current element in read_from_promises
458  */
459 Promise * Node::get_read_from_promise() const
460 {
461         ASSERT(read_from_promise_idx >= 0 && read_from_promise_idx < ((int)read_from_promises.size()));
462         return read_from_promises[read_from_promise_idx]->get_reads_from_promise();
463 }
464
465 /**
466  * Checks whether the read_from_promises set for this node is empty.
467  * @return true if the read_from_promises set is empty.
468  */
469 bool Node::read_from_promise_empty() const
470 {
471         return ((read_from_promise_idx + 1) >= ((int)read_from_promises.size()));
472 }
473
474 /**
475  * Increments the index into the read_from_promises set to explore the next item.
476  * @return Returns false if we have explored all promises.
477  */
478 bool Node::increment_read_from_promise()
479 {
480         DBG();
481         if (read_from_promise_idx < ((int)read_from_promises.size())) {
482                 read_from_promise_idx++;
483                 return (read_from_promise_idx < ((int)read_from_promises.size()));
484         }
485         return false;
486 }
487
488 /************************* end read_from_promises *****************************/
489
490 /****************************** future values *********************************/
491
492 /**
493  * Adds a value from a weakly ordered future write to backtrack to. This
494  * operation may "fail" if the future value has already been run (within some
495  * sloppiness window of this expiration), or if the futurevalues set has
496  * reached its maximum.
497  * @see model_params.maxfuturevalues
498  *
499  * @param value is the value to backtrack to.
500  * @return True if the future value was successully added; false otherwise
501  */
502 bool Node::add_future_value(struct future_value fv)
503 {
504         uint64_t value = fv.value;
505         modelclock_t expiration = fv.expiration;
506         thread_id_t tid = fv.tid;
507         int idx = -1; /* Highest index where value is found */
508         for (unsigned int i = 0; i < future_values.size(); i++) {
509                 if (future_values[i].value == value && future_values[i].tid == tid) {
510                         if (expiration <= future_values[i].expiration)
511                                 return false;
512                         idx = i;
513                 }
514         }
515         if (idx > future_index) {
516                 /* Future value hasn't been explored; update expiration */
517                 future_values[idx].expiration = expiration;
518                 return true;
519         } else if (idx >= 0 && expiration <= future_values[idx].expiration + model->params.expireslop) {
520                 /* Future value has been explored and is within the "sloppy" window */
521                 return false;
522         }
523
524         /* Limit the size of the future-values set */
525         if (model->params.maxfuturevalues > 0 &&
526                         (int)future_values.size() >= model->params.maxfuturevalues)
527                 return false;
528
529         future_values.push_back(fv);
530         return true;
531 }
532
533 /**
534  * Gets the next 'future_value' from this Node. Only valid for a node where
535  * this->action is a 'read'.
536  * @return The first element in future_values
537  */
538 struct future_value Node::get_future_value() const
539 {
540         ASSERT(future_index >= 0 && future_index < ((int)future_values.size()));
541         return future_values[future_index];
542 }
543
544 /**
545  * Checks whether the future_values set for this node is empty.
546  * @return true if the future_values set is empty.
547  */
548 bool Node::future_value_empty() const
549 {
550         return ((future_index + 1) >= ((int)future_values.size()));
551 }
552
553 /**
554  * Increments the index into the future_values set to explore the next item.
555  * @return Returns false if we have explored all values.
556  */
557 bool Node::increment_future_value()
558 {
559         DBG();
560         if (future_index < ((int)future_values.size())) {
561                 future_index++;
562                 return (future_index < ((int)future_values.size()));
563         }
564         return false;
565 }
566
567 /************************** end future values *********************************/
568
569 /**
570  * Add a write ModelAction to the set of writes that may break the release
571  * sequence. This is used during replay exploration of pending release
572  * sequences. This Node must correspond to a release sequence fixup action.
573  *
574  * @param write The write that may break the release sequence. NULL means we
575  * allow the release sequence to synchronize.
576  */
577 void Node::add_relseq_break(const ModelAction *write)
578 {
579         relseq_break_writes.push_back(write);
580 }
581
582 /**
583  * Get the write that may break the current pending release sequence,
584  * according to the replay / divergence pattern.
585  *
586  * @return A write that may break the release sequence. If NULL, that means
587  * the release sequence should not be broken.
588  */
589 const ModelAction * Node::get_relseq_break() const
590 {
591         if (relseq_break_index < (int)relseq_break_writes.size())
592                 return relseq_break_writes[relseq_break_index];
593         else
594                 return NULL;
595 }
596
597 /**
598  * Increments the index into the relseq_break_writes set to explore the next
599  * item.
600  * @return Returns false if we have explored all values.
601  */
602 bool Node::increment_relseq_break()
603 {
604         DBG();
605         if (relseq_break_index < ((int)relseq_break_writes.size())) {
606                 relseq_break_index++;
607                 return (relseq_break_index < ((int)relseq_break_writes.size()));
608         }
609         return false;
610 }
611
612 /**
613  * @return True if all writes that may break the release sequence have been
614  * explored
615  */
616 bool Node::relseq_break_empty() const
617 {
618         return ((relseq_break_index + 1) >= ((int)relseq_break_writes.size()));
619 }
620
621 void Node::explore(thread_id_t tid)
622 {
623         int i = id_to_int(tid);
624         ASSERT(i < ((int)backtrack.size()));
625         if (backtrack[i]) {
626                 backtrack[i] = false;
627                 numBacktracks--;
628         }
629         explored_children[i] = true;
630 }
631
632 NodeStack::NodeStack() :
633         node_list(),
634         head_idx(-1),
635         total_nodes(0)
636 {
637         total_nodes++;
638 }
639
640 NodeStack::~NodeStack()
641 {
642         for (unsigned int i = 0; i < node_list.size(); i++)
643                 delete node_list[i];
644 }
645
646 void NodeStack::print() const
647 {
648         model_print("............................................\n");
649         model_print("NodeStack printing node_list:\n");
650         for (unsigned int it = 0; it < node_list.size(); it++) {
651                 if ((int)it == this->head_idx)
652                         model_print("vvv following action is the current iterator vvv\n");
653                 node_list[it]->print();
654         }
655         model_print("............................................\n");
656 }
657
658 /** Note: The is_enabled set contains what actions were enabled when
659  *  act was chosen. */
660 ModelAction * NodeStack::explore_action(ModelAction *act, enabled_type_t *is_enabled)
661 {
662         DBG();
663
664         if ((head_idx + 1) < (int)node_list.size()) {
665                 head_idx++;
666                 return node_list[head_idx]->get_action();
667         }
668
669         /* Record action */
670         Node *head = get_head();
671         Node *prevfairness = NULL;
672         if (head) {
673                 head->explore_child(act, is_enabled);
674                 if (model->params.fairwindow != 0 && head_idx > (int)model->params.fairwindow)
675                         prevfairness = node_list[head_idx - model->params.fairwindow];
676         }
677
678         int next_threads = model->get_num_threads();
679         if (act->get_type() == THREAD_CREATE)
680                 next_threads++;
681         node_list.push_back(new Node(act, head, next_threads, prevfairness));
682         total_nodes++;
683         head_idx++;
684         return NULL;
685 }
686
687 /**
688  * Empties the stack of all trailing nodes after a given position and calls the
689  * destructor for each. This function is provided an offset which determines
690  * how many nodes (relative to the current replay state) to save before popping
691  * the stack.
692  * @param numAhead gives the number of Nodes (including this Node) to skip over
693  * before removing nodes.
694  */
695 void NodeStack::pop_restofstack(int numAhead)
696 {
697         /* Diverging from previous execution; clear out remainder of list */
698         unsigned int it = head_idx + numAhead;
699         for (unsigned int i = it; i < node_list.size(); i++)
700                 delete node_list[i];
701         node_list.resize(it);
702         node_list.back()->clear_backtracking();
703 }
704
705 Node * NodeStack::get_head() const
706 {
707         if (node_list.empty() || head_idx < 0)
708                 return NULL;
709         return node_list[head_idx];
710 }
711
712 Node * NodeStack::get_next() const
713 {
714         if (node_list.empty()) {
715                 DEBUG("Empty\n");
716                 return NULL;
717         }
718         unsigned int it = head_idx + 1;
719         if (it == node_list.size()) {
720                 DEBUG("At end\n");
721                 return NULL;
722         }
723         return node_list[it];
724 }
725
726 void NodeStack::reset_execution()
727 {
728         head_idx = -1;
729 }