Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
3cbf62ac8166479876d2099c7b6bc76336c6ddb6
[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 CommTestTransition::CommTestTransition(aid_t issuer, int times_considered, unsigned comm_, aid_t sender_,
60                                        aid_t receiver_, unsigned mbox_)
61     : Transition(Type::COMM_TEST, issuer, times_considered)
62     , comm_(comm_)
63     , mbox_(mbox_)
64     , sender_(sender_)
65     , receiver_(receiver_)
66 {
67 }
68 CommTestTransition::CommTestTransition(aid_t issuer, int times_considered, std::stringstream& stream)
69     : Transition(Type::COMM_TEST, issuer, times_considered)
70 {
71   xbt_assert(stream >> comm_ >> sender_ >> receiver_ >> mbox_ >> call_location_);
72   XBT_DEBUG("CommTestTransition comm:%u, sender:%ld receiver:%ld mbox:%u call_loc:%s", comm_, sender_, receiver_, mbox_,
73             call_location_.c_str());
74 }
75 std::string CommTestTransition::to_string(bool verbose) const
76 {
77   return xbt::string_printf("TestComm(from %ld to %ld, mbox=%u)", sender_, receiver_, mbox_);
78 }
79 bool CommTestTransition::depends(const Transition* other) const
80 {
81   if (other->type_ < type_)
82     return other->depends(this);
83
84   // Actions executed by the same actor are always dependent
85   if (other->aid_ == aid_)
86     return true;
87
88   if (dynamic_cast<const CommTestTransition*>(other) != nullptr)
89     return false; // Test & Test are independent
90
91   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
92     if (wait->timeout_)
93       return true; // Timeouts are not considered by the independence theorem, thus assumed dependent
94
95     /* Wait & Test are independent */
96     return false;
97   }
98
99   return false; // Comm transitions are INDEP with non-comm transitions
100 }
101
102 CommRecvTransition::CommRecvTransition(aid_t issuer, int times_considered, unsigned comm_, unsigned mbox_, int tag_)
103     : Transition(Type::COMM_ASYNC_RECV, issuer, times_considered), comm_(comm_), mbox_(mbox_), tag_(tag_)
104 {
105 }
106 CommRecvTransition::CommRecvTransition(aid_t issuer, int times_considered, std::stringstream& stream)
107     : Transition(Type::COMM_ASYNC_RECV, issuer, times_considered)
108 {
109   xbt_assert(stream >> comm_ >> mbox_ >> tag_ >> call_location_);
110   XBT_DEBUG("CommRecvTransition comm:%u, mbox:%u tag:%d call_loc:%s", comm_, mbox_, tag_, call_location_.c_str());
111 }
112 std::string CommRecvTransition::to_string(bool verbose) const
113 {
114   return xbt::string_printf("iRecv(mbox=%u)", mbox_);
115 }
116 bool CommRecvTransition::depends(const Transition* other) const
117 {
118   if (other->type_ < type_)
119     return other->depends(this);
120
121   // Actions executed by the same actor are always dependent
122   if (other->aid_ == aid_)
123     return true;
124
125   if (const auto* recv = dynamic_cast<const CommRecvTransition*>(other))
126     return mbox_ == recv->mbox_;
127
128   if (dynamic_cast<const CommSendTransition*>(other) != nullptr)
129     return false;
130
131   if (const auto* test = dynamic_cast<const CommTestTransition*>(other)) {
132     if (mbox_ != test->mbox_)
133       return false;
134
135     if ((aid_ != test->sender_) && (aid_ != test->receiver_))
136       return false;
137
138     // If the test is checking a paired comm already, we're independent!
139     // If we happen to make up that pair, then we're dependent...
140     if (test->comm_ != comm_)
141       return false;
142
143     return true; // DEP with other send transitions
144   }
145
146   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
147     if (wait->timeout_)
148       return true;
149
150     if (mbox_ != wait->mbox_)
151       return false;
152
153     if ((aid_ != wait->sender_) && (aid_ != wait->receiver_))
154       return false;
155
156     // If the wait is waiting on a paired comm already, we're independent!
157     // If we happen to make up that pair, then we're dependent...
158     if ((aid_ != wait->aid_) && wait->comm_ != comm_)
159       return false;
160
161     return true; // DEP with other wait transitions
162   }
163
164   return false; // Comm transitions are INDEP with non-comm transitions
165 }
166
167 CommSendTransition::CommSendTransition(aid_t issuer, int times_considered, unsigned comm_, unsigned mbox_, int tag_)
168     : Transition(Type::COMM_ASYNC_SEND, issuer, times_considered), comm_(comm_), mbox_(mbox_), tag_(tag_)
169 {
170 }
171 CommSendTransition::CommSendTransition(aid_t issuer, int times_considered, std::stringstream& stream)
172     : Transition(Type::COMM_ASYNC_SEND, issuer, times_considered)
173 {
174   xbt_assert(stream >> comm_ >> mbox_ >> tag_ >> call_location_);
175   XBT_DEBUG("SendTransition comm:%u mbox:%u tag:%d call_loc:%s", comm_, mbox_, tag_, call_location_.c_str());
176 }
177 std::string CommSendTransition::to_string(bool verbose = false) const
178 {
179   return xbt::string_printf("iSend(mbox=%u)", mbox_);
180 }
181
182 bool CommSendTransition::depends(const Transition* other) const
183 {
184   if (other->type_ < type_)
185     return other->depends(this);
186
187   // Actions executed by the same actor are always dependent
188   if (other->aid_ == aid_)
189     return true;
190
191   if (const auto* other_isend = dynamic_cast<const CommSendTransition*>(other))
192     return mbox_ == other_isend->mbox_;
193
194   if (dynamic_cast<const CommRecvTransition*>(other) != nullptr)
195     return false;
196
197   if (const auto* test = dynamic_cast<const CommTestTransition*>(other)) {
198     if (mbox_ != test->mbox_)
199       return false;
200
201     if ((aid_ != test->sender_) && (aid_ != test->receiver_))
202       return false;
203
204     // If the test is checking a paired comm already, we're independent!
205     // If we happen to make up that pair, then we're dependent...
206     if (test->comm_ != comm_)
207       return false;
208
209     return true; // DEP with other test transitions
210   }
211
212   if (const auto* wait = dynamic_cast<const CommWaitTransition*>(other)) {
213     if (wait->timeout_)
214       return true;
215
216     if (mbox_ != wait->mbox_)
217       return false;
218
219     if ((aid_ != wait->sender_) && (aid_ != wait->receiver_))
220       return false;
221
222     // If the wait is waiting on a paired comm already, we're independent!
223     // If we happen to make up that pair, then we're dependent...
224     if ((aid_ != wait->aid_) && wait->comm_ != comm_)
225       return false;
226
227     return true; // DEP with other wait transitions
228   }
229
230   return false; // Comm transitions are INDEP with non-comm transitions
231 }
232
233 } // namespace simgrid::mc