Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
MC: move the reversible_race logic to the Transition class
[simgrid.git] / src / mc / transition / TransitionComm.cpp
1 /* Copyright (c) 2015-2023. 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/transition/TransitionComm.hpp"
7 #include "simgrid/config.h"
8 #include "src/mc/api/RemoteApp.hpp"
9 #include "src/mc/api/State.hpp"
10 #include "xbt/asserts.h"
11 #include "xbt/string.hpp"
12
13 #include <inttypes.h>
14 #include <sstream>
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_trans_comm, mc_transition,
17                                 "Logging specific to MC transitions about communications");
18
19 namespace simgrid::mc {
20
21 CommWaitTransition::CommWaitTransition(aid_t issuer, int times_considered, bool timeout_, unsigned comm_, aid_t sender_,
22                                        aid_t receiver_, unsigned mbox_)
23     : Transition(Type::COMM_WAIT, issuer, times_considered)
24     , timeout_(timeout_)
25     , comm_(comm_)
26     , mbox_(mbox_)
27     , sender_(sender_)
28     , receiver_(receiver_)
29 {
30 }
31 CommWaitTransition::CommWaitTransition(aid_t issuer, int times_considered, std::stringstream& stream)
32     : Transition(Type::COMM_WAIT, issuer, times_considered)
33 {
34   xbt_assert(stream >> timeout_ >> comm_ >> sender_ >> receiver_ >> mbox_ >> call_location_);
35   XBT_DEBUG("CommWaitTransition %s comm:%u, sender:%ld receiver:%ld mbox:%u call_loc:%s",
36             (timeout_ ? "timeout" : "no-timeout"), comm_, sender_, receiver_, mbox_, call_location_.c_str());
37 }
38 std::string CommWaitTransition::to_string(bool verbose) const
39 {
40   return xbt::string_printf("WaitComm(from %ld to %ld, mbox=%u, %s)", sender_, receiver_, mbox_,
41                             (timeout_ ? "timeout" : "no timeout"));
42 }
43 bool CommWaitTransition::depends(const Transition* other) const
44 {
45   if (other->type_ < type_)
46     return other->depends(this);
47
48   // Actions executed by the same actor are always dependent
49   if (other->aid_ == aid_)
50     return true;
51
52   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
53     if (timeout_ || wait->timeout_)
54       return true; // Timeouts are not considered by the independence theorem, thus assumed dependent
55   }
56
57   return false; // Comm transitions are INDEP with non-comm transitions
58 }
59
60 bool CommWaitTransition::reversible_race(const Transition* other) const
61 {
62   switch (type_) {
63     case Type::COMM_WAIT:
64       // If the other event is a communication event, then we are not reversible; otherwise we are reversible.
65       return other->type_ != Transition::Type::COMM_ASYNC_SEND && other->type_ != Transition::Type::COMM_ASYNC_RECV;
66     default:
67       xbt_die("Unexpected transition type %s", to_c_str(type_));
68   }
69 }
70
71 CommTestTransition::CommTestTransition(aid_t issuer, int times_considered, unsigned comm_, aid_t sender_,
72                                        aid_t receiver_, unsigned mbox_)
73     : Transition(Type::COMM_TEST, issuer, times_considered)
74     , comm_(comm_)
75     , mbox_(mbox_)
76     , sender_(sender_)
77     , receiver_(receiver_)
78 {
79 }
80 CommTestTransition::CommTestTransition(aid_t issuer, int times_considered, std::stringstream& stream)
81     : Transition(Type::COMM_TEST, issuer, times_considered)
82 {
83   xbt_assert(stream >> comm_ >> sender_ >> receiver_ >> mbox_ >> call_location_);
84   XBT_DEBUG("CommTestTransition comm:%u, sender:%ld receiver:%ld mbox:%u call_loc:%s", comm_, sender_, receiver_, mbox_,
85             call_location_.c_str());
86 }
87 std::string CommTestTransition::to_string(bool verbose) const
88 {
89   return xbt::string_printf("TestComm(from %ld to %ld, mbox=%u)", sender_, receiver_, mbox_);
90 }
91
92 bool CommTestTransition::depends(const Transition* other) const
93 {
94   if (other->type_ < type_)
95     return other->depends(this);
96
97   // Actions executed by the same actor are always dependent
98   if (other->aid_ == aid_)
99     return true;
100
101   if (dynamic_cast<const CommTestTransition*>(other) != nullptr)
102     return false; // Test & Test are independent
103
104   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
105     if (wait->timeout_)
106       return true; // Timeouts are not considered by the independence theorem, thus assumed dependent
107
108     /* Wait & Test are independent */
109     return false;
110   }
111
112   return false; // Comm transitions are INDEP with non-comm transitions
113 }
114
115 bool CommTestTransition::reversible_race(const Transition* other) const
116 {
117   switch (type_) {
118     case Type::COMM_TEST:
119       return true; // CommTest is always enabled
120     default:
121       xbt_die("Unexpected transition type %s", to_c_str(type_));
122   }
123 }
124
125 CommRecvTransition::CommRecvTransition(aid_t issuer, int times_considered, unsigned comm_, unsigned mbox_, int tag_)
126     : Transition(Type::COMM_ASYNC_RECV, issuer, times_considered), comm_(comm_), mbox_(mbox_), tag_(tag_)
127 {
128 }
129 CommRecvTransition::CommRecvTransition(aid_t issuer, int times_considered, std::stringstream& stream)
130     : Transition(Type::COMM_ASYNC_RECV, issuer, times_considered)
131 {
132   xbt_assert(stream >> comm_ >> mbox_ >> tag_ >> call_location_);
133   XBT_DEBUG("CommRecvTransition comm:%u, mbox:%u tag:%d call_loc:%s", comm_, mbox_, tag_, call_location_.c_str());
134 }
135 std::string CommRecvTransition::to_string(bool verbose) const
136 {
137   return xbt::string_printf("iRecv(mbox=%u)", mbox_);
138 }
139 bool CommRecvTransition::depends(const Transition* other) const
140 {
141   if (other->type_ < type_)
142     return other->depends(this);
143
144   // Actions executed by the same actor are always dependent
145   if (other->aid_ == aid_)
146     return true;
147
148   if (const auto* recv = dynamic_cast<const CommRecvTransition*>(other))
149     return mbox_ == recv->mbox_;
150
151   if (dynamic_cast<const CommSendTransition*>(other) != nullptr)
152     return false;
153
154   if (const auto* test = dynamic_cast<const CommTestTransition*>(other)) {
155     if (mbox_ != test->mbox_)
156       return false;
157
158     if ((aid_ != test->sender_) && (aid_ != test->receiver_))
159       return false;
160
161     // If the test is checking a paired comm already, we're independent!
162     // If we happen to make up that pair, then we're dependent...
163     if (test->comm_ != comm_)
164       return false;
165
166     return true; // DEP with other send transitions
167   }
168
169   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
170     if (wait->timeout_)
171       return true;
172
173     if (mbox_ != wait->mbox_)
174       return false;
175
176     if ((aid_ != wait->sender_) && (aid_ != wait->receiver_))
177       return false;
178
179     // If the wait is waiting on a paired comm already, we're independent!
180     // If we happen to make up that pair, then we're dependent...
181     if ((aid_ != wait->aid_) && wait->comm_ != comm_)
182       return false;
183
184     return true; // DEP with other wait transitions
185   }
186
187   return false; // Comm transitions are INDEP with non-comm transitions
188 }
189
190 bool CommRecvTransition::reversible_race(const Transition* other) const
191 {
192   switch (type_) {
193     case Type::COMM_ASYNC_RECV:
194       return true; // CommRecv is always enabled
195     default:
196       xbt_die("Unexpected transition type %s", to_c_str(type_));
197   }
198 }
199
200 CommSendTransition::CommSendTransition(aid_t issuer, int times_considered, unsigned comm_, unsigned mbox_, int tag_)
201     : Transition(Type::COMM_ASYNC_SEND, issuer, times_considered), comm_(comm_), mbox_(mbox_), tag_(tag_)
202 {
203 }
204 CommSendTransition::CommSendTransition(aid_t issuer, int times_considered, std::stringstream& stream)
205     : Transition(Type::COMM_ASYNC_SEND, issuer, times_considered)
206 {
207   xbt_assert(stream >> comm_ >> mbox_ >> tag_ >> call_location_);
208   XBT_DEBUG("SendTransition comm:%u mbox:%u tag:%d call_loc:%s", comm_, mbox_, tag_, call_location_.c_str());
209 }
210 std::string CommSendTransition::to_string(bool verbose = false) const
211 {
212   return xbt::string_printf("iSend(mbox=%u)", mbox_);
213 }
214
215 bool CommSendTransition::depends(const Transition* other) const
216 {
217   if (other->type_ < type_)
218     return other->depends(this);
219
220   // Actions executed by the same actor are always dependent
221   if (other->aid_ == aid_)
222     return true;
223
224   if (const auto* other_isend = dynamic_cast<const CommSendTransition*>(other))
225     return mbox_ == other_isend->mbox_;
226
227   if (dynamic_cast<const CommRecvTransition*>(other) != nullptr)
228     return false;
229
230   if (const auto* test = dynamic_cast<const CommTestTransition*>(other)) {
231     if (mbox_ != test->mbox_)
232       return false;
233
234     if ((aid_ != test->sender_) && (aid_ != test->receiver_))
235       return false;
236
237     // If the test is checking a paired comm already, we're independent!
238     // If we happen to make up that pair, then we're dependent...
239     if (test->comm_ != comm_)
240       return false;
241
242     return true; // DEP with other test transitions
243   }
244
245   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
246     if (wait->timeout_)
247       return true;
248
249     if (mbox_ != wait->mbox_)
250       return false;
251
252     if ((aid_ != wait->sender_) && (aid_ != wait->receiver_))
253       return false;
254
255     // If the wait is waiting on a paired comm already, we're independent!
256     // If we happen to make up that pair, then we're dependent...
257     if ((aid_ != wait->aid_) && wait->comm_ != comm_)
258       return false;
259
260     return true; // DEP with other wait transitions
261   }
262
263   return false; // Comm transitions are INDEP with non-comm transitions
264 }
265
266 bool CommSendTransition::reversible_race(const Transition* other) const
267 {
268   switch (type_) {
269     case Type::COMM_ASYNC_SEND:
270       return true; // CommSend is always enabled
271     default:
272       xbt_die("Unexpected transition type %s", to_c_str(type_));
273   }
274 }
275
276 } // namespace simgrid::mc