bc7fb98e515895d6317b8e74146ce47d342c577f
[c11tester.git] / execution.h
1 /** @file execution.h
2  *  @brief Model-checker core
3  */
4
5 #ifndef __EXECUTION_H__
6 #define __EXECUTION_H__
7
8 #include <cstddef>
9 #include <inttypes.h>
10
11 #include "mymemory.h"
12 #include "hashtable.h"
13 #include "workqueue.h"
14 #include "config.h"
15 #include "modeltypes.h"
16 #include "stl-model.h"
17 #include "params.h"
18
19 #include "mutex.h"
20 #include <condition_variable>
21
22 /* Forward declaration */
23 class Node;
24 class NodeStack;
25 class CycleGraph;
26 class Scheduler;
27 class Thread;
28 class ClockVector;
29 struct model_snapshot_members;
30 class ModelChecker;
31 struct bug_message;
32
33 /** @brief Shorthand for a list of release sequence heads */
34 typedef ModelVector<const ModelAction *> rel_heads_list_t;
35 typedef SnapList<ModelAction *> action_list_t;
36
37 struct PendingFutureValue {
38         PendingFutureValue(ModelAction *writer, ModelAction *reader) :
39                 writer(writer), reader(reader)
40         { }
41         const ModelAction *writer;
42         ModelAction *reader;
43 };
44
45 /** @brief Records information regarding a single pending release sequence */
46 struct release_seq {
47         /** @brief The acquire operation */
48         ModelAction *acquire;
49         /** @brief The read operation that may read from a release sequence;
50          *  may be the same as acquire, or else an earlier action in the same
51          *  thread (i.e., when 'acquire' is a fence-acquire) */
52         const ModelAction *read;
53         /** @brief The head of the RMW chain from which 'read' reads; may be
54          *  equal to 'release' */
55         const ModelAction *rf;
56         /** @brief The head of the potential longest release sequence chain */
57         const ModelAction *release;
58         /** @brief The write(s) that may break the release sequence */
59         SnapVector<const ModelAction *> writes;
60 };
61
62 /** @brief The central structure for model-checking */
63 class ModelExecution {
64 public:
65         ModelExecution(ModelChecker *m,
66                         const struct model_params *params,
67                         Scheduler *scheduler,
68                         NodeStack *node_stack);
69         ~ModelExecution();
70
71         const struct model_params * get_params() const { return params; }
72
73         Thread * take_step(ModelAction *curr);
74
75         void print_summary() const;
76 #if SUPPORT_MOD_ORDER_DUMP
77         void dumpGraph(char *filename) const;
78 #endif
79
80         void add_thread(Thread *t);
81         Thread * get_thread(thread_id_t tid) const;
82         Thread * get_thread(const ModelAction *act) const;
83
84         pthread_t get_pthread_counter() { return pthread_counter; }
85         void incr_pthread_counter() { pthread_counter++; }
86         Thread * get_pthread(pthread_t pid);
87
88         bool is_enabled(Thread *t) const;
89         bool is_enabled(thread_id_t tid) const;
90
91         thread_id_t get_next_id();
92         unsigned int get_num_threads() const;
93
94         ClockVector * get_cv(thread_id_t tid) const;
95         ModelAction * get_parent_action(thread_id_t tid) const;
96         bool isfeasibleprefix() const;
97
98         action_list_t * get_actions_on_obj(void * obj, thread_id_t tid) const;
99         ModelAction * get_last_action(thread_id_t tid) const;
100
101         bool check_action_enabled(ModelAction *curr);
102
103         bool assert_bug(const char *msg);
104         bool have_bug_reports() const;
105         SnapVector<bug_message *> * get_bugs() const;
106
107         bool has_asserted() const;
108         void set_assert();
109         bool is_complete_execution() const;
110
111         void print_infeasibility(const char *prefix) const;
112         bool is_infeasible() const;
113         bool is_deadlocked() const;
114         bool is_yieldblocked() const;
115         bool too_many_steps() const;
116
117         ModelAction * get_next_backtrack();
118
119         action_list_t * get_action_trace() { return &action_trace; }
120
121         CycleGraph * const get_mo_graph() { return mo_graph; }
122   HashTable<pthread_cond_t *, cdsc::condition_variable *, uintptr_t, 4> * getCondMap() {return &cond_map;}
123   HashTable<pthread_mutex_t *, cdsc::mutex *, uintptr_t, 4> * getMutexMap() {return &mutex_map;}
124   
125         SNAPSHOTALLOC
126 private:
127         int get_execution_number() const;
128         pthread_t pthread_counter;
129
130         ModelChecker *model;
131
132         const model_params * const params;
133
134         /** The scheduler to use: tracks the running/ready Threads */
135         Scheduler * const scheduler;
136
137         bool sleep_can_read_from(ModelAction *curr, const ModelAction *write);
138         bool thin_air_constraint_may_allow(const ModelAction *writer, const ModelAction *reader) const;
139         bool mo_may_allow(const ModelAction *writer, const ModelAction *reader);
140         void set_bad_synchronization();
141         void set_bad_sc_read();
142         bool should_wake_up(const ModelAction *curr, const Thread *thread) const;
143         void wake_up_sleeping_actions(ModelAction *curr);
144         modelclock_t get_next_seq_num();
145
146         bool next_execution();
147         ModelAction * check_current_action(ModelAction *curr);
148         bool initialize_curr_action(ModelAction **curr);
149         bool process_read(ModelAction *curr);
150         bool process_write(ModelAction *curr, work_queue_t *work);
151         bool process_fence(ModelAction *curr);
152         bool process_mutex(ModelAction *curr);
153
154         bool process_thread_action(ModelAction *curr);
155         bool read_from(ModelAction *act, const ModelAction *rf);
156         bool synchronize(const ModelAction *first, ModelAction *second);
157
158         template <typename T>
159         bool check_recency(ModelAction *curr, const T *rf) const;
160
161         template <typename T, typename U>
162         bool should_read_instead(const ModelAction *curr, const T *rf, const U *other_rf) const;
163
164         ModelAction * get_last_fence_conflict(ModelAction *act) const;
165         ModelAction * get_last_conflict(ModelAction *act) const;
166         void set_backtracking(ModelAction *act);
167         bool set_latest_backtrack(ModelAction *act);
168
169         void check_curr_backtracking(ModelAction *curr);
170         void add_action_to_lists(ModelAction *act);
171         ModelAction * get_last_fence_release(thread_id_t tid) const;
172         ModelAction * get_last_seq_cst_write(ModelAction *curr) const;
173         ModelAction * get_last_seq_cst_fence(thread_id_t tid, const ModelAction *before_fence) const;
174         ModelAction * get_last_unlock(ModelAction *curr) const;
175         void build_may_read_from(ModelAction *curr);
176         ModelAction * process_rmw(ModelAction *curr);
177
178         template <typename rf_type>
179         bool r_modification_order(ModelAction *curr, const rf_type *rf);
180
181         bool w_modification_order(ModelAction *curr);
182         void get_release_seq_heads(ModelAction *acquire, ModelAction *read, rel_heads_list_t *release_heads);
183         bool release_seq_heads(const ModelAction *rf, rel_heads_list_t *release_heads, struct release_seq *pending) const;
184         void propagate_clockvector(ModelAction *acquire, work_queue_t *work);
185         bool resolve_release_sequences(void *location, work_queue_t *work_queue);
186         ModelAction * get_uninitialized_action(const ModelAction *curr) const;
187
188         action_list_t action_trace;
189         SnapVector<Thread *> thread_map;
190         SnapVector<Thread *> pthread_map;
191
192         /** Per-object list of actions. Maps an object (i.e., memory location)
193          * to a trace of all actions performed on the object. */
194         HashTable<const void *, action_list_t *, uintptr_t, 4> obj_map;
195
196         /** Per-object list of actions. Maps an object (i.e., memory location)
197          * to a trace of all actions performed on the object. */
198         HashTable<const void *, action_list_t *, uintptr_t, 4> condvar_waiters_map;
199
200         HashTable<void *, SnapVector<action_list_t> *, uintptr_t, 4> obj_thrd_map;
201
202   HashTable<pthread_mutex_t *, cdsc::mutex *, uintptr_t, 4> mutex_map;
203         HashTable<pthread_cond_t *, cdsc::condition_variable *, uintptr_t, 4> cond_map;
204
205         /**
206          * List of pending release sequences. Release sequences might be
207          * determined lazily as promises are fulfilled and modification orders
208          * are established. Each entry in the list may only be partially
209          * filled, depending on its pending status.
210          */
211         SnapVector<struct release_seq *> pending_rel_seqs;
212
213         SnapVector<ModelAction *> thrd_last_action;
214         SnapVector<ModelAction *> thrd_last_fence_release;
215         NodeStack * const node_stack;
216
217         /** A special model-checker Thread; used for associating with
218          *  model-checker-related ModelAcitons */
219         Thread *model_thread;
220
221         /** Private data members that should be snapshotted. They are grouped
222          * together for efficiency and maintainability. */
223         struct model_snapshot_members * const priv;
224
225         /**
226          * @brief The modification order graph
227          *
228          * A directed acyclic graph recording observations of the modification
229          * order on all the atomic objects in the system. This graph should
230          * never contain any cycles, as that represents a violation of the
231          * memory model (total ordering). This graph really consists of many
232          * disjoint (unconnected) subgraphs, each graph corresponding to a
233          * separate ordering on a distinct object.
234          *
235          * The edges in this graph represent the "ordered before" relation,
236          * such that <tt>a --> b</tt> means <tt>a</tt> was ordered before
237          * <tt>b</tt>.
238          */
239         CycleGraph * const mo_graph;
240
241         Thread * action_select_next_thread(const ModelAction *curr) const;
242 };
243
244 #endif /* __EXECUTION_H__ */