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