CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
event_graph.h
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: graph of abstract events
4
5Author: Vincent Nimal
6
7Date: 2012
8
9\*******************************************************************/
10
13
14#ifndef CPROVER_GOTO_INSTRUMENT_WMM_EVENT_GRAPH_H
15#define CPROVER_GOTO_INSTRUMENT_WMM_EVENT_GRAPH_H
16
17#include <list>
18#include <set>
19#include <map>
20#include <iosfwd>
21
22#include <util/graph.h>
23#include <util/invariant.h>
24
25#include "abstract_event.h"
26#include "data_dp.h"
27#include "wmm.h"
28
29class messaget;
30
33
35{
36public:
37 /* critical cycle */
38 class critical_cyclet final
39 {
40 typedef std::list<event_idt> data_typet;
42
44
45 bool is_not_uniproc() const;
46 bool is_not_weak_uniproc() const;
47
48 std::string print_detail(const critical_cyclet &reduced,
49 std::map<std::string, std::string> &map_id2var,
50 std::map<std::string, std::string> &map_var2id) const;
51 std::string print_name(const critical_cyclet &redyced,
52 memory_modelt model) const;
53
54 bool check_AC(
55 data_typet::const_iterator s_it,
56 const abstract_eventt &first,
57 const abstract_eventt &second) const;
58 bool check_BC(
59 data_typet::const_iterator it,
60 const abstract_eventt &first,
61 const abstract_eventt &second) const;
62
63 public:
64 unsigned id;
66
67 // NOLINTNEXTLINE(readability/identifiers)
68 typedef data_typet::iterator iterator;
69 // NOLINTNEXTLINE(readability/identifiers)
70 typedef data_typet::const_iterator const_iterator;
71 // NOLINTNEXTLINE(readability/identifiers)
72 typedef data_typet::value_type value_type;
73
74 iterator begin() { return data.begin(); }
75 const_iterator begin() const { return data.begin(); }
76 const_iterator cbegin() const { return data.cbegin(); }
77
78 iterator end() { return data.end(); }
79 const_iterator end() const { return data.end(); }
80 const_iterator cend() const { return data.cend(); }
81
82 template <typename T>
83 void push_front(T &&t) { data.push_front(std::forward<T>(t)); }
84
85 template <typename T>
86 void push_back(T &&t) { data.push_back(std::forward<T>(t)); }
87
88 value_type &front() { return data.front(); }
89 const value_type &front() const { return data.front(); }
90
91 value_type &back() { return data.back(); }
92 const value_type &back() const { return data.back(); }
93
94 size_t size() const { return data.size(); }
95
100
102 {
103 data.clear();
104 for(auto it=cyc.data.cbegin();
105 it!=cyc.data.cend();
106 ++it)
107 data.push_back(*it);
108 has_user_defined_fence=cyc.has_user_defined_fence;
109 }
110
111 bool is_cycle()
112 {
113 /* size check */
114 if(data.size()<4)
115 return false;
116
117 /* po order check */
118 auto it=data.cbegin();
119 auto n_it=it;
120 ++n_it;
121 for(; it!=data.cend() && n_it!=data.cend(); ++it, ++n_it)
122 {
123 if(egraph[*it].thread==egraph[*n_it].thread
124 && !egraph.are_po_ordered(*it, *n_it))
125 return false;
126 }
127
128 return true;
129 }
130
131 /* removes internal events (e.g. podWW Rfi gives podWR)
132 from.hide_internals(&target) */
134
137 bool is_unsafe(memory_modelt model, bool fast=false);
138
139 /* do not update the unsafe pairs set */
141 {
142 return is_unsafe(model, true);
143 }
144
146 {
147 is_unsafe(model);
148 }
149
150 bool is_unsafe_asm(memory_modelt model, bool fast=false);
151
153 {
154 if(model==RMO)
155 return is_not_weak_uniproc();
156 else
157 return is_not_uniproc();
158 }
159
160 bool is_not_thin_air() const;
161
162 /* pair of events in a cycle */
163 struct delayt
164 {
167 bool is_po;
168
171 {
172 }
173
178
183
184 bool operator==(const delayt &other) const
185 {
186 return (is_po ? first==other.first :
187 first==other.first && second==other.second);
188 }
189
190 bool operator<(const delayt &other) const
191 {
192 return (is_po ? first<other.first :
193 first<other.first ||
194 (first==other.first && second<other.second));
195 }
196 };
197
198 std::set<delayt> unsafe_pairs;
199
200 /* print events or ids in the cycles*/
201 std::string print() const;
202 std::string print_events() const;
203
204 /* print outputs */
205 std::string print_name(memory_modelt model) const
206 {
207 return print_name(*this, model);
208 }
209 std::string print_name(memory_modelt model, bool hide_internals) const
210 {
212 {
214 this->hide_internals(reduced);
215 INVARIANT(!reduced.data.empty(), "reduced must not be empty");
216 return print_name(reduced, model);
217 }
218 else
219 return print_name(*this, model);
220 }
221
222 std::string print_unsafes() const;
223 std::string print_output() const;
224 std::string print_all(memory_modelt model,
225 std::map<std::string, std::string> &map_id2var,
226 std::map<std::string, std::string> &map_var2id,
227 bool hide_internals) const;
228
229 void print_dot(std::ostream &str,
230 unsigned colour, memory_modelt model) const;
231
232 bool operator<(const critical_cyclet &other) const
233 {
234 return data<other.data;
235 }
236 };
237
238protected:
239 /* graph contains po and com transitions */
242
243 /* parameters limiting the exploration */
244 unsigned max_var;
245 unsigned max_po_trans;
247
248 /* graph explorer (for each cycles collection) */
250 {
251 public:
253 {
254 }
255
256 protected:
258
259 /* parameters limiting the exploration */
260 unsigned max_var;
261 unsigned max_po_trans;
262
263 /* constraints for graph exploration */
264 std::map<irep_idt, unsigned char> writes_per_variable;
265 std::map<irep_idt, unsigned char> reads_per_variable;
266 std::map<unsigned, unsigned char> events_per_thread;
267
268 /* for thread and filtering in backtrack */
269 virtual inline bool filtering(event_idt)
270 {
271 return false;
272 }
273
274 virtual inline std::list<event_idt>* order_filtering(
275 std::list<event_idt>* order)
276 {
277 return order;
278 }
279
280 /* number of cycles met so far */
281 unsigned cycle_nb;
282
283 /* events in thin-air executions met so far */
284 /* any execution blocked by thin-air is guaranteed
285 to have all its events in this set */
286 std::set<event_idt> thin_air_events;
287
288 /* after the collection, eliminates the executions forbidden by an
289 indirect thin-air */
290 void filter_thin_air(std::set<critical_cyclet> &set_of_cycles);
291
292 public:
295 unsigned _max_var,
296 unsigned _max_po_trans):
300 cycle_nb(0)
301 {
302 }
303
304 /* structures for graph exploration */
305 std::map<event_idt, bool> mark;
306 std::stack<event_idt> marked_stack;
307 std::stack<event_idt> point_stack;
308
309 std::set<event_idt> skip_tracked;
310
312 event_idt source, unsigned number_of_cycles);
313
314 bool backtrack(std::set<critical_cyclet> &set_of_cycles,
315 event_idt source,
317 bool unsafe_met,
319 bool same_var_pair,
320 bool lwsync_met,
321 bool has_to_be_unsafe,
323 memory_modelt model);
324
325 /* Tarjan 1972 adapted and modified for events + po-transitivity */
326 void collect_cycles(
327 std::set<critical_cyclet> &set_of_cycles,
328 memory_modelt model);
329 };
330
331 /* explorer for thread */
333 {
334 protected:
335 const std::set<event_idt> &filter;
336
337 public:
339 unsigned _max_po_trans, const std::set<event_idt> &_filter)
341 {
342 }
343
345 {
346 return filter.find(u)==filter.end();
347 }
348
349 std::list<event_idt>* initial_filtering(std::list<event_idt>* order)
350 {
351 static std::list<event_idt> new_order;
352
353 /* intersection */
354 for(const auto &evt : *order)
355 if(filter.find(evt)!=filter.end())
356 new_order.push_back(evt);
357
358 return &new_order;
359 }
360 };
361
362 /* explorer for pairs collection a la Pensieve */
364 {
365 protected:
366 std::set<event_idt> visited_nodes;
367 bool naive;
368
369 bool find_second_event(event_idt source);
370
371 public:
376
377 void set_naive() {naive=true;}
378 void collect_pairs();
379 };
380
381public:
391
395
396 /* data dependencies per thread */
397 std::map<unsigned, data_dpt> map_data_dp;
398
399 /* orders */
400 std::list<event_idt> po_order;
401 std::list<event_idt> poUrfe_order;
402
403 std::set<std::pair<event_idt, event_idt> > loops;
404
406 {
409 INVARIANT(po_no==com_no, "node added with same id in both graphs");
410 return po_no;
411 }
412
417
419 {
420 return po_graph.has_edge(i, j);
421 }
422
424 {
425 return com_graph.has_edge(i, j);
426 }
427
428 std::size_t size() const
429 {
430 return po_graph.size();
431 }
432
434 {
435 return po_graph.in(n);
436 }
437
439 {
440 return po_graph.out(n);
441 }
442
444 {
445 return com_graph.in(n);
446 }
447
449 {
450 return com_graph.out(n);
451 }
452
454 {
455 PRECONDITION(a != b);
456 PRECONDITION(operator[](a).thread == operator[](b).thread);
458 po_order.push_back(a);
459 poUrfe_order.push_back(a);
460 }
461
463 {
464 PRECONDITION(a != b);
465 PRECONDITION(operator[](a).thread == operator[](b).thread);
467 po_order.push_back(a);
468 poUrfe_order.push_back(a);
469 loops.insert(std::pair<event_idt, event_idt>(a, b));
470 loops.insert(std::pair<event_idt, event_idt>(b, a));
471 }
472
474 {
475 PRECONDITION(a != b);
477 poUrfe_order.push_back(a);
478 }
479
486
491
496
502
503 /* copies the sub-graph G between begin and end into G', connects
504 G.end with G'.begin, and returns G'.end */
505 void explore_copy_segment(std::set<event_idt> &explored, event_idt begin,
506 event_idt end) const;
508
509 /* to keep track of the loop already copied */
510 std::set<std::pair<const abstract_eventt&, const abstract_eventt&>>
512
514 {
515 return operator[](a).local;
516 }
517
518 /* a -po-> b -- transitive */
520 {
521 if(operator[](a).thread!=operator[](b).thread)
522 return false;
523
524 /* if back-edge, a-po->b \/ b-po->a */
525 if( loops.find(std::pair<event_idt, event_idt>(a, b))!=loops.end() )
526 return true;
527
528 // would be true if no cycle in po
529 for(const auto &evt : po_order)
530 if(evt==a)
531 return true;
532 else if(evt==b)
533 return false;
534
535 return false;
536 }
537
538 void clear()
539 {
540 po_graph.clear();
543 }
544
545 /* prints to graph.dot */
546 void print_graph();
547 void print_rec_graph(std::ofstream &file, event_idt node_id,
548 std::set<event_idt> &visited);
549
550 /* Tarjan 1972 adapted and modified for events + po-transitivity */
551 void collect_cycles(std::set<critical_cyclet> &set_of_cycles,
552 memory_modelt model,
553 const std::set<event_idt> &filter)
554 {
556 exploration.collect_cycles(set_of_cycles, model);
557 }
558
559 void collect_cycles(std::set<critical_cyclet> &set_of_cycles,
560 memory_modelt model)
561 {
563 exploration.collect_cycles(set_of_cycles, model);
564 }
565
567 unsigned _max_var=0,
568 unsigned _max_po_trans=0,
569 bool _ignore_arrays=false)
570 {
574 }
575
576 /* collects all the pairs of events with respectively at least one cmp,
577 regardless of the architecture (Pensieve'05 strategy) */
579 {
581 exploration.collect_pairs();
582 }
583
585 {
587 exploration.set_naive();
588 exploration.collect_pairs();
589 }
590};
591#endif // CPROVER_GOTO_INSTRUMENT_WMM_EVENT_GRAPH_H
abstract events
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
std::string print_events() const
const_iterator end() const
Definition event_graph.h:79
void hide_internals(critical_cyclet &reduced) const
data_typet::const_iterator const_iterator
Definition event_graph.h:70
std::string print_unsafes() const
std::list< event_idt > data_typet
Definition event_graph.h:40
bool is_unsafe(memory_modelt model, bool fast=false)
checks whether there is at least one pair which is unsafe (takes fences and dependencies into account...
bool is_unsafe_asm(memory_modelt model, bool fast=false)
same as is_unsafe, but with ASM fences
bool check_AC(data_typet::const_iterator s_it, const abstract_eventt &first, const abstract_eventt &second) const
const value_type & front() const
Definition event_graph.h:89
const value_type & back() const
Definition event_graph.h:92
const_iterator cend() const
Definition event_graph.h:80
const_iterator cbegin() const
Definition event_graph.h:76
std::set< delayt > unsafe_pairs
bool is_not_uniproc(memory_modelt model) const
std::string print_name(const critical_cyclet &redyced, memory_modelt model) const
std::string print_name(memory_modelt model) const
std::string print_all(memory_modelt model, std::map< std::string, std::string > &map_id2var, std::map< std::string, std::string > &map_var2id, bool hide_internals) const
bool check_BC(data_typet::const_iterator it, const abstract_eventt &first, const abstract_eventt &second) const
void print_dot(std::ostream &str, unsigned colour, memory_modelt model) const
const_iterator begin() const
Definition event_graph.h:75
void operator()(const critical_cyclet &cyc)
std::string print_detail(const critical_cyclet &reduced, std::map< std::string, std::string > &map_id2var, std::map< std::string, std::string > &map_var2id) const
critical_cyclet(event_grapht &_egraph, unsigned _id)
Definition event_graph.h:96
std::string print_name(memory_modelt model, bool hide_internals) const
void compute_unsafe_pairs(memory_modelt model)
std::string print_output() const
bool operator<(const critical_cyclet &other) const
data_typet::value_type value_type
Definition event_graph.h:72
data_typet::iterator iterator
Definition event_graph.h:68
bool is_unsafe_fast(memory_modelt model)
const std::set< event_idt > & filter
std::list< event_idt > * initial_filtering(std::list< event_idt > *order)
graph_conc_explorert(event_grapht &_egraph, unsigned _max_var, unsigned _max_po_trans, const std::set< event_idt > &_filter)
std::set< event_idt > thin_air_events
std::map< irep_idt, unsigned char > reads_per_variable
std::stack< event_idt > marked_stack
virtual std::list< event_idt > * order_filtering(std::list< event_idt > *order)
std::set< event_idt > skip_tracked
std::stack< event_idt > point_stack
std::map< irep_idt, unsigned char > writes_per_variable
virtual bool filtering(event_idt)
std::map< event_idt, bool > mark
graph_explorert(event_grapht &_egraph, unsigned _max_var, unsigned _max_po_trans)
critical_cyclet extract_cycle(event_idt vertex, event_idt source, unsigned number_of_cycles)
extracts a (whole, unreduced) cycle from the stack.
std::map< unsigned, unsigned char > events_per_thread
void collect_cycles(std::set< critical_cyclet > &set_of_cycles, memory_modelt model)
Tarjan 1972 adapted and modified for events.
bool backtrack(std::set< critical_cyclet > &set_of_cycles, event_idt source, event_idt vertex, bool unsafe_met, event_idt po_trans, bool same_var_pair, bool lwsync_met, bool has_to_be_unsafe, irep_idt var_to_avoid, memory_modelt model)
see event_grapht::collect_cycles
graph_pensieve_explorert(event_grapht &_egraph, unsigned _max_var, unsigned _max_po_trans)
wmm_grapht po_graph
void add_undirected_com_edge(event_idt a, event_idt b)
std::list< event_idt > poUrfe_order
void collect_cycles(std::set< critical_cyclet > &set_of_cycles, memory_modelt model)
unsigned max_po_trans
std::set< std::pair< event_idt, event_idt > > loops
void print_graph()
unsigned max_var
grapht< abstract_eventt >::nodet & operator[](event_idt n)
bool has_com_edge(event_idt i, event_idt j) const
std::list< event_idt > po_order
void explore_copy_segment(std::set< event_idt > &explored, event_idt begin, event_idt end) const
copies the segment
void remove_po_edge(event_idt a, event_idt b)
event_idt copy_segment(event_idt begin, event_idt end)
void collect_pairs_naive()
bool has_po_edge(event_idt i, event_idt j) const
std::size_t size() const
void collect_pairs()
event_grapht(messaget &_message)
const wmm_grapht::edgest & po_out(event_idt n) const
const wmm_grapht::edgest & com_in(event_idt n) const
bool are_po_ordered(event_idt a, event_idt b)
void remove_com_edge(event_idt a, event_idt b)
void set_parameters_collection(unsigned _max_var=0, unsigned _max_po_trans=0, bool _ignore_arrays=false)
const wmm_grapht::edgest & po_in(event_idt n) const
bool is_local(event_idt a)
void collect_cycles(std::set< critical_cyclet > &set_of_cycles, memory_modelt model, const std::set< event_idt > &filter)
std::map< unsigned, data_dpt > map_data_dp
wmm_grapht com_graph
std::set< std::pair< const abstract_eventt &, const abstract_eventt & > > duplicated_bodies
void add_com_edge(event_idt a, event_idt b)
messaget & message
const wmm_grapht::edgest & com_out(event_idt n) const
void add_po_edge(event_idt a, event_idt b)
void remove_edge(event_idt a, event_idt b)
void print_rec_graph(std::ofstream &file, event_idt node_id, std::set< event_idt > &visited)
bool filter_uniproc
void add_po_back_edge(event_idt a, event_idt b)
bool filter_thin_air
event_idt add_node()
nodet::node_indext node_indext
Definition graph.h:173
nodet::edgest edgest
Definition graph.h:170
const edgest & out(node_indext n) const
Definition graph.h:227
bool has_edge(node_indext i, node_indext j) const
Definition graph.h:192
node_indext add_node(arguments &&... values)
Definition graph.h:180
const edgest & in(node_indext n) const
Definition graph.h:222
void add_edge(node_indext a, node_indext b)
Definition graph.h:232
std::size_t size() const
Definition graph.h:212
void clear()
Definition graph.h:260
void remove_edge(node_indext a, node_indext b)
Definition graph.h:238
Class that provides messages with a built-in verbosity 'level'.
Definition message.h:154
data dependencies
wmm_grapht::node_indext event_idt
Definition event_graph.h:32
grapht< abstract_eventt > wmm_grapht
Definition event_graph.h:31
A Template Class for Graphs.
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
delayt(event_idt _first, event_idt _second, bool _is_po)
delayt(event_idt _first, event_idt _second)
bool operator==(const delayt &other) const
bool operator<(const delayt &other) const
memory models
memory_modelt
Definition wmm.h:18
@ RMO
Definition wmm.h:22