#include <simgrid/forward.h>
#include <simgrid/s4u/Activity.hpp>
+#include <simgrid/s4u/Actor.hpp>
#include <xbt/ex.h>
#include <atomic>
friend XBT_PUBLIC void intrusive_ptr_release(Exec* e);
friend XBT_PUBLIC void intrusive_ptr_add_ref(Exec* e);
#endif
- static xbt::signal<void(Actor const&)> on_start;
- static xbt::signal<void(Actor const&)> on_completion;
+ static xbt::signal<void(Actor const&, Exec const&)> on_start;
+ static xbt::signal<void(Actor const&, Exec const&)> on_completion;
virtual Exec* start() override = 0;
virtual double get_remaining_ratio() = 0;
Exec* cancel() override;
const std::string& get_name() const { return name_; }
const char* get_cname() const { return name_.c_str(); }
+ Host* get_host() const;
+ unsigned int get_host_number() const;
+ double get_start_time() const;
+ double get_finish_time() const;
+ double get_cost() const;
};
class XBT_PUBLIC ExecSeq : public Exec {
simgrid::s4u::Actor::on_wake_up.connect([](simgrid::s4u::Actor const& actor) {
simgrid::instr::Container::by_name(instr_pid(actor))->get_state("ACTOR_STATE")->pop_event();
});
- simgrid::s4u::Exec::on_start.connect([](simgrid::s4u::Actor const& actor) {
+ simgrid::s4u::Exec::on_start.connect([](simgrid::s4u::Actor const& actor, simgrid::s4u::Exec const&) {
simgrid::instr::Container::by_name(instr_pid(actor))->get_state("ACTOR_STATE")->push_event("execute");
});
- simgrid::s4u::Exec::on_completion.connect([](simgrid::s4u::Actor const& actor) {
+ simgrid::s4u::Exec::on_completion.connect([](simgrid::s4u::Actor const& actor, simgrid::s4u::Exec const&) {
simgrid::instr::Container::by_name(instr_pid(actor))->get_state("ACTOR_STATE")->pop_event();
});
simgrid::s4u::Comm::on_sender_start.connect([](simgrid::s4u::Actor const& actor) {
}
XBT_DEBUG("Create execute synchro %p: %s", this, get_cname());
- ExecImpl::on_creation(*this);
return this;
}
state_ = SIMIX_DONE;
}
- on_completion(*this);
-
clean_action();
if (timeout_detector_) {
/*************
* Callbacks *
*************/
-xbt::signal<void(ExecImpl&)> ExecImpl::on_creation;
-xbt::signal<void(ExecImpl const&)> ExecImpl::on_completion;
xbt::signal<void(ExecImpl const&, s4u::Host*)> ExecImpl::on_migration;
} // namespace activity
void post() override;
void finish() override;
- static xbt::signal<void(ExecImpl&)> on_creation;
- static xbt::signal<void(ExecImpl const&)> on_completion;
static xbt::signal<void(ExecImpl const&, s4u::Host*)> on_migration;
};
} // namespace activity
* under the terms of the license (GNU LGPL) which comes with this package. */
#include "simgrid/plugins/live_migration.h"
+#include "simgrid/s4u/Exec.hpp"
#include "src/kernel/activity/ExecImpl.hpp"
#include "src/plugins/vm/VirtualMachineImpl.hpp"
vm.extension_set<simgrid::vm::DirtyPageTrackingExt>(new simgrid::vm::DirtyPageTrackingExt());
}
-static void on_exec_creation(simgrid::kernel::activity::ExecImpl const& exec)
+static void on_exec_creation(simgrid::s4u::Actor const&, simgrid::s4u::Exec const& e)
{
- simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(exec.get_host());
+ auto exec = static_cast<simgrid::kernel::activity::ExecImpl*>(e.get_impl());
+ simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(exec->get_host());
if (vm == nullptr)
return;
if (vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->is_tracking()) {
- vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->track(&exec, exec.get_remaining());
+ vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->track(exec, exec->get_remaining());
} else {
- vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->track(&exec, 0.0);
+ vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->track(exec, 0.0);
}
}
-static void on_exec_completion(simgrid::kernel::activity::ExecImpl const& exec)
+static void on_exec_completion(simgrid::s4u::Actor const&, simgrid::s4u::Exec const& e)
{
- simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(exec.get_host());
+ auto exec = static_cast<simgrid::kernel::activity::ExecImpl*>(e.get_impl());
+ simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(exec->get_host());
if (vm == nullptr)
return;
/* If we are in the middle of dirty page tracking, we record how much computation has been done until now, and keep
* the information for the lookup_() function that will called soon. */
if (vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->is_tracking()) {
- double delta = vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->get_stored_remains(&exec);
+ double delta = vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->get_stored_remains(exec);
vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->update_dirty_page_count(delta);
}
- vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->untrack(&exec);
+ vm->get_impl()->extension<simgrid::vm::DirtyPageTrackingExt>()->untrack(exec);
}
void sg_vm_dirty_page_tracking_init()
simgrid::vm::DirtyPageTrackingExt::EXTENSION_ID =
simgrid::vm::VirtualMachineImpl::extension_create<simgrid::vm::DirtyPageTrackingExt>();
simgrid::vm::VirtualMachineImpl::on_creation.connect(&on_virtual_machine_creation);
- simgrid::kernel::activity::ExecImpl::on_creation.connect(&on_exec_creation);
- simgrid::kernel::activity::ExecImpl::on_completion.connect(&on_exec_completion);
+ simgrid::s4u::Exec::on_start.connect(&on_exec_creation);
+ simgrid::s4u::Exec::on_completion.connect(&on_exec_completion);
}
}
task_id = 0;
}
});
- simgrid::kernel::activity::ExecImpl::on_creation.connect(
- [this](simgrid::kernel::activity::ExecImpl const& activity) {
- if (activity.get_host() == get_host())
- pre_task();
- });
- simgrid::kernel::activity::ExecImpl::on_completion.connect(
- [this](simgrid::kernel::activity::ExecImpl const& activity) {
- // For more than one host (not yet supported), we can access the host via
- // simcalls_.front()->issuer->iface()->get_host()
- if (activity.get_host() == get_host() && iteration_running) {
- comp_timer += activity.surf_action_->get_finish_time() - activity.surf_action_->get_start_time();
- }
- });
+ simgrid::s4u::Exec::on_start.connect([this](simgrid::s4u::Actor const&, simgrid::s4u::Exec const& activity) {
+ if (activity.get_host() == get_host())
+ pre_task();
+ });
+ simgrid::s4u::Exec::on_completion.connect([this](simgrid::s4u::Actor const&, simgrid::s4u::Exec const& activity) {
+ // For more than one host (not yet supported), we can access the host via
+ // simcalls_.front()->issuer->iface()->get_host()
+ if (activity.get_host() == get_host() && iteration_running) {
+ comp_timer += activity.get_finish_time() - activity.get_start_time();
+ }
+ });
// FIXME I think that this fires at the same time for all hosts, so when the src sends something,
// the dst will be notified even though it didn't even arrive at the recv yet
simgrid::s4u::Link::on_communicate.connect(
#include "simgrid/plugins/energy.h"
#include "simgrid/s4u/Engine.hpp"
-#include "src/kernel/activity/ExecImpl.hpp"
+#include "simgrid/s4u/Exec.hpp"
#include "src/include/surf/surf.hpp"
+#include "src/kernel/activity/ExecImpl.hpp"
#include "src/plugins/vm/VirtualMachineImpl.hpp"
#include "src/surf/cpu_interface.hpp"
// that the next trigger would be the 2nd compute, hence ignoring the idle time
// during the recv call. By updating at the beginning of a compute, we can
// fix that. (If the cpu is not idle, this is not required.)
- simgrid::kernel::activity::ExecImpl::on_creation.connect([](simgrid::kernel::activity::ExecImpl const& activity) {
+ simgrid::s4u::Exec::on_start.connect([](simgrid::s4u::Actor const&, simgrid::s4u::Exec const& activity) {
if (activity.get_host_number() == 1) { // We only run on one host
simgrid::s4u::Host* host = activity.get_host();
simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(host);
#include "src/plugins/vm/VirtualMachineImpl.hpp"
#include <simgrid/s4u.hpp>
+// Makes sure that this plugin can be activated from the command line with ``--plugin=name``
SIMGRID_REGISTER_PLUGIN(host_load, "Cpu load", &sg_host_load_plugin_init)
-/** @addtogroup plugin_load
+/** @defgroup plugin_host_load
-This plugin makes it very simple for users to obtain the current load for each host.
+ @rst
+Simple plugin that monitors the current load for each host.
+
+In addition, this constitutes a good introductory example on how to write a plugin.
+It attaches an extension to each host to store some data, and places callbacks in the following signals:
+
+ - :cpp:member:`simgrid::s4u::Host::on_creation`: Attach a new extension to the newly created host.
+ - :cpp:member:`simgrid::s4u::Exec::on_start`: Make note that a new execution started, increasing the load.
+ - :cpp:member:`simgrid::s4u::Exec::on_completion`: Make note that an execution completed, decreasing the load.
+ - :cpp:member:`simgrid::s4u::Host::on_state_change`: Do what is appropriate when the host gets suspended, turned off or similar.
+ - :cpp:member:`simgrid::s4u::Host::on_speed_change`: Do what is appropriate when the DVFS is modified.
+
+ Note that extensions are automatically destroyed when the host gets destroyed.
+ @endrst
*/
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_plugin_load, surf, "Logging specific to the HostLoad plugin");
static const double activity_uninitialized_remaining_cost = -1;
+/** This class stores the extra data needed by this plugin about a given host
+ *
+ * It is stored as an extension of s4u::Host. Such extensions are retrieved by type as follows:
+ *
+ * @verbatim
+ * simgrid::s4u::Host* this_host = ???;
+ * this_extension = host->extension<HostLoad>();
+ * @endverbatim
+ *
+ * If no extension of that type was ever attached to the inspected object, the ``extension<X>()`` template returns
+ * nullptr.
+ *
+ * Please refer to the implementation of ``sg_host_load_plugin_init()`` to see the extension objects are attached to
+ * hosts at initialization time.
+ */
class HostLoad {
public:
static simgrid::xbt::Extension<simgrid::s4u::Host, HostLoad> EXTENSION_ID;
/** Return idle time over the whole simulation */
double get_total_idle_time() { update(); return total_idle_time_; }
void update();
- void add_activity(simgrid::kernel::activity::ExecImplPtr activity);
+ void add_activity(simgrid::kernel::activity::ExecImpl* activity);
void reset();
private:
simgrid::s4u::Host* host_ = nullptr;
/* Stores all currently ongoing activities (computations) on this machine */
- std::map<simgrid::kernel::activity::ExecImplPtr, /* cost still remaining*/double> current_activities;
+ std::map<simgrid::kernel::activity::ExecImpl*, /* cost still remaining*/ double> current_activities;
double last_updated_ = 0;
double last_reset_ = 0;
/**
double current_flops_ = 0;
double computed_flops_ = 0;
double idle_time_ = 0;
- double total_idle_time_ = 0; /* This gets never reset */
+ double total_idle_time_ = 0; /* This updated but never gets reset */
double theor_max_flops_ = 0;
};
+// Create the static field that the extension mechanism needs
simgrid::xbt::Extension<simgrid::s4u::Host, HostLoad> HostLoad::EXTENSION_ID;
-void HostLoad::add_activity(simgrid::kernel::activity::ExecImplPtr activity)
+void HostLoad::add_activity(simgrid::kernel::activity::ExecImpl* activity)
{
current_activities.insert({activity, activity_uninitialized_remaining_cost});
}
/* **************************** Public interface *************************** */
/** @brief Initializes the HostLoad plugin
- * @details The HostLoad plugin provides an API to get the current load of each host.
+ * @ingroup plugin_host_load
*/
void sg_host_load_plugin_init()
{
host.extension_set(new HostLoad(&host));
});
- simgrid::kernel::activity::ExecImpl::on_creation.connect([](simgrid::kernel::activity::ExecImpl& activity) {
+ simgrid::s4u::Exec::on_start.connect([](simgrid::s4u::Actor const&, simgrid::s4u::Exec const& activity) {
if (activity.get_host_number() == 1) { // We only run on one host
simgrid::s4u::Host* host = activity.get_host();
simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(host);
if (vm != nullptr)
host = vm->get_pm();
xbt_assert(host != nullptr);
- host->extension<HostLoad>()->add_activity(&activity);
+ host->extension<HostLoad>()->add_activity(static_cast<simgrid::kernel::activity::ExecImpl*>(activity.get_impl()));
host->extension<HostLoad>()->update(); // If the system was idle until now, we need to update *before*
// this computation starts running so we can keep track of the
// idle time. (Communication operations don't trigger this hook!)
XBT_WARN("HostLoad plugin currently does not support executions on several hosts");
}
});
- simgrid::kernel::activity::ExecImpl::on_completion.connect([](simgrid::kernel::activity::ExecImpl const& activity) {
+ simgrid::s4u::Exec::on_completion.connect([](simgrid::s4u::Actor const&, simgrid::s4u::Exec const& activity) {
if (activity.get_host_number() == 1) { // We only run on one host
simgrid::s4u::Host* host = activity.get_host();
simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(host);
}
/** @brief Returns the current load of that host, as a ratio = achieved_flops / (core_current_speed * core_amount)
- *
- * See simgrid::plugin::HostLoad::get_current_load() for the full documentation.
+ * @ingroup plugin_host_load
*/
double sg_host_get_current_load(sg_host_t host)
{
- xbt_assert(HostLoad::EXTENSION_ID.valid(),
- "The Load plugin is not active. Please call sg_host_load_plugin_init() during initialization.");
+ xbt_assert(HostLoad::EXTENSION_ID.valid(), "Please sg_host_load_plugin_init() to initialize this plugin.");
return host->extension<HostLoad>()->get_current_load();
}
-/** @brief Returns the current load of the host passed as argument
- *
- * See also @ref plugin_load
+/** @brief Returns the current load of that host
+ * @ingroup plugin_host_load
*/
double sg_host_get_avg_load(sg_host_t host)
{
- xbt_assert(HostLoad::EXTENSION_ID.valid(),
- "The Load plugin is not active. Please call sg_host_load_plugin_init() during initialization.");
+ xbt_assert(HostLoad::EXTENSION_ID.valid(), "Please sg_host_load_plugin_init() to initialize this plugin.");
return host->extension<HostLoad>()->get_average_load();
}
/** @brief Returns the time this host was idle since the last reset
- *
- * See also @ref plugin_load
+ * @ingroup plugin_host_load
*/
double sg_host_get_idle_time(sg_host_t host)
{
- xbt_assert(HostLoad::EXTENSION_ID.valid(),
- "The Load plugin is not active. Please call sg_host_load_plugin_init() during initialization.");
+ xbt_assert(HostLoad::EXTENSION_ID.valid(), "Please sg_host_load_plugin_init() to initialize this plugin.");
return host->extension<HostLoad>()->get_idle_time();
}
+/** @brief Returns the time this host was idle since the beginning of the simulation
+ * @ingroup plugin_host_load
+ */
double sg_host_get_total_idle_time(sg_host_t host)
{
- xbt_assert(HostLoad::EXTENSION_ID.valid(),
- "The Load plugin is not active. Please call sg_host_load_plugin_init() during initialization.");
+ xbt_assert(HostLoad::EXTENSION_ID.valid(), "Please sg_host_load_plugin_init() to initialize this plugin.");
return host->extension<HostLoad>()->get_total_idle_time();
}
+/** @brief Returns the amount of flops computed by that host since the last reset
+ * @ingroup plugin_host_load
+ */
double sg_host_get_computed_flops(sg_host_t host)
{
- xbt_assert(HostLoad::EXTENSION_ID.valid(),
- "The Load plugin is not active. Please call sg_host_load_plugin_init() during initialization.");
+ xbt_assert(HostLoad::EXTENSION_ID.valid(), "Please sg_host_load_plugin_init() to initialize this plugin.");
return host->extension<HostLoad>()->get_computed_flops();
}
+/** @brief Resets the idle time and flops amount of that host
+ * @ingroup plugin_host_load
+ */
void sg_host_load_reset(sg_host_t host)
{
- xbt_assert(HostLoad::EXTENSION_ID.valid(),
- "The Load plugin is not active. Please call sg_host_load_plugin_init() during initialization.");
+ xbt_assert(HostLoad::EXTENSION_ID.valid(), "Please sg_host_load_plugin_init() to initialize this plugin.");
host->extension<HostLoad>()->reset();
}
#include "src/plugins/vm/VirtualMachineImpl.hpp"
#include "simgrid/Exception.hpp"
+#include "simgrid/s4u/Exec.hpp"
#include "src/include/surf/surf.hpp"
#include "src/kernel/activity/ExecImpl.hpp"
}
}
-static s4u::VirtualMachine* get_vm_from_task(kernel::activity::ActivityImpl const& task)
+static void add_active_exec(s4u::Actor const&, s4u::Exec const& task)
{
- auto* exec = dynamic_cast<kernel::activity::ExecImpl const*>(&task);
+ s4u::VirtualMachine* vm = dynamic_cast<s4u::VirtualMachine*>(task.get_host());
+ if (vm != nullptr) {
+ VirtualMachineImpl* vm_impl = vm->get_impl();
+ vm_impl->active_tasks_ = vm_impl->active_tasks_ + 1;
+ vm_impl->update_action_weight();
+ }
+}
+
+static void remove_active_exec(s4u::Actor const&, s4u::Exec const& task)
+{
+ s4u::VirtualMachine* vm = dynamic_cast<s4u::VirtualMachine*>(task.get_host());
+ if (vm != nullptr) {
+ VirtualMachineImpl* vm_impl = vm->get_impl();
+ vm_impl->active_tasks_ = vm_impl->active_tasks_ - 1;
+ vm_impl->update_action_weight();
+ }
+}
+
+static s4u::VirtualMachine* get_vm_from_activity(kernel::activity::ActivityImpl const& act)
+{
+ auto* exec = dynamic_cast<kernel::activity::ExecImpl const*>(&act);
return exec != nullptr ? dynamic_cast<s4u::VirtualMachine*>(exec->get_host()) : nullptr;
}
-static void add_active_task(kernel::activity::ActivityImpl const& task)
+static void add_active_activity(kernel::activity::ActivityImpl const& act)
{
- s4u::VirtualMachine* vm = get_vm_from_task(task);
+ s4u::VirtualMachine* vm = get_vm_from_activity(act);
if (vm != nullptr) {
VirtualMachineImpl *vm_impl = vm->get_impl();
vm_impl->active_tasks_ = vm_impl->active_tasks_ + 1;
- vm_impl->update_action_weight();
+ vm_impl->update_action_weight();
}
}
-static void remove_active_task(kernel::activity::ActivityImpl const& task)
+static void remove_active_activity(kernel::activity::ActivityImpl const& act)
{
- s4u::VirtualMachine* vm = get_vm_from_task(task);
+ s4u::VirtualMachine* vm = get_vm_from_activity(act);
if (vm != nullptr) {
VirtualMachineImpl *vm_impl = vm->get_impl();
vm_impl->active_tasks_ = vm_impl->active_tasks_ - 1;
{
all_existing_models.push_back(this);
s4u::Host::on_state_change.connect(host_state_change);
- kernel::activity::ExecImpl::on_creation.connect(add_active_task);
- kernel::activity::ExecImpl::on_completion.connect(remove_active_task);
- kernel::activity::ActivityImpl::on_resumed.connect(add_active_task);
- kernel::activity::ActivityImpl::on_suspended.connect(remove_active_task);
+ s4u::Exec::on_start.connect(add_active_exec);
+ s4u::Exec::on_completion.connect(remove_active_exec);
+ kernel::activity::ActivityImpl::on_resumed.connect(add_active_activity);
+ kernel::activity::ActivityImpl::on_suspended.connect(remove_active_activity);
}
double VMModel::next_occuring_event(double now)
namespace simgrid {
namespace s4u {
-xbt::signal<void(Actor const&)> Exec::on_start;
-xbt::signal<void(Actor const&)> Exec::on_completion;
+xbt::signal<void(Actor const&, Exec const&)> Exec::on_start;
+xbt::signal<void(Actor const&, Exec const&)> Exec::on_completion;
Exec::Exec()
{
start();
simcall_execution_wait(pimpl_);
state_ = State::FINISHED;
- on_completion(*Actor::self());
+ on_completion(*Actor::self(), *this);
return this;
}
return this;
}
+Host* Exec::get_host() const
+{
+ return static_cast<kernel::activity::ExecImpl*>(pimpl_.get())->get_host();
+}
+unsigned int Exec::get_host_number() const
+{
+ return static_cast<kernel::activity::ExecImpl*>(pimpl_.get())->get_host_number();
+}
+double Exec::get_start_time() const
+{
+ return (pimpl_->surf_action_ == nullptr) ? -1 : pimpl_->surf_action_->get_start_time();
+}
+double Exec::get_finish_time() const
+{
+ return (pimpl_->surf_action_ == nullptr) ? -1 : pimpl_->surf_action_->get_finish_time();
+}
+double Exec::get_cost() const
+{
+ return (pimpl_->surf_action_ == nullptr) ? -1 : pimpl_->surf_action_->get_cost();
+}
+
/** @brief Change the execution priority, don't you think?
*
* An execution with twice the priority will get twice the amount of flops when the resource is shared.
.start();
});
state_ = State::STARTED;
- on_start(*Actor::self());
+ on_start(*Actor::self(), *this);
return this;
}
.start();
});
state_ = State::STARTED;
- on_start(*Actor::self());
+ on_start(*Actor::self(), *this);
return this;
}
return new_mapping.get_host(actor);
}
-void LoadBalancer::record_actor_computation(simgrid::s4u::ActorPtr actor, double load)
+void LoadBalancer::record_actor_computation(simgrid::s4u::Actor const& actor, double load)
{
- actor_computation[actor->get_pid()] += load;
+ actor_computation[actor.get_pid()] += load;
}
}
}
* FIXME These are functions used for testing and should be re-written or removed
*/
simgrid::s4u::Host* get_mapping(simgrid::s4u::ActorPtr);
- void record_actor_computation(simgrid::s4u::ActorPtr actor, double load);
+ void record_actor_computation(simgrid::s4u::Actor const& actor, double load);
};
}
static bool done = false;
if (!done) {
done = true;
- simgrid::kernel::activity::ExecImpl::on_completion.connect([](simgrid::kernel::activity::ExecImpl const& activity) {
- simgrid::smpi::plugin::lb.record_actor_computation(activity.simcalls_.front()->issuer_->iface(),
- activity.surf_action_->get_cost());
+ simgrid::s4u::Exec::on_completion.connect([](simgrid::s4u::Actor const& actor, simgrid::s4u::Exec const& exec) {
+
+ simgrid::smpi::plugin::lb.record_actor_computation(actor, exec.get_cost());
});
xbt_replay_action_register(