mc2lib
model12.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2016, Marco Elver
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the
15  * distribution.
16  *
17  * * Neither the name of the software nor the names of its contributors
18  * may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 #ifndef MC2LIB_MEMCONSISTENCY_MODEL12_HPP_
35 #define MC2LIB_MEMCONSISTENCY_MODEL12_HPP_
36 
37 #include <memory>
38 
39 #include "eventsets.hpp"
40 
41 namespace mc2lib {
42 namespace memconsistency {
43 
54 namespace model12 {
55 
56 class ExecWitness {
57  public:
58  template <class FilterFunc>
59  EventRel fr(FilterFunc filter_func) const {
60  EventRel er;
61 
62  for (const auto& rf_tuples : rf.get()) {
63  const auto ws_reach = ws.Reachable(rf_tuples.first);
64  for (const auto& ws_w : ws_reach.get()) {
65  for (const auto& rf_r : rf_tuples.second.get()) {
66  if (filter_func(std::make_pair(rf_tuples.first, rf_r),
67  std::make_pair(rf_tuples.first, ws_w))) {
68  er.Insert(rf_r, ws_w);
69  }
70  }
71  }
72  }
73 
74  return er;
75  }
76 
77  EventRel fr() const {
78  return fr([](const EventRel::Tuple& t1, const EventRel::Tuple& t2) {
79  return true;
80  });
81  }
82 
83  EventRel fri() const {
84  return fr([](const EventRel::Tuple& t1, const EventRel::Tuple& t2) {
85  return t1.second.iiid.pid == t2.second.iiid.pid;
86  });
87  }
88 
89  EventRel fre() const {
90  return fr([](const EventRel::Tuple& t1, const EventRel::Tuple& t2) {
91  return t1.second.iiid.pid != t2.second.iiid.pid;
92  });
93  }
94 
95  EventRel rfi() const {
96  return rf.Filter([](const Event& e1, const Event& e2) {
97  return e1.iiid.pid == e2.iiid.pid;
98  });
99  }
100 
101  EventRel rfe() const {
102  return rf.Filter([](const Event& e1, const Event& e2) {
103  return e1.iiid.pid != e2.iiid.pid;
104  });
105  }
106 
107  EventRel wsi() const {
108  return ws.Filter([](const Event& e1, const Event& e2) {
109  return e1.iiid.pid == e2.iiid.pid;
110  });
111  }
112 
113  EventRel wse() const {
114  return ws.Filter([](const Event& e1, const Event& e2) {
115  return e1.iiid.pid != e2.iiid.pid;
116  });
117  }
118 
119  EventRel com() const { return rf | ws | fr(); }
120 
121  EventRel po_loc() const {
122  return po.Filter(
123  [](const Event& e1, const Event& e2) { return e1.addr == e2.addr; });
124  }
125 
126  void Clear() {
127  events.Clear();
128  po.Clear();
129  dp.Clear();
130  rf.Clear();
131  ws.Clear();
132  }
133 
134  public:
140 };
141 
142 class Checker;
143 
145  public:
146  virtual ~Architecture() {}
147 
148  virtual void Clear() {}
149 
153  virtual std::unique_ptr<Checker> MakeChecker(
154  const Architecture* arch, const ExecWitness* exec) const = 0;
155 
156  virtual EventRel ppo(const ExecWitness& ew) const = 0;
157  virtual EventRel grf(const ExecWitness& ew) const = 0;
158  virtual EventRel ab(const ExecWitness& ew) const = 0;
159 
160  virtual EventRel ghb(const ExecWitness& ew) const {
161  return ew.ws | ew.fr() | ppo(ew) | grf(ew) | ab(ew);
162  }
163 
167  virtual Event::Type EventTypeRead() const = 0;
168 
172  virtual Event::Type EventTypeWrite() const = 0;
173 };
174 
175 class Checker {
176  public:
177  Checker(const Architecture* arch, const ExecWitness* exec)
178  : arch_(arch), exec_(exec) {}
179 
180  virtual ~Checker() {}
181 
182  virtual void wf_rf() const {
183  EventSet reads;
184 
185  for (const auto& tuples : exec_->rf.get()) {
186  if (!tuples.first.AnyType(arch_->EventTypeWrite())) {
187  throw Error("WF_RF_NOT_FROM_WRITE");
188  }
189 
190  for (const auto& e : tuples.second.get()) {
191  if (!e.AnyType(arch_->EventTypeRead()) || tuples.first.addr != e.addr) {
192  throw Error("WF_RF_NOT_SAME_LOC");
193  }
194 
195  // For every read, there exists only 1 source!
196  if (reads.Contains(e)) {
197  throw Error("WF_RF_MULTI_SOURCE");
198  }
199  reads.Insert(e);
200  }
201  }
202  }
203 
204  virtual void wf_ws() const {
205  std::unordered_set<types::Addr> addrs;
206 
207  // Assert writes ordered captured in ws are to the same location.
208  for (const auto& tuples : exec_->ws.get()) {
209  addrs.insert(tuples.first.addr);
210 
211  for (const auto& e : tuples.second.get()) {
212  if (tuples.first.addr != e.addr) {
213  throw Error("WF_WS_NOT_SAME_LOC");
214  }
215  }
216  }
217 
218  auto writes = exec_->events.Filter(
219  [&](const Event& e) { return e.AnyType(arch_->EventTypeWrite()); });
220  if (!exec_->ws.StrictPartialOrder(writes)) {
221  throw Error("WF_WS_NOT_STRICT_PARTIAL_ORDER");
222  }
223 
224  for (const auto& addr : addrs) {
225  auto same_addr_writes =
226  writes.Filter([&](const Event& e) { return e.addr == addr; });
227  if (!exec_->ws.ConnexOn(same_addr_writes)) {
228  throw Error("WF_WS_NOT_CONNEX");
229  }
230  }
231  }
232 
233  virtual void wf() const {
234  wf_rf();
235  wf_ws();
236  }
237 
238  virtual bool uniproc(EventRel::Path* cyclic = nullptr) const {
239  return (exec_->com() | exec_->po_loc()).Acyclic(cyclic);
240  }
241 
242  virtual bool thin(EventRel::Path* cyclic = nullptr) const {
243  return (exec_->rf | exec_->dp).Acyclic(cyclic);
244  }
245 
246  virtual bool check_exec(EventRel::Path* cyclic = nullptr) const {
247  return arch_->ghb(*exec_).Acyclic(cyclic);
248  }
249 
250  virtual void valid_exec(EventRel::Path* cyclic = nullptr) const {
251  wf();
252 
253  if (!uniproc(cyclic)) {
254  throw Error("UNIPROC");
255  }
256 
257  if (!thin(cyclic)) {
258  throw Error("THIN");
259  }
260 
261  if (!check_exec(cyclic)) {
262  throw Error("CHECK_EXEC");
263  }
264  }
265 
266  protected:
269 };
270 
271 /*
272 =============================
273 Some common memory models.
274 =============================
275 */
276 
277 class Arch_SC : public Architecture {
278  public:
279  std::unique_ptr<Checker> MakeChecker(const Architecture* arch,
280  const ExecWitness* exec) const override {
281  return std::unique_ptr<Checker>(new Checker(arch, exec));
282  }
283 
284  EventRel ppo(const ExecWitness& ew) const override {
285  assert(ew.po.Transitive());
286  return ew.po.Eval();
287  }
288 
289  EventRel grf(const ExecWitness& ew) const override { return ew.rf; }
290 
291  EventRel ab(const ExecWitness& ew) const override { return EventRel(); }
292 
293  Event::Type EventTypeRead() const override { return Event::kRead; }
294 
295  Event::Type EventTypeWrite() const override { return Event::kWrite; }
296 };
297 
298 class Arch_TSO : public Architecture {
299  public:
300  void Clear() override { mfence.Clear(); }
301 
302  std::unique_ptr<Checker> MakeChecker(const Architecture* arch,
303  const ExecWitness* exec) const override {
304  return std::unique_ptr<Checker>(new Checker(arch, exec));
305  }
306 
307  EventRel ppo(const ExecWitness& ew) const override {
308  assert(ew.po.Transitive());
309  return ew.po.Filter([](const Event& e1, const Event& e2) {
310  return !e1.AllType(Event::kWrite) || !e2.AllType(Event::kRead);
311  });
312  }
313 
314  EventRel grf(const ExecWitness& ew) const override { return ew.rfe(); }
315 
316  EventRel ab(const ExecWitness& ew) const override {
317  if (mfence.empty()) {
318  return mfence;
319  }
320 
321  // Filter postar by only those events which are possibly relevent.
322  const auto postar =
323  ew.po
324  .Filter([&](const Event& e1, const Event& e2) {
325  // Only include those where first event is write or second
326  // is a read, all other are included in po regardless.
327  return e1.AllType(Event::kWrite) || e2.AllType(Event::kRead);
328  })
329  .set_props(EventRel::kReflexiveClosure);
330 
331  return EventRelSeq({postar, mfence, postar}).EvalClear();
332  }
333 
334  Event::Type EventTypeRead() const override { return Event::kRead; }
335 
336  Event::Type EventTypeWrite() const override { return Event::kWrite; }
337 
338  public:
340 };
341 
342 } // namespace model12
343 } // namespace memconsistency
344 } // namespace mc2lib
345 
346 #endif /* MEMCONSISTENCY_MODEL12_HPP_ */
347 
348 /* vim: set ts=2 sts=2 sw=2 et : */
Definition: eventsets.hpp:227
virtual void Clear()
Definition: model12.hpp:148
bool AllType(Type type_mask) const
Definition: eventsets.hpp:209
bool AnyType(Type type_mask) const
Definition: eventsets.hpp:213
EventRel ws
Definition: model12.hpp:139
bool Transitive() const
Definition: sets.hpp:693
EventRel fr(FilterFunc filter_func) const
Definition: model12.hpp:59
virtual ~Checker()
Definition: model12.hpp:180
virtual void wf() const
Definition: model12.hpp:233
Set< Ts > Reachable(const Element &e) const
Definition: sets.hpp:656
virtual void wf_rf() const
Definition: model12.hpp:182
Event::Type EventTypeWrite() const override
Definition: model12.hpp:295
EventRel rfe() const
Definition: model12.hpp:101
EventRel fr() const
Definition: model12.hpp:77
Definition: cats.hpp:47
EventRel rfi() const
Definition: model12.hpp:95
Definition: model12.hpp:277
Event::Type EventTypeWrite() const override
Definition: model12.hpp:336
EventRel ab(const ExecWitness &ew) const override
Definition: model12.hpp:316
EventRel wse() const
Definition: model12.hpp:113
EventRel grf(const ExecWitness &ew) const override
Definition: model12.hpp:289
const Element & Insert(const Element &e, bool assert_unique=false)
Definition: sets.hpp:112
std::uint32_t Type
Definition: eventsets.hpp:111
void Clear()
Definition: model12.hpp:126
Iiid iiid
Definition: eventsets.hpp:220
std::vector< Element > Path
Definition: sets.hpp:327
Event::Type EventTypeRead() const override
Definition: model12.hpp:334
std::pair< Element, Element > Tuple
Definition: sets.hpp:325
virtual bool uniproc(EventRel::Path *cyclic=nullptr) const
Definition: model12.hpp:238
Definition: eventsets.hpp:103
sets::RelationSeq< sets::Types< Event > > EventRelSeq
Definition: eventsets.hpp:225
std::unique_ptr< Checker > MakeChecker(const Architecture *arch, const ExecWitness *exec) const override
Definition: model12.hpp:279
static constexpr Properties kReflexiveClosure
Definition: sets.hpp:341
void Clear()
Definition: sets.hpp:156
bool Contains(const Element &e) const
Definition: sets.hpp:158
Relation Eval() const
Definition: sets.hpp:475
Checker(const Architecture *arch, const ExecWitness *exec)
Definition: model12.hpp:177
virtual bool check_exec(EventRel::Path *cyclic=nullptr) const
Definition: model12.hpp:246
virtual void wf_ws() const
Definition: model12.hpp:204
EventSet events
Definition: model12.hpp:135
const Container & get() const
Definition: sets.hpp:355
EventRel fre() const
Definition: model12.hpp:89
std::unique_ptr< Checker > MakeChecker(const Architecture *arch, const ExecWitness *exec) const override
Definition: model12.hpp:302
EventRel ab(const ExecWitness &ew) const override
Definition: model12.hpp:291
virtual bool thin(EventRel::Path *cyclic=nullptr) const
Definition: model12.hpp:242
virtual void valid_exec(EventRel::Path *cyclic=nullptr) const
Definition: model12.hpp:250
EventRel rf
Definition: model12.hpp:138
EventRel po
Definition: model12.hpp:136
EventRel com() const
Definition: model12.hpp:119
sets::Relation< sets::Types< Event > > EventRel
Definition: eventsets.hpp:224
Definition: model12.hpp:175
EventRel po_loc() const
Definition: model12.hpp:121
void Clear() override
Definition: model12.hpp:300
types::Addr addr
Definition: eventsets.hpp:218
const ExecWitness * exec_
Definition: model12.hpp:268
Relation Filter(FilterFunc filterFunc) const
Definition: sets.hpp:511
EventRel ppo(const ExecWitness &ew) const override
Definition: model12.hpp:284
void Insert(const Element &e1, const Element &e2, bool assert_unique=false)
Definition: sets.hpp:384
static constexpr Type kRead
Definition: eventsets.hpp:118
virtual ~Architecture()
Definition: model12.hpp:146
static constexpr Type kWrite
Definition: eventsets.hpp:119
types::Pid pid
Definition: eventsets.hpp:99
virtual EventRel ghb(const ExecWitness &ew) const
Definition: model12.hpp:160
Event::Type EventTypeRead() const override
Definition: model12.hpp:293
EventRel grf(const ExecWitness &ew) const override
Definition: model12.hpp:314
EventRel mfence
Definition: model12.hpp:339
EventRel fri() const
Definition: model12.hpp:83
const Architecture * arch_
Definition: model12.hpp:267
EventRel ppo(const ExecWitness &ew) const override
Definition: model12.hpp:307
EventRel wsi() const
Definition: model12.hpp:107
EventRel dp
Definition: model12.hpp:137
void Clear()
Definition: sets.hpp:596