X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/640e6f6494f5e1151f6436aea0e0c515da2c144b..7b6fecb801d2d513ebbd7bea94c52322e2cc1df2:/src/s4u/s4u_Actor.cpp diff --git a/src/s4u/s4u_Actor.cpp b/src/s4u/s4u_Actor.cpp index 1b45a6a7e7..df7dc2d058 100644 --- a/src/s4u/s4u_Actor.cpp +++ b/src/s4u/s4u_Actor.cpp @@ -5,58 +5,64 @@ #include "simgrid/Exception.hpp" #include "simgrid/actor.h" +#include "simgrid/modelchecker.h" #include "simgrid/s4u/Actor.hpp" #include "simgrid/s4u/Exec.hpp" #include "simgrid/s4u/Host.hpp" #include "simgrid/s4u/VirtualMachine.hpp" +#include "src/include/mc/mc.h" #include "src/kernel/activity/ExecImpl.hpp" -#include "src/simix/smx_private.hpp" +#include "src/mc/mc_replay.hpp" #include "src/surf/HostImpl.hpp" #include #include -XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_actor, "S4U actors"); +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(s4u_actor, s4u, "S4U actors"); namespace simgrid { namespace s4u { -xbt::signal s4u::Actor::on_creation; -xbt::signal s4u::Actor::on_suspend; -xbt::signal s4u::Actor::on_resume; -xbt::signal s4u::Actor::on_sleep; -xbt::signal s4u::Actor::on_wake_up; -xbt::signal s4u::Actor::on_migration_start; -xbt::signal s4u::Actor::on_migration_end; -xbt::signal s4u::Actor::on_destruction; +xbt::signal s4u::Actor::on_creation; +xbt::signal s4u::Actor::on_suspend; +xbt::signal s4u::Actor::on_resume; +xbt::signal s4u::Actor::on_sleep; +xbt::signal s4u::Actor::on_wake_up; +xbt::signal s4u::Actor::on_migration_start; // deprecated +xbt::signal s4u::Actor::on_migration_end; // deprecated +xbt::signal s4u::Actor::on_host_change; +xbt::signal s4u::Actor::on_termination; +xbt::signal s4u::Actor::on_destruction; // ***** Actor creation ***** -ActorPtr Actor::self() +Actor* Actor::self() { - smx_context_t self_context = kernel::context::Context::self(); + kernel::context::Context* self_context = kernel::context::Context::self(); if (self_context == nullptr) - return ActorPtr(); + return nullptr; - return self_context->get_actor()->iface(); + return self_context->get_actor()->ciface(); } + ActorPtr Actor::init(const std::string& name, s4u::Host* host) { - smx_actor_t self = SIMIX_process_self(); - kernel::actor::ActorImpl* actor = simix::simcall([self, &name, host] { return self->init(name, host).get(); }); - return actor->ciface(); + kernel::actor::ActorImpl* self = kernel::actor::ActorImpl::self(); + kernel::actor::ActorImpl* actor = + kernel::actor::simcall([self, &name, host] { return self->init(name, host).get(); }); + return actor->iface(); } ActorPtr Actor::start(const std::function& code) { - simgrid::simix::simcall([this, &code] { pimpl_->start(code); }); + simgrid::kernel::actor::simcall([this, &code] { pimpl_->start(code); }); return this; } ActorPtr Actor::create(const std::string& name, s4u::Host* host, const std::function& code) { - smx_actor_t self = SIMIX_process_self(); + kernel::actor::ActorImpl* self = kernel::actor::ActorImpl::self(); kernel::actor::ActorImpl* actor = - simix::simcall([self, &name, host, &code] { return self->init(name, host)->start(code); }); + kernel::actor::simcall([self, &name, host, &code] { return self->init(name, host)->start(code); }); return actor->iface(); } @@ -64,7 +70,7 @@ ActorPtr Actor::create(const std::string& name, s4u::Host* host, const std::func ActorPtr Actor::create(const std::string& name, s4u::Host* host, const std::string& function, std::vector args) { - simix::ActorCodeFactory& factory = SIMIX_get_actor_code_factory(function); + const simix::ActorCodeFactory& factory = SIMIX_get_actor_code_factory(function); return create(name, host, factory(std::move(args))); } @@ -76,57 +82,68 @@ void intrusive_ptr_release(Actor* actor) { intrusive_ptr_release(actor->pimpl_); } +int Actor::get_refcount() +{ + return pimpl_->get_refcount(); +} // ***** Actor methods ***** void Actor::join() { - simcall_process_join(this->pimpl_, -1); + join(-1); } void Actor::join(double timeout) { - simcall_process_join(this->pimpl_, timeout); + kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self(); + kernel::actor::ActorImpl* target = pimpl_; + kernel::actor::simcall_blocking([issuer, target, timeout] { + if (target->finished_) { + // The joined process is already finished, just wake up the issuer right away + issuer->simcall_answer(); + } else { + smx_activity_t sync = issuer->join(target, timeout); + sync->register_simcall(&issuer->simcall); + } + }); } void Actor::set_auto_restart(bool autorestart) { - simix::simcall([this, autorestart]() { + kernel::actor::simcall([this, autorestart]() { xbt_assert(autorestart && not pimpl_->has_to_auto_restart()); // FIXME: handle all cases pimpl_->set_auto_restart(autorestart); kernel::actor::ProcessArg* arg = new kernel::actor::ProcessArg(pimpl_->get_host(), pimpl_); - XBT_DEBUG("Adding Process %s to the actors_at_boot_ list of Host %s", arg->name.c_str(), arg->host->get_cname()); - pimpl_->get_host()->pimpl_->actors_at_boot_.emplace_back(arg); + XBT_DEBUG("Adding %s to the actors_at_boot_ list of Host %s", arg->name.c_str(), arg->host->get_cname()); + pimpl_->get_host()->pimpl_->add_actor_at_boot(arg); }); } -void Actor::on_exit(int_f_pvoid_pvoid_t fun, - void* data) /* deprecated: cleanup SIMIX_process_on_exit: change prototype of second parameter and - remove the last one */ +void Actor::on_exit(const std::function& fun) const { - simix::simcall([this, fun, data] { SIMIX_process_on_exit(pimpl_, fun, data); }); + kernel::actor::simcall([this, &fun] { pimpl_->on_exit->emplace_back(fun); }); } -void Actor::on_exit(const std::function& fun, void* data) /* deprecated */ +void Actor::set_host(Host* new_host) { - on_exit([fun, data](bool exit) { fun(exit, data); }); -} - -void Actor::on_exit(const std::function& fun) -{ - simix::simcall( - [this, fun] { SIMIX_process_on_exit(pimpl_, [fun](int a, void* /*data*/) { fun(a != 0); }, nullptr); }); -} + if (s4u::Actor::on_migration_start.get_slot_count() > 0) { // XBT_ATTRIB_DEPRECATED_v329 + static bool already_warned = false; + if (not already_warned) { + XBT_INFO("Please use s4u::Actor::on_host_change instead of s4u::Actor::on_migration_start. This will be removed " + "in v3.29"); + already_warned = true; + } + s4u::Actor::on_migration_start(*this); + } -void Actor::migrate(Host* new_host) -{ - s4u::Actor::on_migration_start(this); + const s4u::Host* previous_location = get_host(); - simix::simcall([this, new_host]() { + kernel::actor::simcall([this, new_host]() { if (pimpl_->waiting_synchro != nullptr) { // The actor is blocked on an activity. If it's an exec, migrate it too. - // FIXME: implement the migration of other kind of activities + // FIXME: implement the migration of other kinds of activities kernel::activity::ExecImplPtr exec = boost::dynamic_pointer_cast(pimpl_->waiting_synchro); xbt_assert(exec.get() != nullptr, "We can only migrate blocked actors when they are blocked on executions."); @@ -135,17 +152,27 @@ void Actor::migrate(Host* new_host) this->pimpl_->set_host(new_host); }); - s4u::Actor::on_migration_end(this); + if (s4u::Actor::on_migration_end.get_slot_count() > 0) { // XBT_ATTRIB_DEPRECATED_v329 + static bool already_warned = false; + if (not already_warned) { + XBT_INFO("Please use s4u::Actor::on_host_change instead of s4u::Actor::on_migration_end. This will be removed in " + "v3.29"); + already_warned = true; + } + s4u::Actor::on_migration_end(*this); + } + + s4u::Actor::on_host_change(*this, *previous_location); } -s4u::Host* Actor::get_host() +s4u::Host* Actor::get_host() const { return this->pimpl_->get_host(); } void Actor::daemonize() { - simix::simcall([this]() { pimpl_->daemonize(); }); + kernel::actor::simcall([this]() { pimpl_->daemonize(); }); } bool Actor::is_daemon() const @@ -175,24 +202,32 @@ aid_t Actor::get_ppid() const void Actor::suspend() { - s4u::Actor::on_suspend(this); - simcall_process_suspend(pimpl_); + kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self(); + kernel::actor::ActorImpl* target = pimpl_; + s4u::Actor::on_suspend(*this); + kernel::actor::simcall_blocking([issuer, target]() { + target->suspend(); + if (target != issuer) { + /* If we are suspending ourselves, then just do not finish the simcall now */ + issuer->simcall_answer(); + } + }); } void Actor::resume() { - simix::simcall([this] { pimpl_->resume(); }); - s4u::Actor::on_resume(this); + kernel::actor::simcall([this] { pimpl_->resume(); }); + s4u::Actor::on_resume(*this); } bool Actor::is_suspended() { - return simix::simcall([this] { return pimpl_->is_suspended(); }); + return pimpl_->is_suspended(); } void Actor::set_kill_time(double kill_time) { - simix::simcall([this, kill_time] { pimpl_->set_kill_time(kill_time); }); + kernel::actor::simcall([this, kill_time] { pimpl_->set_kill_time(kill_time); }); } /** @brief Get the kill time of an actor(or 0 if unset). */ @@ -201,71 +236,48 @@ double Actor::get_kill_time() return pimpl_->get_kill_time(); } -void Actor::kill(aid_t pid) // deprecated -{ - kernel::actor::ActorImpl* killer = SIMIX_process_self(); - kernel::actor::ActorImpl* victim = SIMIX_process_from_PID(pid); - if (victim != nullptr) { - simix::simcall([killer, victim] { killer->kill(victim); }); - } else { - std::ostringstream oss; - oss << "kill: (" << pid << ") - No such actor" << std::endl; - throw std::runtime_error(oss.str()); - } -} - void Actor::kill() { - kernel::actor::ActorImpl* process = SIMIX_process_self(); - simix::simcall([this, process] { - if (pimpl_ == simix_global->maestro_process) - pimpl_->exit(); - else - process->kill(pimpl_); - }); -} - -kernel::actor::ActorImpl* Actor::get_impl() -{ - return pimpl_; + kernel::actor::ActorImpl* self = kernel::actor::ActorImpl::self(); + kernel::actor::simcall([this, self] { self->kill(pimpl_); }); } // ***** Static functions ***** ActorPtr Actor::by_pid(aid_t pid) { - kernel::actor::ActorImpl* process = SIMIX_process_from_PID(pid); - if (process != nullptr) - return process->iface(); + kernel::actor::ActorImpl* actor = SIMIX_process_from_PID(pid); + if (actor != nullptr) + return actor->iface(); else return ActorPtr(); } void Actor::kill_all() { - kernel::actor::ActorImpl* self = SIMIX_process_self(); - simix::simcall([self] { self->kill_all(); }); + kernel::actor::ActorImpl* self = kernel::actor::ActorImpl::self(); + kernel::actor::simcall([self] { self->kill_all(); }); } -std::unordered_map* Actor::get_properties() +const std::unordered_map* Actor::get_properties() const { - return simix::simcall([this] { return this->pimpl_->get_properties(); }); + return pimpl_->get_properties(); } /** Retrieve the property value (or nullptr if not set) */ -const char* Actor::get_property(const std::string& key) +const char* Actor::get_property(const std::string& key) const { - return simix::simcall([this, &key] { return pimpl_->get_property(key); }); + return pimpl_->get_property(key); } void Actor::set_property(const std::string& key, const std::string& value) { - simix::simcall([this, &key, &value] { pimpl_->set_property(key, value); }); + kernel::actor::simcall([this, &key, &value] { pimpl_->set_property(key, value); }); } Actor* Actor::restart() { - return simix::simcall([this]() { return pimpl_->restart(); }); + return kernel::actor::simcall([this]() { return pimpl_->restart(); }); } // ***** this_actor ***** @@ -283,32 +295,41 @@ namespace this_actor { */ bool is_maestro() { - kernel::actor::ActorImpl* process = SIMIX_process_self(); - return process == nullptr || process == simix_global->maestro_process; + return SIMIX_is_maestro(); } void sleep_for(double duration) { - if (duration > 0) { - kernel::actor::ActorImpl* actor = SIMIX_process_self(); - Actor::on_sleep(actor->iface()); - - simcall_process_sleep(duration); + xbt_assert(std::isfinite(duration), "duration is not finite!"); - Actor::on_wake_up(actor->iface()); + if (duration > 0) { + kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self(); + Actor::on_sleep(*issuer->ciface()); + + kernel::actor::simcall_blocking([issuer, duration]() { + if (MC_is_active() || MC_record_replay_is_active()) { + MC_process_clock_add(issuer, duration); + issuer->simcall_answer(); + return; + } + smx_activity_t sync = issuer->sleep(duration); + sync->register_simcall(&issuer->simcall); + }); + + Actor::on_wake_up(*issuer->ciface()); } } void yield() { - simix::simcall([] { /* do nothing*/ }); + kernel::actor::simcall([] { /* do nothing*/ }); } -XBT_PUBLIC void sleep_until(double timeout) +XBT_PUBLIC void sleep_until(double wakeup_time) { double now = SIMIX_get_clock(); - if (timeout > now) - sleep_for(timeout - now); + if (wakeup_time > now) + sleep_for(wakeup_time - now); } void execute(double flops) @@ -324,11 +345,22 @@ void execute(double flops, double priority) void parallel_execute(const std::vector& hosts, const std::vector& flops_amounts, const std::vector& bytes_amounts) { - parallel_execute(hosts, flops_amounts, bytes_amounts, -1); + exec_init(hosts, flops_amounts, bytes_amounts)->wait(); } void parallel_execute(const std::vector& hosts, const std::vector& flops_amounts, - const std::vector& bytes_amounts, double timeout) + const std::vector& bytes_amounts, double timeout) // XBT_ATTRIB_DEPRECATED_v329 +{ + exec_init(hosts, flops_amounts, bytes_amounts)->wait_for(timeout); +} + +ExecPtr exec_init(double flops_amount) +{ + return ExecPtr(new ExecSeq(get_host(), flops_amount)); +} + +ExecPtr exec_init(const std::vector& hosts, const std::vector& flops_amounts, + const std::vector& bytes_amounts) { xbt_assert(hosts.size() > 0, "Your parallel executions must span over at least one host."); xbt_assert(hosts.size() == flops_amounts.size() || flops_amounts.empty(), @@ -350,38 +382,6 @@ void parallel_execute(const std::vector& hosts, const std::vectorset_timeout(timeout)->wait(); -} - -// deprecated -void parallel_execute(int host_nb, s4u::Host* const* host_list, const double* flops_amount, const double* bytes_amount, - double timeout) -{ - smx_activity_t s = - simcall_execution_parallel_start("", host_nb, host_list, flops_amount, bytes_amount, /* rate */ -1, timeout); - simcall_execution_wait(s); - delete[] flops_amount; - delete[] bytes_amount; -} - -// deprecated -void parallel_execute(int host_nb, s4u::Host* const* host_list, const double* flops_amount, const double* bytes_amount) -{ - smx_activity_t s = simcall_execution_parallel_start("", host_nb, host_list, flops_amount, bytes_amount, - /* rate */ -1, /*timeout*/ -1); - simcall_execution_wait(s); - delete[] flops_amount; - delete[] bytes_amount; -} - -ExecPtr exec_init(double flops_amount) -{ - return ExecPtr(new ExecSeq(get_host(), flops_amount)); -} - -ExecPtr exec_init(const std::vector& hosts, const std::vector& flops_amounts, - const std::vector& bytes_amounts) -{ return ExecPtr(new ExecPar(hosts, flops_amounts, bytes_amounts)); } @@ -394,104 +394,65 @@ ExecPtr exec_async(double flops) aid_t get_pid() { - return SIMIX_process_self()->get_pid(); + return simgrid::kernel::actor::ActorImpl::self()->get_pid(); } aid_t get_ppid() { - return SIMIX_process_self()->get_ppid(); + return simgrid::kernel::actor::ActorImpl::self()->get_ppid(); } std::string get_name() { - return SIMIX_process_self()->get_name(); + return simgrid::kernel::actor::ActorImpl::self()->get_name(); } const char* get_cname() { - return SIMIX_process_self()->get_cname(); + return simgrid::kernel::actor::ActorImpl::self()->get_cname(); } Host* get_host() { - return SIMIX_process_self()->get_host(); + return simgrid::kernel::actor::ActorImpl::self()->get_host(); } void suspend() { - kernel::actor::ActorImpl* actor = SIMIX_process_self(); - Actor::on_suspend(actor->iface()); - - simcall_process_suspend(actor); + kernel::actor::ActorImpl* self = simgrid::kernel::actor::ActorImpl::self(); + s4u::Actor::on_suspend(*self->ciface()); + kernel::actor::simcall_blocking([self] { self->suspend(); }); } void resume() { - kernel::actor::ActorImpl* self = SIMIX_process_self(); - simix::simcall([self] { self->resume(); }); - Actor::on_resume(self->iface()); + kernel::actor::ActorImpl* self = simgrid::kernel::actor::ActorImpl::self(); + kernel::actor::simcall([self] { self->resume(); }); + Actor::on_resume(*self->ciface()); } void exit() { - kernel::actor::ActorImpl* self = SIMIX_process_self(); - simgrid::simix::simcall([self] { self->exit(); }); + kernel::actor::ActorImpl* self = simgrid::kernel::actor::ActorImpl::self(); + simgrid::kernel::actor::simcall([self] { self->exit(); }); } void on_exit(const std::function& fun) { - SIMIX_process_self()->iface()->on_exit(fun); -} - -void on_exit(const std::function& fun, void* data) /* deprecated */ -{ - SIMIX_process_self()->iface()->on_exit([fun, data](bool exit) { fun(exit, data); }); + simgrid::kernel::actor::ActorImpl::self()->iface()->on_exit(fun); } /** @brief Moves the current actor to another host * * @see simgrid::s4u::Actor::migrate() for more information */ -void migrate(Host* new_host) -{ - SIMIX_process_self()->iface()->migrate(new_host); -} - -std::string getName() /* deprecated */ -{ - return get_name(); -} -const char* getCname() /* deprecated */ -{ - return get_cname(); -} -bool isMaestro() /* deprecated */ -{ - return is_maestro(); -} -aid_t getPid() /* deprecated */ -{ - return get_pid(); -} -aid_t getPpid() /* deprecated */ -{ - return get_ppid(); -} -Host* getHost() /* deprecated */ -{ - return get_host(); -} -void on_exit(int_f_pvoid_pvoid_t fun, void* data) /* deprecated */ -{ - SIMIX_process_self()->iface()->on_exit([fun, data](int a) { fun((void*)(intptr_t)a, data); }); -} -void onExit(int_f_pvoid_pvoid_t fun, void* data) /* deprecated */ +void set_host(Host* new_host) { - on_exit([fun, data](int a) { fun((void*)(intptr_t)a, data); }); + simgrid::kernel::actor::ActorImpl::self()->iface()->set_host(new_host); } -void kill() /* deprecated */ +void migrate(Host* new_host) // deprecated { - exit(); + set_host(new_host); } } // namespace this_actor @@ -500,6 +461,19 @@ void kill() /* deprecated */ /* **************************** Public C interface *************************** */ +sg_actor_t sg_actor_init(const char* name, sg_host_t host) +{ + return simgrid::s4u::Actor::init(name, host).get(); +} + +void sg_actor_start(sg_actor_t actor, xbt_main_func_t code, int argc, char** argv) +{ + simgrid::simix::ActorCode function; + if (code) + function = simgrid::xbt::wrap_main(code, argc, static_cast(argv)); + actor->start(std::move(function)); +} + /** @ingroup m_actor_management * @brief Returns the process ID of @a actor. * @@ -572,11 +546,11 @@ xbt_dict_t sg_actor_get_properties(sg_actor_t actor) { xbt_assert(actor != nullptr, "Invalid parameter: First argument must not be nullptr"); xbt_dict_t as_dict = xbt_dict_new_homogeneous(xbt_free_f); - std::unordered_map* props = actor->get_properties(); + const std::unordered_map* props = actor->get_properties(); if (props == nullptr) return nullptr; for (auto const& kv : *props) { - xbt_dict_set(as_dict, kv.first.c_str(), xbt_strdup(kv.second.c_str()), nullptr); + xbt_dict_set(as_dict, kv.first.c_str(), xbt_strdup(kv.second.c_str())); } return as_dict; } @@ -645,9 +619,13 @@ void sg_actor_daemonize(sg_actor_t actor) * * This function changes the value of the #sg_host_t on which @a actor is running. */ -void sg_actor_migrate(sg_actor_t process, sg_host_t host) +void sg_actor_set_host(sg_actor_t actor, sg_host_t host) { - process->migrate(host); + actor->set_host(host); +} +void sg_actor_migrate(sg_actor_t process, sg_host_t host) // deprecated +{ + process->set_host(host); } /** @ingroup m_actor_management @@ -720,3 +698,60 @@ void sg_actor_detach() { simgrid::kernel::actor::ActorImpl::detach(); } + +aid_t sg_actor_self_get_pid() +{ + return simgrid::s4u::this_actor::get_pid(); +} + +aid_t sg_actor_self_get_ppid() +{ + return simgrid::s4u::this_actor::get_ppid(); +} + +const char* sg_actor_self_get_name() +{ + return simgrid::s4u::this_actor::get_cname(); +} + +void* sg_actor_self_data() +{ + return simgrid::s4u::Actor::self()->get_data(); +} + +void sg_actor_self_data_set(void* userdata) +{ + simgrid::s4u::Actor::self()->set_data(userdata); +} + +sg_actor_t sg_actor_self() +{ + return simgrid::s4u::Actor::self(); +} + +void sg_actor_self_execute(double flops) +{ + simgrid::s4u::this_actor::execute(flops); +} + +/** @brief Take an extra reference on that actor to prevent it to be garbage-collected */ +void sg_actor_ref(sg_actor_t actor) +{ + intrusive_ptr_add_ref(actor); +} +/** @brief Release a reference on that actor so that it can get be garbage-collected */ +void sg_actor_unref(sg_actor_t actor) +{ + intrusive_ptr_release(actor); +} + +/** @brief Return the user data of a #sg_actor_t */ +void* sg_actor_data(const_sg_actor_t actor) +{ + return actor->get_data(); +} +/** @brief Set the user data of a #sg_actor_t */ +void sg_actor_data_set(sg_actor_t actor, void* userdata) +{ + actor->set_data(userdata); +}