Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Reduce code dupplication to please sonar
[simgrid.git] / src / mc / api / TransitionComm.cpp
1 /* Copyright (c) 2015-2022. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "src/mc/api/TransitionComm.hpp"
7 #include "xbt/asserts.h"
8 #include <simgrid/config.h>
9 #if SIMGRID_HAVE_MC
10 #include "src/mc/ModelChecker.hpp"
11 #include "src/mc/Session.hpp"
12 #include "src/mc/api/State.hpp"
13 #endif
14
15 #include <sstream>
16
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_trans_comm, mc_transition,
18                                 "Logging specific to MC transitions about communications");
19
20 namespace simgrid {
21 namespace mc {
22
23 CommWaitTransition::CommWaitTransition(aid_t issuer, int times_considered, std::stringstream& stream)
24     : Transition(Type::COMM_WAIT, issuer, times_considered)
25 {
26   stream >> timeout_ >> comm_ >> sender_ >> receiver_ >> mbox_ >> src_buff_ >> dst_buff_ >> size_;
27   XBT_DEBUG("CommWaitTransition %s comm:%p, sender:%ld receiver:%ld mbox:%u sbuff:%p rbuff:%p size:%zu",
28             (timeout_ ? "timeout" : "no-timeout"), comm_, sender_, receiver_, mbox_, src_buff_, dst_buff_, size_);
29 }
30 std::string CommWaitTransition::to_string(bool verbose) const
31 {
32   auto res = xbt::string_printf("%ld: WaitComm(from %ld to %ld, mbox=%u, %s", aid_, sender_, receiver_, mbox_,
33                                 (timeout_ ? "timeout" : "no timeout"));
34   if (verbose) {
35     res += ", src_buff=" + xbt::string_printf("%p", src_buff_) + ", size=" + std::to_string(size_);
36     res += ", dst_buff=" + xbt::string_printf("%p", dst_buff_);
37   }
38   res += ")";
39   return res;
40 }
41 bool CommWaitTransition::depends(const Transition* other) const
42 {
43   if (aid_ == other->aid_)
44     return false;
45
46   if (other->type_ < type_)
47     return other->depends(this);
48
49   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
50     if (timeout_ || wait->timeout_)
51       return true; // Timeouts are not considered by the independence theorem, thus assumed dependent
52
53     if (src_buff_ == wait->src_buff_ && dst_buff_ == wait->dst_buff_)
54       return false;
55     if (src_buff_ != nullptr && dst_buff_ != nullptr && wait->src_buff_ != nullptr && wait->dst_buff_ != nullptr &&
56         dst_buff_ != wait->src_buff_ && dst_buff_ != wait->dst_buff_ && dst_buff_ != src_buff_)
57       return false;
58   }
59
60   return true;
61 }
62 CommTestTransition::CommTestTransition(aid_t issuer, int times_considered, std::stringstream& stream)
63     : Transition(Type::COMM_TEST, issuer, times_considered)
64 {
65   stream >> comm_ >> sender_ >> receiver_ >> mbox_ >> src_buff_ >> dst_buff_ >> size_;
66   XBT_DEBUG("CommTestTransition comm:%p, sender:%ld receiver:%ld mbox:%u sbuff:%p rbuff:%p size:%zu", comm_, sender_,
67             receiver_, mbox_, src_buff_, dst_buff_, size_);
68 }
69 std::string CommTestTransition::to_string(bool verbose) const
70 {
71   auto res = xbt::string_printf("%ld: TestComm(from %ld to %ld, mbox=%u", aid_, sender_, receiver_, mbox_);
72   if (verbose) {
73     res += ", src_buff=" + xbt::string_printf("%p", src_buff_) + ", size=" + std::to_string(size_);
74     res += ", dst_buff=" + xbt::string_printf("%p", dst_buff_);
75   }
76   res += ")";
77   return res;
78 }
79 bool CommTestTransition::depends(const Transition* other) const
80 {
81   if (aid_ == other->aid_)
82     return false;
83
84   if (other->type_ < type_)
85     return other->depends(this);
86
87   if (dynamic_cast<const CommTestTransition*>(other) != nullptr)
88     return false; // Test & Test are independent
89
90   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
91     if (wait->timeout_)
92       return true; // Timeouts are not considered by the independence theorem, thus assumed dependent
93
94     /* Wait & Test are independent */
95     return false;
96   }
97
98   return true;
99 }
100
101 CommRecvTransition::CommRecvTransition(aid_t issuer, int times_considered, std::stringstream& stream)
102     : Transition(Type::COMM_RECV, issuer, times_considered)
103 {
104   stream >> mbox_ >> dst_buff_;
105 }
106 std::string CommRecvTransition::to_string(bool verbose) const
107 {
108   auto res = xbt::string_printf("%ld: iRecv(mbox=%u", aid_, mbox_);
109   if (verbose)
110     res += ", buff=" + xbt::string_printf("%p", dst_buff_);
111   res += ")";
112   return res;
113 }
114 bool CommRecvTransition::depends(const Transition* other) const
115 {
116   if (aid_ == other->aid_)
117     return false;
118
119   if (other->type_ < type_)
120     return other->depends(this);
121
122   if (const auto* recv = dynamic_cast<const CommRecvTransition*>(other))
123     return mbox_ == recv->mbox_;
124
125   if (dynamic_cast<const CommSendTransition*>(other) != nullptr)
126     return false;
127
128   if (const auto* test = dynamic_cast<const CommTestTransition*>(other)) {
129     if (mbox_ != test->mbox_)
130       return false;
131
132     if ((aid_ != test->sender_) && (aid_ != test->receiver_) && (test->dst_buff_ != dst_buff_))
133       return false;
134   }
135
136   if (auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
137     if (wait->timeout_)
138       return true;
139
140     if (mbox_ != wait->mbox_)
141       return false;
142
143     if ((aid_ != wait->sender_) && (aid_ != wait->receiver_) && (wait->dst_buff_ != dst_buff_))
144       return false;
145   }
146
147   return true;
148 }
149
150 CommSendTransition::CommSendTransition(aid_t issuer, int times_considered, std::stringstream& stream)
151     : Transition(Type::COMM_SEND, issuer, times_considered)
152 {
153   stream >> mbox_ >> src_buff_ >> size_;
154   XBT_DEBUG("SendTransition mbox:%u buff:%p size:%zu", mbox_, src_buff_, size_);
155 }
156 std::string CommSendTransition::to_string(bool verbose = false) const
157 {
158   auto res = xbt::string_printf("%ld: iSend(mbox=%u", aid_, mbox_);
159   if (verbose)
160     res += ", buff=" + xbt::string_printf("%p", src_buff_) + ", size=" + std::to_string(size_);
161   res += ")";
162   return res;
163 }
164 TestAnyTransition::TestAnyTransition(aid_t issuer, int times_considered, std::stringstream& stream)
165     : Transition(Type::TESTANY, issuer, times_considered)
166 {
167   int size;
168   stream >> size;
169   for (int i = 0; i < size; i++) {
170
171     Transition* t = deserialize_transition(issuer, 0, stream);
172     XBT_DEBUG("TestAny received a transition %s", t->to_string(true).c_str());
173     transitions_.push_back(t);
174   }
175 }
176 std::string TestAnyTransition::to_string(bool verbose) const
177 {
178   auto res = xbt::string_printf("%ld: TestAny{ ", aid_);
179   for (auto const* t : transitions_)
180     res += t->to_string(verbose);
181   res += "}";
182   return res;
183 }
184 bool TestAnyTransition::depends(const Transition* other) const
185 {
186   return transitions_[times_considered_]->depends(other);
187 }
188 WaitAnyTransition::WaitAnyTransition(aid_t issuer, int times_considered, std::stringstream& stream)
189     : Transition(Type::WAITANY, issuer, times_considered)
190 {
191   int size;
192   stream >> size;
193   for (int i = 0; i < size; i++) {
194     Transition* t = deserialize_transition(issuer, 0, stream);
195     transitions_.push_back(t);
196   }
197 }
198 std::string WaitAnyTransition::to_string(bool verbose) const
199 {
200   auto res = xbt::string_printf("%ld: WaitAny{ ", aid_);
201   for (auto const* t : transitions_)
202     res += t->to_string(verbose);
203   res += "}";
204   return res;
205 }
206 bool WaitAnyTransition::depends(const Transition* other) const
207 {
208   return transitions_[times_considered_]->depends(other);
209 }
210
211 bool CommSendTransition::depends(const Transition* other) const
212 {
213   if (aid_ == other->aid_)
214     return false;
215
216   if (other->type_ < type_)
217     return other->depends(this);
218
219   if (const auto* other_isend = dynamic_cast<const CommSendTransition*>(other))
220     return mbox_ == other_isend->mbox_;
221
222   if (dynamic_cast<const CommRecvTransition*>(other) != nullptr)
223     return false;
224
225   if (const auto* test = dynamic_cast<const CommTestTransition*>(other)) {
226     if (mbox_ != test->mbox_)
227       return false;
228
229     if ((aid_ != test->sender_) && (aid_ != test->receiver_) && (test->src_buff_ != src_buff_))
230       return false;
231   }
232
233   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
234     if (wait->timeout_)
235       return true;
236
237     if (mbox_ != wait->mbox_)
238       return false;
239
240     if ((aid_ != wait->sender_) && (aid_ != wait->receiver_) && (wait->src_buff_ != src_buff_))
241       return false;
242   }
243
244   return true;
245 }
246
247 Transition* deserialize_transition(aid_t issuer, int times_considered, std::stringstream& stream)
248 {
249   short type;
250   stream >> type;
251   xbt_assert(type >= 0 && type <= static_cast<short>(Transition::Type::UNKNOWN), "Invalid transition type %d received",
252              type);
253
254   auto simcall = static_cast<Transition::Type>(type);
255
256   switch (simcall) {
257     case Transition::Type::COMM_RECV:
258       return new CommRecvTransition(issuer, times_considered, stream);
259     case Transition::Type::COMM_SEND:
260       return new CommSendTransition(issuer, times_considered, stream);
261     case Transition::Type::COMM_TEST:
262       return new CommTestTransition(issuer, times_considered, stream);
263     case Transition::Type::COMM_WAIT:
264       return new CommWaitTransition(issuer, times_considered, stream);
265
266     case Transition::Type::TESTANY:
267       return new TestAnyTransition(issuer, times_considered, stream);
268     case Transition::Type::WAITANY:
269       return new WaitAnyTransition(issuer, times_considered, stream);
270
271     case Transition::Type::RANDOM:
272       return new RandomTransition(issuer, times_considered, stream);
273
274     case Transition::Type::UNKNOWN:
275       return new Transition(Transition::Type::UNKNOWN, issuer, times_considered);
276   }
277   THROW_IMPOSSIBLE; // Some compilers don't detect that each branch of the above switch has a return
278 }
279
280 } // namespace mc
281 } // namespace simgrid