1 /* Copyright (c) 2019-2023. The SimGrid Team. All rights reserved. */
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. */
6 #include "simgrid/s4u/Host.hpp"
7 #include "src/kernel/activity/CommImpl.hpp"
8 #include "src/kernel/activity/MailboxImpl.hpp"
9 #include "src/kernel/activity/MessageQueueImpl.hpp"
10 #include "src/kernel/actor/ActorImpl.hpp"
11 #include "src/kernel/actor/SimcallObserver.hpp"
12 #include "src/mc/mc_config.hpp"
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(obs_comm, mc_observer, "Logging specific to the Communication simcalls observation");
18 namespace simgrid::kernel::actor {
20 ActivityTestanySimcall::ActivityTestanySimcall(ActorImpl* actor, const std::vector<activity::ActivityImpl*>& activities,
21 std::string_view fun_call)
22 : ResultingSimcall(actor, -1), activities_(activities), fun_call_(fun_call)
25 // list all the activities that are ready
26 for (unsigned i = 0; i < activities_.size(); i++)
27 if (activities_[i]->test(get_issuer()))
28 indexes_.push_back(i);
31 int ActivityTestanySimcall::get_max_consider() const
33 return indexes_.size() + 1;
36 void ActivityTestanySimcall::prepare(int times_considered)
38 if (times_considered < static_cast<int>(indexes_.size()))
39 next_value_ = indexes_.at(times_considered);
43 static void serialize_activity_test(const activity::ActivityImpl* act, std::string const& call_location,
44 std::stringstream& stream)
46 if (const auto* comm = dynamic_cast<activity::CommImpl const*>(act)) {
47 stream << " " << (short)mc::Transition::Type::COMM_TEST;
48 stream << ' ' << comm->get_id();
49 stream << ' ' << (comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1);
50 stream << ' ' << (comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1);
51 stream << ' ' << comm->get_mailbox_id();
52 stream << ' ' << call_location;
54 stream << (short)mc::Transition::Type::UNKNOWN;
55 XBT_CRITICAL("Unknown transition in a test any. Bad things may happen");
58 static std::string to_string_activity_test(const activity::ActivityImpl* act)
60 if (const auto* comm = dynamic_cast<activity::CommImpl const*>(act)) {
61 return "CommTest(comm_id:" + std::to_string(comm->get_id()) +
62 " src:" + std::to_string(comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1) +
63 " dst:" + std::to_string(comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1) +
64 " mbox:" + std::to_string(comm->get_mailbox_id()) + ")";
66 return "TestUnknownType()";
69 void ActivityTestanySimcall::serialize(std::stringstream& stream) const
71 XBT_DEBUG("Serialize %s", to_string().c_str());
72 stream << (short)mc::Transition::Type::TESTANY << ' ' << activities_.size() << ' ';
73 for (auto const* act : activities_) {
74 // fun_call of each activity embedded in the TestAny is not known, so let's use the location of the TestAny itself
75 serialize_activity_test(act, fun_call_, stream);
80 std::string ActivityTestanySimcall::to_string() const
82 std::stringstream buffer("TestAny(");
84 for (auto const* act : activities_) {
89 buffer << to_string_activity_test(act);
95 void ActivityTestSimcall::serialize(std::stringstream& stream) const
97 serialize_activity_test(activity_, fun_call_, stream);
99 std::string ActivityTestSimcall::to_string() const
101 return to_string_activity_test(activity_);
103 static void serialize_activity_wait(const activity::ActivityImpl* act, bool timeout, std::string const& call_location,
104 std::stringstream& stream)
106 if (const auto* comm = dynamic_cast<activity::CommImpl const*>(act)) {
107 stream << (short)mc::Transition::Type::COMM_WAIT << ' ';
108 stream << timeout << ' ' << comm->get_id();
110 stream << ' ' << (comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1);
111 stream << ' ' << (comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1);
112 stream << ' ' << comm->get_mailbox_id();
113 stream << ' ' << call_location;
115 stream << (short)mc::Transition::Type::UNKNOWN;
118 static std::string to_string_activity_wait(const activity::ActivityImpl* act)
120 if (const auto* comm = dynamic_cast<activity::CommImpl const*>(act)) {
121 return "CommWait(comm_id:" + std::to_string(comm->get_id()) +
122 " src:" + std::to_string(comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1) +
123 " dst:" + std::to_string(comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1) +
124 " mbox:" + (comm->get_mailbox() == nullptr ? "-" : comm->get_mailbox()->get_name()) +
125 "(id:" + std::to_string(comm->get_mailbox_id()) + "))";
127 return "WaitUnknownType()";
131 void ActivityWaitSimcall::serialize(std::stringstream& stream) const
133 serialize_activity_wait(activity_, timeout_ > 0, fun_call_, stream);
135 void ActivityWaitanySimcall::serialize(std::stringstream& stream) const
137 XBT_DEBUG("Serialize %s", to_string().c_str());
138 stream << (short)mc::Transition::Type::WAITANY << ' ' << activities_.size() << ' ';
139 for (auto const* act : activities_) {
140 // fun_call of each activity embedded in the WaitAny is not known, so let's use the location of the WaitAny itself
141 serialize_activity_wait(act, timeout_ > 0, fun_call_, stream);
146 std::string ActivityWaitSimcall::to_string() const
148 return to_string_activity_wait(activity_);
150 std::string ActivityWaitanySimcall::to_string() const
152 std::stringstream buffer("WaitAny(");
154 for (auto const* act : activities_) {
159 buffer << to_string_activity_test(act);
164 ActivityWaitanySimcall::ActivityWaitanySimcall(ActorImpl* actor, const std::vector<activity::ActivityImpl*>& activities,
165 double timeout, std::string_view fun_call)
166 : ResultingSimcall(actor, -1), activities_(activities), timeout_(timeout), fun_call_(fun_call)
168 // list all the activities that are ready
170 for (unsigned i = 0; i < activities_.size(); i++)
171 if (activities_[i]->test(get_issuer()))
172 indexes_.push_back(i);
175 bool ActivityWaitSimcall::is_enabled()
177 // FIXME: if _sg_mc_timeout == 1 and if we have either a sender or receiver timeout, the transition is enabled
178 // because even if the communication is not ready, it can timeout and won't block.
180 return activity_->test(get_issuer());
183 bool ActivityWaitanySimcall::is_enabled()
185 // list all the activities that are ready
187 for (unsigned i = 0; i < activities_.size(); i++)
188 if (activities_[i]->test(get_issuer()))
189 indexes_.push_back(i);
191 // if (_sg_mc_timeout && timeout_) FIXME: deal with the potential timeout of the WaitAny
193 // FIXME: even if the WaitAny has no timeout, some of the activities may still have one.
194 // we should iterate over the vector searching for them
195 return not indexes_.empty();
198 int ActivityWaitanySimcall::get_max_consider() const
200 int res = indexes_.size();
201 // if (_sg_mc_timeout && timeout_)
207 void ActivityWaitanySimcall::prepare(int times_considered)
209 if (times_considered < static_cast<int>(indexes_.size()))
210 next_value_ = indexes_.at(times_considered);
215 void CommIsendSimcall::serialize(std::stringstream& stream) const
217 /* Note that the comm_ is 0 until after the execution of the simcall */
218 stream << (short)mc::Transition::Type::COMM_ASYNC_SEND << ' ';
219 stream << (comm_ ? comm_->get_id() : 0) << ' ' << mbox_->get_id() << ' ' << tag_;
220 XBT_DEBUG("SendObserver comm:%p mbox:%u tag:%d", comm_, mbox_->get_id(), tag_);
221 stream << ' ' << fun_call_;
223 std::string CommIsendSimcall::to_string() const
225 return "CommAsyncSend(comm_id: " + std::to_string((comm_ ? comm_->get_id() : 0)) + " mbox:" +
226 std::to_string(mbox_->get_id()) + " tag: " + std::to_string(tag_) + ")";
229 void CommIrecvSimcall::serialize(std::stringstream& stream) const
231 /* Note that the comm_ is 0 until after the execution of the simcall */
232 stream << (short)mc::Transition::Type::COMM_ASYNC_RECV << ' ';
233 stream << (comm_ ? comm_->get_id() : 0) << ' ' << mbox_->get_id() << ' ' << tag_;
234 XBT_DEBUG("RecvObserver comm:%p mbox:%u tag:%d", comm_, mbox_->get_id(), tag_);
235 stream << ' ' << fun_call_;
238 std::string CommIrecvSimcall::to_string() const
240 return "CommAsyncRecv(comm_id: " + std::to_string((comm_ ? comm_->get_id() : 0)) + " mbox:" +
241 std::to_string(mbox_->get_id()) + " tag: " + std::to_string(tag_) + ")";
244 void MessIputSimcall::serialize(std::stringstream& stream) const
246 stream << mess_ << ' ' << queue_;
247 XBT_DEBUG("PutObserver mess:%p queue:%p", mess_, queue_);
250 std::string MessIputSimcall::to_string() const
252 return "MessAsyncPut(queue:" + queue_->get_name() + ")";
255 void MessIgetSimcall::serialize(std::stringstream& stream) const
257 stream << mess_ << ' ' << queue_;
258 XBT_DEBUG("GettObserver mess:%p queue:%p", mess_, queue_);
261 std::string MessIgetSimcall::to_string() const
263 return "MessAsyncGet(queue:" + queue_->get_name() + ")";
268 } // namespace simgrid::kernel::actor