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