From: Martin Quinson Date: Sun, 16 Oct 2022 09:54:03 +0000 (+0200) Subject: Implement pthread_join in MC mode for sthread X-Git-Tag: v3.34~776 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/666f14c5995d2584dbb8dea680f17e6a915da146?hp=9bc8f94845279e46a82d91d9bf55aa4df7be84b5 Implement pthread_join in MC mode for sthread --- diff --git a/ChangeLog b/ChangeLog index e782fb08f3..e3294b2dea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,9 @@ Models: - See also "A Flow-Level Wi-Fi Model for Large Scale Network Simulation" https://hal.archives-ouvertes.fr/hal-03777726 +sthread: + - Implement pthread_join in MC mode. + Fixed bugs (FG#.. -> FramaGit bugs; FG!.. -> FG merge requests) (FG: issues on Framagit; GH: issues on GitHub) - FG!118: Wi-Fi callback mechanism diff --git a/src/kernel/actor/SimcallObserver.cpp b/src/kernel/actor/SimcallObserver.cpp index 87991ccefa..294fc3a645 100644 --- a/src/kernel/actor/SimcallObserver.cpp +++ b/src/kernel/actor/SimcallObserver.cpp @@ -16,10 +16,6 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_observer, mc, "Logging specific to MC simcall namespace simgrid::kernel::actor { -void SimcallObserver::serialize(std::stringstream& stream) const -{ - stream << (short)mc::Transition::Type::UNKNOWN; -} void RandomSimcall::serialize(std::stringstream& stream) const { stream << (short)mc::Transition::Type::RANDOM << ' '; @@ -45,4 +41,22 @@ bool ConditionWaitSimcall::is_enabled() } return true; } +void ConditionWaitSimcall::serialize(std::stringstream& stream) const +{ + THROW_UNIMPLEMENTED; +} + +ActorJoinSimcall::ActorJoinSimcall(ActorImpl* actor, ActorImpl* other, double timeout) + : SimcallObserver(actor), other_(s4u::ActorPtr(other->get_iface())), timeout_(timeout) +{ +} +bool ActorJoinSimcall::is_enabled() +{ + return other_->get_impl()->wannadie(); +} +void ActorJoinSimcall::serialize(std::stringstream& stream) const +{ + stream << (short)mc::Transition::Type::ACTOR_JOIN << ' '; + stream << other_->get_pid() << ' ' << static_cast(timeout_ > 0); +} } // namespace simgrid::kernel::actor diff --git a/src/kernel/actor/SimcallObserver.hpp b/src/kernel/actor/SimcallObserver.hpp index a4095e4a42..909ebd1444 100644 --- a/src/kernel/actor/SimcallObserver.hpp +++ b/src/kernel/actor/SimcallObserver.hpp @@ -53,10 +53,11 @@ public: } /** Serialize to the given string buffer */ - virtual void serialize(std::stringstream& stream) const; + virtual void serialize(std::stringstream& stream) const = 0; - /** Some simcalls may only be observable under some conditions. - * Most simcalls are not visible from the MC because they don't have an observer at all. */ + /** Whether the MC should see this simcall. + * Simcall that don't have an observer (ie, most of them) are not visible from the MC, but if there is an observer, + * they are observable by default. */ virtual bool is_visible() const { return true; } }; @@ -99,13 +100,25 @@ public: : ResultingSimcall(actor, false), cond_(cond), mutex_(mutex), timeout_(timeout) { } + void serialize(std::stringstream& stream) const override; bool is_enabled() override; - bool is_visible() const override { return false; } activity::ConditionVariableImpl* get_cond() const { return cond_; } activity::MutexImpl* get_mutex() const { return mutex_; } double get_timeout() const { return timeout_; } }; +class ActorJoinSimcall final : public SimcallObserver { + s4u::ActorPtr const other_; // We need a Ptr to ensure access to the actor after its end, but Ptr requires s4u + const double timeout_; + +public: + ActorJoinSimcall(ActorImpl* actor, ActorImpl* other, double timeout = -1.0); + void serialize(std::stringstream& stream) const override; + bool is_enabled() override; + + s4u::ActorPtr get_other_actor() const { return other_; } + double get_timeout() const { return timeout_; } +}; } // namespace simgrid::kernel::actor #endif diff --git a/src/mc/remote/AppSide.cpp b/src/mc/remote/AppSide.cpp index e74e4d4f13..541089809e 100644 --- a/src/mc/remote/AppSide.cpp +++ b/src/mc/remote/AppSide.cpp @@ -145,6 +145,7 @@ void AppSide::handle_actors_status() const { auto const& actor_list = kernel::EngineImpl::get_instance()->get_actor_list(); int count = actor_list.size(); + XBT_DEBUG("Serialize the actors to answer ACTORS_STATUS from the checker. %d actors to go.", count); struct s_mc_message_actors_status_answer_t answer { MessageType::ACTORS_STATUS_REPLY, count diff --git a/src/mc/transition/Transition.cpp b/src/mc/transition/Transition.cpp index 3fb8ced4ac..520992744c 100644 --- a/src/mc/transition/Transition.cpp +++ b/src/mc/transition/Transition.cpp @@ -10,6 +10,7 @@ #if SIMGRID_HAVE_MC #include "src/mc/ModelChecker.hpp" +#include "src/mc/transition/TransitionActorJoin.hpp" #include "src/mc/transition/TransitionAny.hpp" #include "src/mc/transition/TransitionComm.hpp" #include "src/mc/transition/TransitionRandom.hpp" @@ -91,13 +92,18 @@ Transition* deserialize_transition(aid_t issuer, int times_considered, std::stri case Transition::Type::SEM_WAIT: return new SemaphoreTransition(issuer, times_considered, simcall, stream); + case Transition::Type::ACTOR_JOIN: + return new ActorJoinTransition(issuer, times_considered, stream); + case Transition::Type::UNKNOWN: return new Transition(Transition::Type::UNKNOWN, issuer, times_considered); default: break; } - xbt_die("Invalid transition type %d received", type); + xbt_die("Invalid transition type %d received. Did you implement a new observer in the app without implementing the " + "corresponding transition in the checker?", + type); #else xbt_die("Deserializing transitions is only interesting in MC mode."); #endif diff --git a/src/mc/transition/Transition.hpp b/src/mc/transition/Transition.hpp index 19e30b9051..91f02b9b0f 100644 --- a/src/mc/transition/Transition.hpp +++ b/src/mc/transition/Transition.hpp @@ -37,6 +37,7 @@ public: COMM_RECV, COMM_SEND, COMM_TEST, COMM_WAIT, /* Alphabetical ordering of COMM_* */ MUTEX_LOCK, MUTEX_TEST, MUTEX_TRYLOCK, MUTEX_UNLOCK, MUTEX_WAIT, /* alphabetical */ SEM_LOCK, SEM_UNLOCK, SEM_WAIT, /* alphabetical ordering of SEM transitions */ + ACTOR_JOIN, /* UNKNOWN must be last */ UNKNOWN); Type type_ = Type::UNKNOWN; diff --git a/src/mc/transition/TransitionActorJoin.cpp b/src/mc/transition/TransitionActorJoin.cpp new file mode 100644 index 0000000000..2f4b017c91 --- /dev/null +++ b/src/mc/transition/TransitionActorJoin.cpp @@ -0,0 +1,40 @@ +/* Copyright (c) 2015-2022. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "src/mc/transition/TransitionActorJoin.hpp" +#include "xbt/asserts.h" +#include +#if SIMGRID_HAVE_MC +#include "src/mc/ModelChecker.hpp" +#include "src/mc/api/RemoteApp.hpp" +#include "src/mc/api/State.hpp" +#endif + +#include + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_trans_actorlifecycle, mc_transition, + "Logging specific to MC transitions about actors' lifecycle: joining, ending"); + +namespace simgrid::mc { + +ActorJoinTransition::ActorJoinTransition(aid_t issuer, int times_considered, std::stringstream& stream) + : Transition(Type::ACTOR_JOIN, issuer, times_considered) +{ + xbt_assert(stream >> target_ >> timeout_); + XBT_DEBUG("ActorJoinTransition target:%ld, %s ", target_, (timeout_ ? "timeout" : "no-timeout")); +} +std::string ActorJoinTransition::to_string(bool verbose) const +{ + return xbt::string_printf("ActorJoin(target %ld, %s)", target_, (timeout_ ? "timeout" : "no timeout")); +} +bool ActorJoinTransition::depends(const Transition* other) const +{ + // Joining is indep with any other transitions: + // - It is only enabled once the target ends, and after this point it's enabled no matter what + // - Other joins don't affect it, and it does not impact on the enabledness of any other transition + return false; +} + +} // namespace simgrid::mc diff --git a/src/mc/transition/TransitionActorJoin.hpp b/src/mc/transition/TransitionActorJoin.hpp new file mode 100644 index 0000000000..da06a339e3 --- /dev/null +++ b/src/mc/transition/TransitionActorJoin.hpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2015-2022. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#ifndef SIMGRID_MC_TRANSITION_ACTOR_JOIN_HPP +#define SIMGRID_MC_TRANSITION_ACTOR_JOIN_HPP + +#include "src/kernel/actor/SimcallObserver.hpp" +#include "src/mc/transition/Transition.hpp" + +#include +#include +#include + +namespace simgrid::mc { + +class ActorJoinTransition : public Transition { + bool timeout_; + aid_t target_; + +public: + ActorJoinTransition(aid_t issuer, int times_considered, std::stringstream& stream); + std::string to_string(bool verbose) const override; + bool depends(const Transition* other) const override; + + bool get_timeout() const { return timeout_; } + /** Target ID */ + aid_t get_target() const { return target_; } +}; + +} // namespace simgrid::mc + +#endif diff --git a/src/s4u/s4u_Actor.cpp b/src/s4u/s4u_Actor.cpp index 8c0fc2e679..e4ec4be8c9 100644 --- a/src/s4u/s4u_Actor.cpp +++ b/src/s4u/s4u_Actor.cpp @@ -108,20 +108,21 @@ void Actor::join() const void Actor::join(double timeout) const { - xbt_assert(not(MC_is_active() || MC_record_replay_is_active()), - "Actor::join() is not usable in MC yet. Please report this bug."); - kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self(); const kernel::actor::ActorImpl* target = pimpl_; - kernel::actor::simcall_blocking([issuer, target, timeout] { - if (target->wannadie()) { - // The joined actor is already finished, just wake up the issuer right away - issuer->simcall_answer(); - } else { - kernel::activity::ActivityImplPtr sync = issuer->join(target, timeout); - sync->register_simcall(&issuer->simcall_); - } - }); + kernel::actor::ActorJoinSimcall observer{issuer, get_impl(), timeout}; + + kernel::actor::simcall_blocking( + [issuer, target, timeout] { + if (target->wannadie()) { + // The joined actor is already finished, just wake up the issuer right away + issuer->simcall_answer(); + } else { + kernel::activity::ActivityImplPtr sync = issuer->join(target, timeout); + sync->register_simcall(&issuer->simcall_); + } + }, + &observer); } Actor* Actor::set_auto_restart(bool autorestart) diff --git a/src/sthread/sthread.c b/src/sthread/sthread.c index a52fec8081..117156fd5c 100644 --- a/src/sthread/sthread.c +++ b/src/sthread/sthread.c @@ -78,7 +78,6 @@ int pthread_join(pthread_t thread, void** retval) { if (raw_pthread_join == NULL) intercepter_init(); - if (sthread_inside_simgrid) return raw_pthread_join(thread, retval); diff --git a/src/sthread/sthread_impl.cpp b/src/sthread/sthread_impl.cpp index 9eb1a91ff6..4ef0265325 100644 --- a/src/sthread/sthread_impl.cpp +++ b/src/sthread/sthread_impl.cpp @@ -46,7 +46,7 @@ int sthread_main(int argc, char** argv, char** envp, int (*raw_main)(int, char** /* Launch the user's main() on an actor */ sthread_enable(); - sg4::ActorPtr main_actor = sg4::Actor::create("tid 0", lilibeth, raw_main, argc, argv, envp); + sg4::ActorPtr main_actor = sg4::Actor::create("main thread", lilibeth, raw_main, argc, argv, envp); XBT_INFO("Starting the simulation."); sg4::Engine::get_instance()->run(); diff --git a/tools/cmake/DefinePackages.cmake b/tools/cmake/DefinePackages.cmake index 2ade51725d..e9b706048d 100644 --- a/tools/cmake/DefinePackages.cmake +++ b/tools/cmake/DefinePackages.cmake @@ -622,6 +622,8 @@ set(MC_SRC src/mc/sosp/Snapshot.hpp src/mc/transition/Transition.hpp + src/mc/transition/TransitionActorJoin.cpp + src/mc/transition/TransitionActorJoin.hpp src/mc/transition/TransitionAny.cpp src/mc/transition/TransitionAny.hpp src/mc/transition/TransitionComm.cpp