CBMC
event_graph.h
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: graph of abstract events
4 
5 Author: Vincent Nimal
6 
7 Date: 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 
29 class messaget;
30 
33 
35 {
36 public:
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 
96  critical_cyclet(event_grapht &_egraph, unsigned _id)
97  :egraph(_egraph), id(_id), has_user_defined_fence(false)
98  {
99  }
100 
101  void operator()(const critical_cyclet &cyc)
102  {
103  data.clear();
104  for(auto it=cyc.data.cbegin();
105  it!=cyc.data.cend();
106  ++it)
107  data.push_back(*it);
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) */
133  void hide_internals(critical_cyclet &reduced) const;
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 
152  bool is_not_uniproc(memory_modelt model) const
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 
169  explicit delayt(event_idt _first):
170  first(_first), is_po(true)
171  {
172  }
173 
174  delayt(event_idt _first, event_idt _second):
175  first(_first), second(_second), is_po(false)
176  {
177  }
178 
179  delayt(event_idt _first, event_idt _second, bool _is_po):
180  first(_first), second(_second), is_po(_is_po)
181  {
182  }
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  {
211  if(hide_internals)
212  {
213  critical_cyclet reduced(egraph, id);
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 
238 protected:
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:
294  event_grapht &_egraph,
295  unsigned _max_var,
296  unsigned _max_po_trans):
297  egraph(_egraph),
298  max_var(_max_var),
299  max_po_trans(_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,
316  event_idt vertex,
317  bool unsafe_met,
318  event_idt po_trans,
319  bool same_var_pair,
320  bool lwsync_met,
321  bool has_to_be_unsafe,
322  irep_idt var_to_avoid,
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:
338  graph_conc_explorert(event_grapht &_egraph, unsigned _max_var,
339  unsigned _max_po_trans, const std::set<event_idt> &_filter)
340  :graph_explorert(_egraph, _max_var, _max_po_trans), filter(_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:
372  graph_pensieve_explorert(event_grapht &_egraph, unsigned _max_var,
373  unsigned _max_po_trans)
374  :graph_explorert(_egraph, _max_var, _max_po_trans), naive(false)
375  {}
376 
377  void set_naive() {naive=true;}
378  void collect_pairs();
379  };
380 
381 public:
382  explicit event_grapht(messaget &_message):
383  max_var(0),
384  max_po_trans(0),
385  ignore_arrays(false),
386  filter_thin_air(true),
387  filter_uniproc(true),
388  message(_message)
389  {
390  }
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  {
407  const event_idt po_no=po_graph.add_node();
408  const event_idt com_no=com_graph.add_node();
409  INVARIANT(po_no==com_no, "node added with same id in both graphs");
410  return po_no;
411  }
412 
414  {
415  return po_graph[n];
416  }
417 
418  bool has_po_edge(event_idt i, event_idt j) const
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);
457  po_graph.add_edge(a, b);
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);
466  po_graph.add_edge(a, b);
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);
476  com_graph.add_edge(a, b);
477  poUrfe_order.push_back(a);
478  }
479 
481  {
482  PRECONDITION(a != b);
483  add_com_edge(a, b);
484  add_com_edge(b, a);
485  }
486 
488  {
489  po_graph.remove_edge(a, b);
490  }
491 
493  {
494  com_graph.remove_edge(a, b);
495  }
496 
498  {
499  remove_po_edge(a, b);
500  remove_com_edge(a, b);
501  }
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();
541  com_graph.clear();
542  map_data_dp.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  {
555  graph_conc_explorert exploration(*this, max_var, max_po_trans, filter);
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  {
562  graph_explorert exploration(*this, max_var, max_po_trans);
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  {
571  max_var = _max_var;
572  max_po_trans = _max_po_trans;
573  ignore_arrays = _ignore_arrays;
574  }
575 
576  /* collects all the pairs of events with respectively at least one cmp,
577  regardless of the architecture (Pensieve'05 strategy) */
579  {
580  graph_pensieve_explorert exploration(*this, max_var, max_po_trans);
581  exploration.collect_pairs();
582  }
583 
585  {
586  graph_pensieve_explorert exploration(*this, max_var, max_po_trans);
587  exploration.set_naive();
588  exploration.collect_pairs();
589  }
590 };
591 #endif // CPROVER_GOTO_INSTRUMENT_WMM_EVENT_GRAPH_H
abstract events
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
const value_type & back() const
Definition: event_graph.h:92
std::list< event_idt > data_typet
Definition: event_graph.h:40
const value_type & front() const
Definition: event_graph.h:89
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_iterator cend() const
Definition: event_graph.h:80
const_iterator cbegin() const
Definition: event_graph.h:76
std::set< delayt > unsafe_pairs
Definition: event_graph.h:198
bool is_not_uniproc(memory_modelt model) const
Definition: event_graph.h:152
std::string print_name(const critical_cyclet &redyced, memory_modelt model) const
std::string print_name(memory_modelt model) const
Definition: event_graph.h:205
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)
Definition: event_graph.h:101
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
Definition: event_graph.h:209
void compute_unsafe_pairs(memory_modelt model)
Definition: event_graph.h:145
std::string print_output() const
bool operator<(const critical_cyclet &other) const
Definition: event_graph.h:232
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)
Definition: event_graph.h:140
const std::set< event_idt > & filter
Definition: event_graph.h:335
std::list< event_idt > * initial_filtering(std::list< event_idt > *order)
Definition: event_graph.h:349
graph_conc_explorert(event_grapht &_egraph, unsigned _max_var, unsigned _max_po_trans, const std::set< event_idt > &_filter)
Definition: event_graph.h:338
std::set< event_idt > thin_air_events
Definition: event_graph.h:286
std::map< irep_idt, unsigned char > reads_per_variable
Definition: event_graph.h:265
std::stack< event_idt > marked_stack
Definition: event_graph.h:306
std::set< event_idt > skip_tracked
Definition: event_graph.h:309
std::stack< event_idt > point_stack
Definition: event_graph.h:307
std::map< irep_idt, unsigned char > writes_per_variable
Definition: event_graph.h:264
virtual bool filtering(event_idt)
Definition: event_graph.h:269
std::map< event_idt, bool > mark
Definition: event_graph.h:305
graph_explorert(event_grapht &_egraph, unsigned _max_var, unsigned _max_po_trans)
Definition: event_graph.h:293
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
Definition: event_graph.h:266
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
virtual std::list< event_idt > * order_filtering(std::list< event_idt > *order)
Definition: event_graph.h:274
void filter_thin_air(std::set< critical_cyclet > &set_of_cycles)
after the collection, eliminates the executions forbidden by an indirect thin-air
std::set< event_idt > visited_nodes
Definition: event_graph.h:366
graph_pensieve_explorert(event_grapht &_egraph, unsigned _max_var, unsigned _max_po_trans)
Definition: event_graph.h:372
const wmm_grapht::edgest & com_in(event_idt n) const
Definition: event_graph.h:443
wmm_grapht po_graph
Definition: event_graph.h:240
grapht< abstract_eventt >::nodet & operator[](event_idt n)
Definition: event_graph.h:413
void clear()
Definition: event_graph.h:538
void add_undirected_com_edge(event_idt a, event_idt b)
Definition: event_graph.h:480
std::list< event_idt > poUrfe_order
Definition: event_graph.h:401
void collect_cycles(std::set< critical_cyclet > &set_of_cycles, memory_modelt model)
Definition: event_graph.h:559
unsigned max_po_trans
Definition: event_graph.h:245
std::set< std::pair< event_idt, event_idt > > loops
Definition: event_graph.h:403
void print_graph()
Definition: event_graph.cpp:56
unsigned max_var
Definition: event_graph.h:244
bool has_com_edge(event_idt i, event_idt j) const
Definition: event_graph.h:423
std::list< event_idt > po_order
Definition: event_graph.h:400
bool ignore_arrays
Definition: event_graph.h:246
void explore_copy_segment(std::set< event_idt > &explored, event_idt begin, event_idt end) const
copies the segment
Definition: event_graph.cpp:73
void remove_po_edge(event_idt a, event_idt b)
Definition: event_graph.h:487
event_idt copy_segment(event_idt begin, event_idt end)
Definition: event_graph.cpp:91
void collect_pairs_naive()
Definition: event_graph.h:584
bool has_po_edge(event_idt i, event_idt j) const
Definition: event_graph.h:418
std::size_t size() const
Definition: event_graph.h:428
const wmm_grapht::edgest & com_out(event_idt n) const
Definition: event_graph.h:448
void collect_pairs()
Definition: event_graph.h:578
event_grapht(messaget &_message)
Definition: event_graph.h:382
bool are_po_ordered(event_idt a, event_idt b)
Definition: event_graph.h:519
const wmm_grapht::edgest & po_out(event_idt n) const
Definition: event_graph.h:438
void remove_com_edge(event_idt a, event_idt b)
Definition: event_graph.h:492
void set_parameters_collection(unsigned _max_var=0, unsigned _max_po_trans=0, bool _ignore_arrays=false)
Definition: event_graph.h:566
bool is_local(event_idt a)
Definition: event_graph.h:513
void collect_cycles(std::set< critical_cyclet > &set_of_cycles, memory_modelt model, const std::set< event_idt > &filter)
Definition: event_graph.h:551
std::map< unsigned, data_dpt > map_data_dp
Definition: event_graph.h:397
wmm_grapht com_graph
Definition: event_graph.h:241
std::set< std::pair< const abstract_eventt &, const abstract_eventt & > > duplicated_bodies
Definition: event_graph.h:511
void add_com_edge(event_idt a, event_idt b)
Definition: event_graph.h:473
messaget & message
Definition: event_graph.h:394
void add_po_edge(event_idt a, event_idt b)
Definition: event_graph.h:453
void remove_edge(event_idt a, event_idt b)
Definition: event_graph.h:497
const wmm_grapht::edgest & po_in(event_idt n) const
Definition: event_graph.h:433
void print_rec_graph(std::ofstream &file, event_idt node_id, std::set< event_idt > &visited)
Definition: event_graph.cpp:28
bool filter_uniproc
Definition: event_graph.h:393
void add_po_back_edge(event_idt a, event_idt b)
Definition: event_graph.h:462
bool filter_thin_air
Definition: event_graph.h:392
event_idt add_node()
Definition: event_graph.h:405
const edgest & in(node_indext n) const
Definition: graph.h:222
nodet::node_indext node_indext
Definition: graph.h:173
nodet::edgest edgest
Definition: graph.h:170
bool has_edge(node_indext i, node_indext j) const
Definition: graph.h:192
node_indext add_node(arguments &&... values)
Definition: graph.h:180
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
const edgest & out(node_indext n) const
Definition: graph.h:227
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:29
A Template Class for Graphs.
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
delayt(event_idt _first, event_idt _second, bool _is_po)
Definition: event_graph.h:179
delayt(event_idt _first, event_idt _second)
Definition: event_graph.h:174
bool operator==(const delayt &other) const
Definition: event_graph.h:184
bool operator<(const delayt &other) const
Definition: event_graph.h:190
memory models
memory_modelt
Definition: wmm.h:18
@ RMO
Definition: wmm.h:22