Logo AND Algorithmique Numérique Distribuée

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