X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/138e6f86566611611b1115c957cae0a1c6a85a4b..a924fc6f7328160d99348f7d3de23fc50930ea03:/src/msg/msg_vm.cpp diff --git a/src/msg/msg_vm.cpp b/src/msg/msg_vm.cpp index 351a03c86d..5eb5d1beeb 100644 --- a/src/msg/msg_vm.cpp +++ b/src/msg/msg_vm.cpp @@ -9,81 +9,51 @@ * 2. use parallel tasks to simulate CPU overhead and remove the experimental code generating micro computation tasks */ +#include + +#include "src/plugins/vm/VirtualMachineImpl.hpp" +#include "src/plugins/vm/VmHostExt.hpp" +#include +#include + #include "msg_private.h" #include "xbt/sysdep.h" #include "xbt/log.h" #include "simgrid/host.h" +#include "src/simix/smx_host_private.h" /* don't ask me why the VM functions are in there (FIXME:KILLME) */ + XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_vm, msg, "Cloud-oriented parts of the MSG API"); /* **** ******** GENERAL ********* **** */ -/** \ingroup m_vm_management - * \brief Returns the value of a given vm property - * - * \param vm a vm - * \param name a property name - * \return value of a property (or nullptr if property not set) - */ -const char *MSG_vm_get_property_value(msg_vm_t vm, const char *name) -{ - return MSG_host_get_property_value(vm, name); -} /** \ingroup m_vm_management - * \brief Returns a xbt_dict_t consisting of the list of properties assigned to this host - * - * \param vm a vm - * \return a dict containing the properties - */ -xbt_dict_t MSG_vm_get_properties(msg_vm_t vm) -{ - xbt_assert((vm != nullptr), "Invalid parameters (vm is nullptr)"); - return vm->properties(); -} - -/** \ingroup m_host_management - * \brief Change the value of a given host property + * \brief Set the parameters of a given host * * \param vm a vm - * \param name a property name - * \param value what to change the property to - * \param free_ctn the freeing function to use to kill the value on need + * \param params a parameter object */ -void MSG_vm_set_property_value(msg_vm_t vm, const char *name, void *value, void_f_pvoid_t free_ctn) +void MSG_vm_set_params(msg_vm_t vm, vm_params_t params) { - xbt_dict_set(MSG_host_get_properties(vm), name, value, free_ctn); -} - -/** \ingroup msg_vm_management - * \brief Finds a msg_vm_t using its name. - * - * This is a name directory service - * \param name the name of a vm. - * \return the corresponding vm - * - * Please note that a VM is a specific host. Hence, you should give a different name for each VM/PM. - */ -msg_vm_t MSG_vm_get_by_name(const char *name) -{ - return MSG_host_by_name(name); + static_cast(vm)->setParameters(params); } /** \ingroup m_vm_management + * \brief Get the parameters of a given host * - * \brief Return the name of the #msg_host_t. - * - * This functions checks whether \a host is a valid pointer or not and return its name. + * \param host a host + * \param params a prameter object */ -const char *MSG_vm_get_name(msg_vm_t vm) +void MSG_vm_get_params(msg_vm_t vm, vm_params_t params) { - return MSG_host_get_name(vm); + static_cast(vm)->parameters(params); } /* **** Check state of a VM **** */ static inline int __MSG_vm_is_state(msg_vm_t vm, e_surf_vm_state_t state) { - return simcall_vm_get_state(vm) == state; + return static_cast(vm)->pimpl_vm_->getState() == state; } /** @brief Returns whether the given VM has just created, not running. @@ -107,8 +77,7 @@ int MSG_vm_is_running(msg_vm_t vm) */ int MSG_vm_is_migrating(msg_vm_t vm) { - msg_host_priv_t priv = sg_host_msg(vm); - return priv->is_migrating; + return static_cast(vm)->isMigrating(); } /** @brief Returns whether the given VM is currently suspended, not running. @@ -159,8 +128,9 @@ int MSG_vm_is_restoring(msg_vm_t vm) msg_vm_t MSG_vm_create(msg_host_t pm, const char *name, int ncpus, int ramsize, int net_cap, char *disk_path, int disksize, int mig_netspeed, int dp_intensity) { - /* For the moment, intensity_rate is the percentage against the migration - * bandwidth */ + simgrid::vm::VmHostExt::ensureVmExtInstalled(); + + /* For the moment, intensity_rate is the percentage against the migration bandwidth */ double host_speed = MSG_host_get_speed(pm); double update_speed = ((double)dp_intensity/100) * mig_netspeed; @@ -178,7 +148,7 @@ msg_vm_t MSG_vm_create(msg_host_t pm, const char *name, int ncpus, int ramsize, //XBT_INFO("dp rate %f migspeed : %f intensity mem : %d, updatespeed %f, hostspeed %f",params.dp_rate, // params.mig_speed, dp_intensity, update_speed, host_speed); - vm->setParameters(¶ms); + static_cast(vm)->setParameters(¶ms); return vm; } @@ -188,28 +158,12 @@ msg_vm_t MSG_vm_create(msg_host_t pm, const char *name, int ncpus, int ramsize, * * A VM is treated as a host. The name of the VM must be unique among all hosts. */ -msg_vm_t MSG_vm_create_core(msg_host_t ind_pm, const char *name) +msg_vm_t MSG_vm_create_core(msg_host_t pm, const char* name) { - /* make sure the VM of the same name does not exit */ - { - simgrid::s4u::Host* ind_host_tmp = (simgrid::s4u::Host*) xbt_dict_get_or_null(host_list, name); - if (ind_host_tmp != nullptr && sg_host_simix(ind_host_tmp) != nullptr) { - XBT_ERROR("host %s already exits", name); - return nullptr; - } - } + xbt_assert(sg_host_by_name(name) == nullptr, + "Cannot create a VM named %s: this name is already used by an host or a VM", name); - /* Note: ind_vm and vm_workstation point to the same elm object. */ - /* Ask the SIMIX layer to create the surf vm resource */ - sg_host_t ind_vm_workstation = (sg_host_t) simcall_vm_create(name, ind_pm); - - msg_vm_t ind_vm = (msg_vm_t) __MSG_host_create(ind_vm_workstation); - - XBT_DEBUG("A new VM (%s) has been created", name); - - TRACE_msg_vm_create(name, ind_pm); - - return ind_vm; + return new simgrid::s4u::VirtualMachine(name, pm); } /** @brief Destroy a VM. Destroy the VM object from the simulation. @@ -218,19 +172,18 @@ msg_vm_t MSG_vm_create_core(msg_host_t ind_pm, const char *name) void MSG_vm_destroy(msg_vm_t vm) { if (MSG_vm_is_migrating(vm)) - THROWF(vm_error, 0, "VM(%s) is migrating", sg_host_get_name(vm)); + THROWF(vm_error, 0, "VM(%s) is migrating", vm->name().c_str()); /* First, terminate all processes on the VM if necessary */ if (MSG_vm_is_running(vm)) - simcall_vm_shutdown(vm); + MSG_vm_shutdown(vm); - if (!MSG_vm_is_created(vm)) { - XBT_CRITICAL("shutdown the given VM before destroying it"); - DIE_IMPOSSIBLE; - } + xbt_assert(MSG_vm_is_created(vm), "shutdown the given VM before destroying it"); /* Then, destroy the VM object */ - simcall_vm_destroy(vm); + simgrid::simix::kernelImmediate([vm]() { + vm->destroy(); + }); TRACE_msg_vm_end(vm); } @@ -257,7 +210,8 @@ void MSG_vm_shutdown(msg_vm_t vm) { /* msg_vm_t equals to msg_host_t */ simcall_vm_shutdown(vm); - + MSG_process_sleep(0.); // Make sure that the processes in the VM are killed in this scheduling round before processing + // (eg with the VM destroy) // TRACE_msg_vm_(vm); } @@ -328,7 +282,7 @@ static int migration_rx_fun(int argc, char *argv[]) struct migration_session *ms = (migration_session *) MSG_process_get_data(MSG_process_self()); s_vm_params_t params; - ms->vm->parameters(¶ms); + static_cast(ms->vm)->parameters(¶ms); int need_exit = 0; @@ -362,37 +316,26 @@ static int migration_rx_fun(int argc, char *argv[]) // Copy the reference to the vm (if SRC crashes now, do_migration will free ms) // This is clearly ugly but I (Adrien) need more time to do something cleaner (actually we should copy the whole ms // structure at the beginning and free it at the end of each function) - msg_vm_t vm = ms->vm; - msg_host_t src_pm = ms->src_pm; - msg_host_t dst_pm = ms-> dst_pm; - msg_host_priv_t priv = sg_host_msg(vm); - -// TODO: we have an issue, if the DST node is turning off during the three next calls, then the VM is in an inconsistent -// state. I should check with Takahiro in order to make this portion of code atomic -// /* deinstall the current affinity setting for the CPU */ -// simcall_vm_set_affinity(vm, src_pm, 0); -// -// /* Update the vm location */ -// simcall_vm_migrate(vm, dst_pm); -// -// /* Resume the VM */ -// simcall_vm_resume(vm); -// - simcall_vm_migratefrom_resumeto(vm, src_pm, dst_pm); - - /* install the affinity setting of the VM on the destination pm */ - { + simgrid::s4u::VirtualMachine* vm = static_cast(ms->vm); + msg_host_t src_pm = ms->src_pm; + msg_host_t dst_pm = ms->dst_pm; - unsigned long affinity_mask = - (unsigned long)(uintptr_t) xbt_dict_get_or_null_ext(priv->affinity_mask_db, (char *)dst_pm, sizeof(msg_host_t)); - simcall_vm_set_affinity(vm, dst_pm, affinity_mask); - XBT_DEBUG("set affinity(0x%04lx@%s) for %s", affinity_mask, MSG_host_get_name(dst_pm), MSG_host_get_name(vm)); - } + // Make sure that we cannot get interrupted between the migrate and the resume to not end in an inconsistent state + simgrid::simix::kernelImmediate([vm, src_pm, dst_pm]() { + /* Update the vm location */ + /* precopy migration makes the VM temporally paused */ + xbt_assert(static_cast(vm)->pimpl_vm_->getState() == SURF_VM_STATE_SUSPENDED); + + /* jump to vm_ws_xigrate(). this will update the vm location. */ + static_cast(vm)->pimpl_vm_->migrate(dst_pm); + + /* Resume the VM */ + SIMIX_vm_resume(vm); + }); { // Now the VM is running on the new host (the migration is completed) (even if the SRC crash) - msg_host_priv_t priv = sg_host_msg(vm); - priv->is_migrating = 0; + vm->pimpl_vm_->isMigrating = false; XBT_DEBUG("VM(%s) moved from PM(%s) to PM(%s)", sg_host_get_name(ms->vm), sg_host_get_name(ms->src_pm), sg_host_get_name(ms->dst_pm)); TRACE_msg_vm_change_host(ms->vm, ms->src_pm, ms->dst_pm); @@ -423,12 +366,14 @@ static int migration_rx_fun(int argc, char *argv[]) static void reset_dirty_pages(msg_vm_t vm) { - msg_host_priv_t priv = sg_host_msg(vm); + simgrid::surf::VirtualMachineImpl* pimpl = static_cast(vm->pimpl_); char *key = nullptr; xbt_dict_cursor_t cursor = nullptr; dirty_page_t dp = nullptr; - xbt_dict_foreach(priv->dp_objs, cursor, key, dp) { + if (!pimpl->dp_objs) + return; + xbt_dict_foreach (pimpl->dp_objs, cursor, key, dp) { double remaining = MSG_task_get_flops_amount(dp->task); dp->prev_clock = MSG_get_clock(); dp->prev_remaining = remaining; @@ -439,16 +384,14 @@ static void reset_dirty_pages(msg_vm_t vm) static void start_dirty_page_tracking(msg_vm_t vm) { - msg_host_priv_t priv = sg_host_msg(vm); - priv->dp_enabled = 1; + static_cast(vm)->pimpl_vm_->dp_enabled = 1; reset_dirty_pages(vm); } static void stop_dirty_page_tracking(msg_vm_t vm) { - msg_host_priv_t priv = sg_host_msg(vm); - priv->dp_enabled = 0; + static_cast(vm)->pimpl_vm_->dp_enabled = 0; } static double get_computed(char *key, msg_vm_t vm, dirty_page_t dp, double remaining, double clock) @@ -464,13 +407,13 @@ static double get_computed(char *key, msg_vm_t vm, dirty_page_t dp, double remai static double lookup_computed_flop_counts(msg_vm_t vm, int stage_for_fancy_debug, int stage2_round_for_fancy_debug) { - msg_host_priv_t priv = sg_host_msg(vm); + simgrid::surf::VirtualMachineImpl* pimpl = static_cast(vm)->pimpl_vm_; double total = 0; char *key = nullptr; xbt_dict_cursor_t cursor = nullptr; dirty_page_t dp = nullptr; - xbt_dict_foreach(priv->dp_objs, cursor, key, dp) { + xbt_dict_foreach (pimpl->dp_objs, cursor, key, dp) { double remaining = MSG_task_get_flops_amount(dp->task); double clock = MSG_get_clock(); @@ -482,65 +425,70 @@ static double lookup_computed_flop_counts(msg_vm_t vm, int stage_for_fancy_debug dp->prev_clock = clock; } - total += priv->dp_updated_by_deleted_tasks; + total += pimpl->dp_updated_by_deleted_tasks; - XBT_DEBUG("mig-stage%d.%d: computed %f flop_counts (including %f by deleted tasks)", - stage_for_fancy_debug, stage2_round_for_fancy_debug, total, priv->dp_updated_by_deleted_tasks); + XBT_DEBUG("mig-stage%d.%d: computed %f flop_counts (including %f by deleted tasks)", stage_for_fancy_debug, + stage2_round_for_fancy_debug, total, pimpl->dp_updated_by_deleted_tasks); - priv->dp_updated_by_deleted_tasks = 0; + pimpl->dp_updated_by_deleted_tasks = 0; return total; } // TODO Is this code redundant with the information provided by // msg_process_t MSG_process_create(const char *name, xbt_main_func_t code, void *data, msg_host_t host) +/** @brief take care of the dirty page tracking, in case we're adding a task to a migrating VM */ void MSG_host_add_task(msg_host_t host, msg_task_t task) { - msg_host_priv_t priv = sg_host_msg(host); + simgrid::s4u::VirtualMachine* vm = dynamic_cast(host); + if (vm == nullptr) + return; + simgrid::surf::VirtualMachineImpl* pimpl = static_cast(vm->pimpl_); + double remaining = MSG_task_get_flops_amount(task); char *key = bprintf("%s-%p", task->name, task); dirty_page_t dp = xbt_new0(s_dirty_page, 1); dp->task = task; - - /* It should be okay that we add a task onto a migrating VM. */ - if (priv->dp_enabled) { + if (pimpl->dp_enabled) { dp->prev_clock = MSG_get_clock(); dp->prev_remaining = remaining; } - - xbt_assert(xbt_dict_get_or_null(priv->dp_objs, key) == nullptr); - xbt_dict_set(priv->dp_objs, key, dp, nullptr); - XBT_DEBUG("add %s on %s (remaining %f, dp_enabled %d)", key, sg_host_get_name(host), remaining, priv->dp_enabled); + if (!pimpl->dp_objs) + pimpl->dp_objs = xbt_dict_new(); + xbt_assert(xbt_dict_get_or_null(pimpl->dp_objs, key) == nullptr); + xbt_dict_set(pimpl->dp_objs, key, dp, nullptr); + XBT_DEBUG("add %s on %s (remaining %f, dp_enabled %d)", key, sg_host_get_name(host), remaining, pimpl->dp_enabled); xbt_free(key); } void MSG_host_del_task(msg_host_t host, msg_task_t task) { - msg_host_priv_t priv = sg_host_msg(host); + simgrid::s4u::VirtualMachine* vm = dynamic_cast(host); + if (vm == nullptr) + return; + simgrid::surf::VirtualMachineImpl* pimpl = static_cast(vm->pimpl_); char *key = bprintf("%s-%p", task->name, task); - - dirty_page_t dp = (dirty_page_t) xbt_dict_get_or_null(priv->dp_objs, key); + dirty_page_t dp = (dirty_page_t)(pimpl->dp_objs ? xbt_dict_get_or_null(pimpl->dp_objs, key) : NULL); xbt_assert(dp->task == task); /* 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 (priv->dp_enabled) { + if (pimpl->dp_enabled) { double remaining = MSG_task_get_flops_amount(task); double clock = MSG_get_clock(); // double updated = calc_updated_pages(key, host, dp, remaining, clock); double updated = get_computed(key, host, dp, remaining, clock); - priv->dp_updated_by_deleted_tasks += updated; + pimpl->dp_updated_by_deleted_tasks += updated; } - - xbt_dict_remove(priv->dp_objs, key); + if (pimpl->dp_objs) + xbt_dict_remove(pimpl->dp_objs, key); xbt_free(dp); XBT_DEBUG("del %s on %s", key, sg_host_get_name(host)); - xbt_free(key); } @@ -644,7 +592,7 @@ static int migration_tx_fun(int argc, char *argv[]) migration_session *ms = (migration_session *) MSG_process_get_data(MSG_process_self()); s_vm_params_t params; - ms->vm->parameters(¶ms); + static_cast(ms->vm)->parameters(¶ms); const sg_size_t ramsize = params.ramsize; const sg_size_t devsize = params.devsize; const int skip_stage1 = params.skip_stage1; @@ -665,7 +613,7 @@ static int migration_tx_fun(int argc, char *argv[]) if (ramsize == 0) XBT_WARN("migrate a VM, but ramsize is zero"); - if (max_downtime == 0) { + if (max_downtime <= 0) { XBT_WARN("use the default max_downtime value 30ms"); max_downtime = 0.03; } @@ -907,18 +855,18 @@ void MSG_vm_migrate(msg_vm_t vm, msg_host_t new_pm) if (MSG_vm_is_migrating(vm)) THROWF(vm_error, 0, "VM(%s) is already migrating", sg_host_get_name(vm)); - msg_host_priv_t priv = sg_host_msg(vm); - priv->is_migrating = 1; + simgrid::surf::VirtualMachineImpl* pimpl = static_cast(vm->pimpl_); + pimpl->isMigrating = 1; { int ret = do_migration(vm, old_pm, new_pm); if (ret == -1){ - priv->is_migrating = 0; - THROWF(host_error, 0, "SRC host failed during migration"); + pimpl->isMigrating = 0; + THROWF(host_error, 0, "SRC host failed during migration"); } else if(ret == -2){ - priv->is_migrating = 0; - THROWF(host_error, 0, "DST host failed during migration"); + pimpl->isMigrating = 0; + THROWF(host_error, 0, "DST host failed during migration"); } } @@ -1030,26 +978,3 @@ void MSG_vm_set_bound(msg_vm_t vm, double bound) { simcall_vm_set_bound(vm, bound); } - -/** @brief Set the CPU affinity of a given VM. - * @ingroup msg_VMs - * - * This function changes the CPU affinity of a given VM. Usage is the same as - * MSG_task_set_affinity(). See the MSG_task_set_affinity() for details. - */ -void MSG_vm_set_affinity(msg_vm_t vm, msg_host_t pm, unsigned long mask) -{ - msg_host_priv_t priv = sg_host_msg(vm); - - if (mask == 0) - xbt_dict_remove_ext(priv->affinity_mask_db, (char *) pm, sizeof(pm)); - else - xbt_dict_set_ext(priv->affinity_mask_db, (char *) pm, sizeof(pm), (void *)(uintptr_t) mask, nullptr); - - msg_host_t pm_now = MSG_vm_get_pm(vm); - if (pm_now == pm) { - XBT_DEBUG("set affinity(0x%04lx@%s) for %s", mask, MSG_host_get_name(pm), MSG_host_get_name(vm)); - simcall_vm_set_affinity(vm, pm, mask); - } else - XBT_DEBUG("set affinity(0x%04lx@%s) for %s (not active now)", mask, MSG_host_get_name(pm), MSG_host_get_name(vm)); -}