more implementation of scanalysis...
[model-checker.git] / nodestack.h
1 /** @file nodestack.h
2  *  @brief Stack of operations for use in backtracking.
3 */
4
5 #ifndef __NODESTACK_H__
6 #define __NODESTACK_H__
7
8 #include <cstddef>
9 #include <inttypes.h>
10
11 #include "mymemory.h"
12 #include "schedule.h"
13 #include "promise.h"
14 #include "stl-model.h"
15
16 class ModelAction;
17 class Thread;
18
19 struct fairness_info {
20         unsigned int enabled_count;
21         unsigned int turns;
22         bool priority;
23 };
24
25 /**
26  * @brief Types of read-from relations
27  *
28  * Our "may-read-from" set is composed of multiple types of reads, and we have
29  * to iterate through all of them in the backtracking search. This enumeration
30  * helps to identify which type of read-from we are currently observing.
31  */
32 typedef enum {
33         READ_FROM_PAST, /**< @brief Read from a prior, existing store */
34         READ_FROM_PROMISE, /**< @brief Read from an existing promised future value */
35         READ_FROM_FUTURE, /**< @brief Read from a newly-asserted future value */
36         READ_FROM_NONE, /**< @brief A NULL state, which should not be reached */
37 } read_from_type_t;
38
39 #define YIELD_E 1
40 #define YIELD_D 2
41 #define YIELD_S 4
42 #define YIELD_P 8
43 #define YIELD_INDEX(tid1, tid2, num_threads) (tid1*num_threads+tid2)
44
45
46 /**
47  * @brief A single node in a NodeStack
48  *
49  * Represents a single node in the NodeStack. Each Node is associated with up
50  * to one action and up to one parent node. A node holds information
51  * regarding the last action performed (the "associated action"), the thread
52  * choices that have been explored (explored_children) and should be explored
53  * (backtrack), and the actions that the last action may read from.
54  */
55 class Node {
56 public:
57         Node(ModelAction *act, Node *par, int nthreads, Node *prevfairness);
58         ~Node();
59         /* return true = thread choice has already been explored */
60         bool has_been_explored(thread_id_t tid) const;
61         /* return true = backtrack set is empty */
62         bool backtrack_empty() const;
63
64         void clear_backtracking();
65         void explore_child(ModelAction *act, enabled_type_t *is_enabled);
66         /* return false = thread was already in backtrack */
67         bool set_backtrack(thread_id_t id);
68         thread_id_t get_next_backtrack();
69         bool is_enabled(Thread *t) const;
70         bool is_enabled(thread_id_t tid) const;
71         enabled_type_t enabled_status(thread_id_t tid) const;
72
73         ModelAction * get_action() const { return action; }
74         void set_uninit_action(ModelAction *act) { uninit_action = act; }
75         ModelAction * get_uninit_action() const { return uninit_action; }
76
77         bool has_priority(thread_id_t tid) const;
78         void update_yield(Scheduler *);
79         bool has_priority_over(thread_id_t tid, thread_id_t tid2) const;
80         int get_num_threads() const { return num_threads; }
81         /** @return the parent Node to this Node; that is, the action that
82          * occurred previously in the stack. */
83         Node * get_parent() const { return parent; }
84
85         read_from_type_t get_read_from_status();
86         bool increment_read_from();
87         bool read_from_empty() const;
88         unsigned int read_from_size() const;
89
90         void print_read_from_past();
91         void add_read_from_past(const ModelAction *act);
92         const ModelAction * get_read_from_past() const;
93         const ModelAction * get_read_from_past(int i) const;
94         int get_read_from_past_size() const;
95
96         void add_read_from_promise(const ModelAction *reader);
97         Promise * get_read_from_promise() const;
98         Promise * get_read_from_promise(int i) const;
99         int get_read_from_promise_size() const;
100
101         bool add_future_value(struct future_value fv);
102         struct future_value get_future_value() const;
103
104         void set_promise(unsigned int i);
105         bool get_promise(unsigned int i) const;
106         bool increment_promise();
107         bool promise_empty() const;
108         void clear_promise_resolutions();
109
110         enabled_type_t *get_enabled_array() {return enabled_array;}
111
112         void set_misc_max(int i);
113         int get_misc() const;
114         bool increment_misc();
115         bool misc_empty() const;
116
117         void add_relseq_break(const ModelAction *write);
118         const ModelAction * get_relseq_break() const;
119         bool increment_relseq_break();
120         bool relseq_break_empty() const;
121
122         bool increment_behaviors();
123
124         void print() const;
125
126         MEMALLOC
127 private:
128         void explore(thread_id_t tid);
129         int get_yield_data(int tid1, int tid2) const;
130         bool read_from_past_empty() const;
131         bool increment_read_from_past();
132         bool read_from_promise_empty() const;
133         bool increment_read_from_promise();
134         bool future_value_empty() const;
135         bool increment_future_value();
136         read_from_type_t read_from_status;
137
138         ModelAction * const action;
139
140         /** @brief ATOMIC_UNINIT action which was created at this Node */
141         ModelAction *uninit_action;
142
143         Node * const parent;
144         const int num_threads;
145         ModelVector<bool> explored_children;
146         ModelVector<bool> backtrack;
147         ModelVector<struct fairness_info> fairness;
148         int numBacktracks;
149         enabled_type_t *enabled_array;
150
151         /**
152          * The set of past ModelActions that this the action at this Node may
153          * read from. Only meaningful if this Node represents a 'read' action.
154          */
155         ModelVector<const ModelAction *> read_from_past;
156         unsigned int read_from_past_idx;
157
158         ModelVector<const ModelAction *> read_from_promises;
159         int read_from_promise_idx;
160
161         ModelVector<struct future_value> future_values;
162         int future_index;
163
164         ModelVector<bool> resolve_promise;
165         int resolve_promise_idx;
166
167         ModelVector<const ModelAction *> relseq_break_writes;
168         int relseq_break_index;
169
170         int misc_index;
171         int misc_max;
172         int * yield_data;
173 };
174
175 typedef ModelVector<Node *> node_list_t;
176
177 /**
178  * @brief A stack of nodes
179  *
180  * Holds a Node linked-list that can be used for holding backtracking,
181  * may-read-from, and replay information. It is used primarily as a
182  * stack-like structure, in that backtracking points and replay nodes are
183  * only removed from the top (most recent).
184  */
185 class NodeStack {
186 public:
187         NodeStack();
188         ~NodeStack();
189         ModelAction * explore_action(ModelAction *act, enabled_type_t * is_enabled);
190         Node * get_head() const;
191         Node * get_next() const;
192         void reset_execution();
193         void pop_restofstack(int numAhead);
194         int get_total_nodes() { return total_nodes; }
195
196         void print() const;
197
198         MEMALLOC
199 private:
200         node_list_t node_list;
201
202         /**
203          * @brief the index position of the current head Node
204          *
205          * This index is relative to node_list. The index should point to the
206          * current head Node. It is negative when the list is empty.
207          */
208         int head_idx;
209
210         int total_nodes;
211 };
212
213 #endif /* __NODESTACK_H__ */