Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use std::string_view.
[simgrid.git] / src / kernel / actor / CommObserver.cpp
1 /* Copyright (c) 2019-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 "simgrid/s4u/Host.hpp"
7 #include "src/kernel/activity/CommImpl.hpp"
8 #include "src/kernel/activity/MailboxImpl.hpp"
9 #include "src/kernel/actor/ActorImpl.hpp"
10 #include "src/kernel/actor/SimcallObserver.hpp"
11 #include "src/mc/mc_config.hpp"
12
13 #include <sstream>
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(obs_comm, mc_observer, "Logging specific to the Communication simcalls observation");
16
17 namespace simgrid::kernel::actor {
18
19 ActivityTestanySimcall::ActivityTestanySimcall(ActorImpl* actor, const std::vector<activity::ActivityImpl*>& activities,
20                                                std::string_view fun_call)
21     : ResultingSimcall(actor, -1), activities_(activities), fun_call_(fun_call)
22 {
23   indexes_.clear();
24   // list all the activities that are ready
25   for (unsigned i = 0; i < activities_.size(); i++)
26     if (activities_[i]->test(get_issuer()))
27       indexes_.push_back(i);
28 }
29
30 int ActivityTestanySimcall::get_max_consider() const
31 {
32   return indexes_.size() + 1;
33 }
34
35 void ActivityTestanySimcall::prepare(int times_considered)
36 {
37   if (times_considered < static_cast<int>(indexes_.size()))
38     next_value_ = indexes_.at(times_considered);
39   else
40     next_value_ = -1;
41 }
42 static void serialize_activity_test(const activity::ActivityImpl* act, std::string const& call_location,
43                                     std::stringstream& stream)
44 {
45   if (const auto* comm = dynamic_cast<activity::CommImpl const*>(act)) {
46     stream << "  " << (short)mc::Transition::Type::COMM_TEST;
47     stream << ' ' << comm->get_id();
48     stream << ' ' << (comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1);
49     stream << ' ' << (comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1);
50     stream << ' ' << comm->get_mailbox_id();
51     stream << ' ' << call_location;
52   } else {
53     stream << (short)mc::Transition::Type::UNKNOWN;
54     XBT_CRITICAL("Unknown transition in a test any. Bad things may happen");
55   }
56 }
57 static std::string to_string_activity_test(const activity::ActivityImpl* act)
58 {
59   if (const auto* comm = dynamic_cast<activity::CommImpl const*>(act)) {
60     return "CommTest(comm_id:" + std::to_string(comm->get_id()) +
61            " src:" + std::to_string(comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1) +
62            " dst:" + std::to_string(comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1) +
63            " mbox:" + std::to_string(comm->get_mailbox_id()) + ")";
64   } else {
65     return "TestUnknownType()";
66   }
67 }
68 void ActivityTestanySimcall::serialize(std::stringstream& stream) const
69 {
70   XBT_DEBUG("Serialize %s", to_string().c_str());
71   stream << (short)mc::Transition::Type::TESTANY << ' ' << activities_.size() << ' ';
72   for (auto const* act : activities_) {
73     // fun_call of each activity embedded in the TestAny is not known, so let's use the location of the TestAny itself
74     serialize_activity_test(act, fun_call_, stream);
75     stream << ' ';
76   }
77   stream << fun_call_;
78 }
79 std::string ActivityTestanySimcall::to_string() const
80 {
81   std::stringstream buffer("TestAny(");
82   bool first = true;
83   for (auto const* act : activities_) {
84     if (first)
85       first = false;
86     else
87       buffer << " | ";
88     buffer << to_string_activity_test(act);
89   }
90   buffer << ")";
91   return buffer.str();
92 }
93
94 void ActivityTestSimcall::serialize(std::stringstream& stream) const
95 {
96   serialize_activity_test(activity_, fun_call_, stream);
97 }
98 std::string ActivityTestSimcall::to_string() const
99 {
100   return to_string_activity_test(activity_);
101 }
102 static void serialize_activity_wait(const activity::ActivityImpl* act, bool timeout, std::string const& call_location,
103                                     std::stringstream& stream)
104 {
105   if (const auto* comm = dynamic_cast<activity::CommImpl const*>(act)) {
106     stream << (short)mc::Transition::Type::COMM_WAIT << ' ';
107     stream << timeout << ' ' << comm->get_id();
108
109     stream << ' ' << (comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1);
110     stream << ' ' << (comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1);
111     stream << ' ' << comm->get_mailbox_id();
112     stream << ' ' << call_location;
113   } else {
114     stream << (short)mc::Transition::Type::UNKNOWN;
115   }
116 }
117 static std::string to_string_activity_wait(const activity::ActivityImpl* act)
118 {
119   if (const auto* comm = dynamic_cast<activity::CommImpl const*>(act)) {
120     return "CommWait(comm_id:" + std::to_string(comm->get_id()) +
121            " src:" + std::to_string(comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1) +
122            " dst:" + std::to_string(comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1) +
123            " mbox:" + (comm->get_mailbox() == nullptr ? "-" : comm->get_mailbox()->get_name()) +
124            "(id:" + std::to_string(comm->get_mailbox_id()) + "))";
125   } else {
126     return "WaitUnknownType()";
127   }
128 }
129
130 void ActivityWaitSimcall::serialize(std::stringstream& stream) const
131 {
132   serialize_activity_wait(activity_, timeout_ > 0, fun_call_, stream);
133 }
134 void ActivityWaitanySimcall::serialize(std::stringstream& stream) const
135 {
136   XBT_DEBUG("Serialize %s", to_string().c_str());
137   stream << (short)mc::Transition::Type::WAITANY << ' ' << activities_.size() << ' ';
138   for (auto const* act : activities_) {
139     // fun_call of each activity embedded in the WaitAny is not known, so let's use the location of the WaitAny itself
140     serialize_activity_wait(act, timeout_ > 0, fun_call_, stream);
141     stream << ' ';
142   }
143   stream << fun_call_;
144 }
145 std::string ActivityWaitSimcall::to_string() const
146 {
147   return to_string_activity_wait(activity_);
148 }
149 std::string ActivityWaitanySimcall::to_string() const
150 {
151   std::stringstream buffer("WaitAny(");
152   bool first = true;
153   for (auto const* act : activities_) {
154     if (first)
155       first = false;
156     else
157       buffer << " | ";
158     buffer << to_string_activity_test(act);
159   }
160   buffer << ")";
161   return buffer.str();
162 }
163 ActivityWaitanySimcall::ActivityWaitanySimcall(ActorImpl* actor, const std::vector<activity::ActivityImpl*>& activities,
164                                                double timeout, std::string_view fun_call)
165     : ResultingSimcall(actor, -1), activities_(activities), timeout_(timeout), fun_call_(fun_call)
166 {
167   // list all the activities that are ready
168   indexes_.clear();
169   for (unsigned i = 0; i < activities_.size(); i++)
170     if (activities_[i]->test(get_issuer()))
171       indexes_.push_back(i);
172 }
173
174 bool ActivityWaitSimcall::is_enabled()
175 {
176   // FIXME: if _sg_mc_timeout == 1 and if we have either a sender or receiver timeout, the transition is enabled
177   // because even if the communication is not ready, it can timeout and won't block.
178
179   return activity_->test(get_issuer());
180 }
181
182 bool ActivityWaitanySimcall::is_enabled()
183 {
184   // list all the activities that are ready
185   indexes_.clear();
186   for (unsigned i = 0; i < activities_.size(); i++)
187     if (activities_[i]->test(get_issuer()))
188       indexes_.push_back(i);
189
190   //  if (_sg_mc_timeout && timeout_)  FIXME: deal with the potential timeout of the WaitAny
191
192   // FIXME: even if the WaitAny has no timeout, some of the activities may still have one.
193   // we should iterate over the vector searching for them
194   return not indexes_.empty();
195 }
196
197 int ActivityWaitanySimcall::get_max_consider() const
198 {
199   int res = indexes_.size();
200   //  if (_sg_mc_timeout && timeout_)
201   //    res++;
202
203   return res;
204 }
205
206 void ActivityWaitanySimcall::prepare(int times_considered)
207 {
208   if (times_considered < static_cast<int>(indexes_.size()))
209     next_value_ = indexes_.at(times_considered);
210   else
211     next_value_ = -1;
212 }
213
214 void CommIsendSimcall::serialize(std::stringstream& stream) const
215 {
216   /* Note that the comm_ is 0 until after the execution of the simcall */
217   stream << (short)mc::Transition::Type::COMM_ASYNC_SEND << ' ';
218   stream << (comm_ ? comm_->get_id() : 0) << ' ' << mbox_->get_id() << ' ' << tag_;
219   XBT_DEBUG("SendObserver comm:%p mbox:%u tag:%d", comm_, mbox_->get_id(), tag_);
220   stream << ' ' << fun_call_;
221 }
222 std::string CommIsendSimcall::to_string() const
223 {
224   return "CommAsyncSend(comm_id: " + std::to_string(comm_->get_id()) + " mbox:" + std::to_string(mbox_->get_id()) +
225          " tag: " + std::to_string(tag_) + ")";
226 }
227
228 void CommIrecvSimcall::serialize(std::stringstream& stream) const
229 {
230   /* Note that the comm_ is 0 until after the execution of the simcall */
231   stream << (short)mc::Transition::Type::COMM_ASYNC_RECV << ' ';
232   stream << (comm_ ? comm_->get_id() : 0) << ' ' << mbox_->get_id() << ' ' << tag_;
233   XBT_DEBUG("RecvObserver comm:%p mbox:%u tag:%d", comm_, mbox_->get_id(), tag_);
234   stream << ' ' << fun_call_;
235 }
236 std::string CommIrecvSimcall::to_string() const
237 {
238   return "CommAsyncRecv(comm_id: " + std::to_string(comm_->get_id()) + " mbox:" + std::to_string(mbox_->get_id()) +
239          " tag: " + std::to_string(tag_) + ")";
240 }
241
242 } // namespace simgrid::kernel::actor