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