action: add get_mutex()
[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  * Gets a particular 'read-from-promise' form this Node. Only vlaid for a node
467  * where this->action is a 'read'.
468  * @param i The index of the Promise to get
469  * @return The Promise at index i, if the Promise is still available; NULL
470  * otherwise
471  */
472 Promise * Node::get_read_from_promise(int i) const
473 {
474         return read_from_promises[i]->get_reads_from_promise();
475 }
476
477 /** @return The size of the read-from-promise set */
478 int Node::get_read_from_promise_size() const
479 {
480         return read_from_promises.size();
481 }
482
483 /**
484  * Checks whether the read_from_promises set for this node is empty.
485  * @return true if the read_from_promises set is empty.
486  */
487 bool Node::read_from_promise_empty() const
488 {
489         return ((read_from_promise_idx + 1) >= ((int)read_from_promises.size()));
490 }
491
492 /**
493  * Increments the index into the read_from_promises set to explore the next item.
494  * @return Returns false if we have explored all promises.
495  */
496 bool Node::increment_read_from_promise()
497 {
498         DBG();
499         if (read_from_promise_idx < ((int)read_from_promises.size())) {
500                 read_from_promise_idx++;
501                 return (read_from_promise_idx < ((int)read_from_promises.size()));
502         }
503         return false;
504 }
505
506 /************************* end read_from_promises *****************************/
507
508 /****************************** future values *********************************/
509
510 /**
511  * Adds a value from a weakly ordered future write to backtrack to. This
512  * operation may "fail" if the future value has already been run (within some
513  * sloppiness window of this expiration), or if the futurevalues set has
514  * reached its maximum.
515  * @see model_params.maxfuturevalues
516  *
517  * @param value is the value to backtrack to.
518  * @return True if the future value was successully added; false otherwise
519  */
520 bool Node::add_future_value(struct future_value fv)
521 {
522         uint64_t value = fv.value;
523         modelclock_t expiration = fv.expiration;
524         thread_id_t tid = fv.tid;
525         int idx = -1; /* Highest index where value is found */
526         for (unsigned int i = 0; i < future_values.size(); i++) {
527                 if (future_values[i].value == value && future_values[i].tid == tid) {
528                         if (expiration <= future_values[i].expiration)
529                                 return false;
530                         idx = i;
531                 }
532         }
533         if (idx > future_index) {
534                 /* Future value hasn't been explored; update expiration */
535                 future_values[idx].expiration = expiration;
536                 return true;
537         } else if (idx >= 0 && expiration <= future_values[idx].expiration + model->params.expireslop) {
538                 /* Future value has been explored and is within the "sloppy" window */
539                 return false;
540         }
541
542         /* Limit the size of the future-values set */
543         if (model->params.maxfuturevalues > 0 &&
544                         (int)future_values.size() >= model->params.maxfuturevalues)
545                 return false;
546
547         future_values.push_back(fv);
548         return true;
549 }
550
551 /**
552  * Gets the next 'future_value' from this Node. Only valid for a node where
553  * this->action is a 'read'.
554  * @return The first element in future_values
555  */
556 struct future_value Node::get_future_value() const
557 {
558         ASSERT(future_index >= 0 && future_index < ((int)future_values.size()));
559         return future_values[future_index];
560 }
561
562 /**
563  * Checks whether the future_values set for this node is empty.
564  * @return true if the future_values set is empty.
565  */
566 bool Node::future_value_empty() const
567 {
568         return ((future_index + 1) >= ((int)future_values.size()));
569 }
570
571 /**
572  * Increments the index into the future_values set to explore the next item.
573  * @return Returns false if we have explored all values.
574  */
575 bool Node::increment_future_value()
576 {
577         DBG();
578         if (future_index < ((int)future_values.size())) {
579                 future_index++;
580                 return (future_index < ((int)future_values.size()));
581         }
582         return false;
583 }
584
585 /************************** end future values *********************************/
586
587 /**
588  * Add a write ModelAction to the set of writes that may break the release
589  * sequence. This is used during replay exploration of pending release
590  * sequences. This Node must correspond to a release sequence fixup action.
591  *
592  * @param write The write that may break the release sequence. NULL means we
593  * allow the release sequence to synchronize.
594  */
595 void Node::add_relseq_break(const ModelAction *write)
596 {
597         relseq_break_writes.push_back(write);
598 }
599
600 /**
601  * Get the write that may break the current pending release sequence,
602  * according to the replay / divergence pattern.
603  *
604  * @return A write that may break the release sequence. If NULL, that means
605  * the release sequence should not be broken.
606  */
607 const ModelAction * Node::get_relseq_break() const
608 {
609         if (relseq_break_index < (int)relseq_break_writes.size())
610                 return relseq_break_writes[relseq_break_index];
611         else
612                 return NULL;
613 }
614
615 /**
616  * Increments the index into the relseq_break_writes set to explore the next
617  * item.
618  * @return Returns false if we have explored all values.
619  */
620 bool Node::increment_relseq_break()
621 {
622         DBG();
623         if (relseq_break_index < ((int)relseq_break_writes.size())) {
624                 relseq_break_index++;
625                 return (relseq_break_index < ((int)relseq_break_writes.size()));
626         }
627         return false;
628 }
629
630 /**
631  * @return True if all writes that may break the release sequence have been
632  * explored
633  */
634 bool Node::relseq_break_empty() const
635 {
636         return ((relseq_break_index + 1) >= ((int)relseq_break_writes.size()));
637 }
638
639 void Node::explore(thread_id_t tid)
640 {
641         int i = id_to_int(tid);
642         ASSERT(i < ((int)backtrack.size()));
643         if (backtrack[i]) {
644                 backtrack[i] = false;
645                 numBacktracks--;
646         }
647         explored_children[i] = true;
648 }
649
650 NodeStack::NodeStack() :
651         node_list(),
652         head_idx(-1),
653         total_nodes(0)
654 {
655         total_nodes++;
656 }
657
658 NodeStack::~NodeStack()
659 {
660         for (unsigned int i = 0; i < node_list.size(); i++)
661                 delete node_list[i];
662 }
663
664 void NodeStack::print() const
665 {
666         model_print("............................................\n");
667         model_print("NodeStack printing node_list:\n");
668         for (unsigned int it = 0; it < node_list.size(); it++) {
669                 if ((int)it == this->head_idx)
670                         model_print("vvv following action is the current iterator vvv\n");
671                 node_list[it]->print();
672         }
673         model_print("............................................\n");
674 }
675
676 /** Note: The is_enabled set contains what actions were enabled when
677  *  act was chosen. */
678 ModelAction * NodeStack::explore_action(ModelAction *act, enabled_type_t *is_enabled)
679 {
680         DBG();
681
682         if ((head_idx + 1) < (int)node_list.size()) {
683                 head_idx++;
684                 return node_list[head_idx]->get_action();
685         }
686
687         /* Record action */
688         Node *head = get_head();
689         Node *prevfairness = NULL;
690         if (head) {
691                 head->explore_child(act, is_enabled);
692                 if (model->params.fairwindow != 0 && head_idx > (int)model->params.fairwindow)
693                         prevfairness = node_list[head_idx - model->params.fairwindow];
694         }
695
696         int next_threads = model->get_num_threads();
697         if (act->get_type() == THREAD_CREATE)
698                 next_threads++;
699         node_list.push_back(new Node(act, head, next_threads, prevfairness));
700         total_nodes++;
701         head_idx++;
702         return NULL;
703 }
704
705 /**
706  * Empties the stack of all trailing nodes after a given position and calls the
707  * destructor for each. This function is provided an offset which determines
708  * how many nodes (relative to the current replay state) to save before popping
709  * the stack.
710  * @param numAhead gives the number of Nodes (including this Node) to skip over
711  * before removing nodes.
712  */
713 void NodeStack::pop_restofstack(int numAhead)
714 {
715         /* Diverging from previous execution; clear out remainder of list */
716         unsigned int it = head_idx + numAhead;
717         for (unsigned int i = it; i < node_list.size(); i++)
718                 delete node_list[i];
719         node_list.resize(it);
720         node_list.back()->clear_backtracking();
721 }
722
723 Node * NodeStack::get_head() const
724 {
725         if (node_list.empty() || head_idx < 0)
726                 return NULL;
727         return node_list[head_idx];
728 }
729
730 Node * NodeStack::get_next() const
731 {
732         if (node_list.empty()) {
733                 DEBUG("Empty\n");
734                 return NULL;
735         }
736         unsigned int it = head_idx + 1;
737         if (it == node_list.size()) {
738                 DEBUG("At end\n");
739                 return NULL;
740         }
741         return node_list[it];
742 }
743
744 void NodeStack::reset_execution()
745 {
746         head_idx = -1;
747 }