XBT_PUBLIC(int) simcall_vm_get_state(smx_host_t vm);
XBT_PUBLIC(void) simcall_vm_start(smx_host_t vm);
XBT_PUBLIC(void) simcall_vm_migrate(smx_host_t vm, smx_host_t dst_pm);
-XBT_PUBLIC(const char*) simcall_vm_get_phys_host(smx_host_t vm);
+XBT_PUBLIC(void *) simcall_vm_get_pm(smx_host_t vm);
XBT_PUBLIC(void) simcall_vm_resume(smx_host_t vm);
XBT_PUBLIC(void) simcall_vm_save(smx_host_t vm);
XBT_PUBLIC(void) simcall_vm_restore(smx_host_t vm);
* */
s_surf_model_extension_workstation_t basic;
- void (*create) (const char *name, void *ind_phys_workstation); // First operation of the VM model
// start does not appear here as it corresponds to turn the state from created to running (see smx_vm.c)
- int (*get_state) (void *ind_vm_workstation);
- void (*set_state) (void *ind_vms_workstation, int state);
- void (*migrate) (void *ind_vm_workstation, void *ind_dest_phys_workstation); // will be vm_ws_migrate()
- const char * (*get_phys_host) (void *ind_vm_workstation); // will be vm_ws_get_phys_host()
- void (*destroy) (void *ind_vm_workstation); // will be vm_ws_destroy(), which destroies the vm-workstation-specific data
+
+ void (*create) (const char *name, void *ind_phys_workstation); // First operation of the VM model
+ void (*destroy) (void *ind_vm_ws); // will be vm_ws_destroy(), which destroies the vm-workstation-specific data
+
+ void (*suspend) (void *ind_vm_ws);
+ void (*resume) (void *ind_vm_ws);
+
+ void (*save) (void *ind_vm_ws);
+ void (*restore) (void *ind_vm_ws);
+
+ void (*migrate) (void *ind_vm_ws, void *ind_vm_ws_dest); // will be vm_ws_migrate()
+ void * (*get_pm) (void *ind_vm_ws); // will be vm_ws_get_pmt()
+
+ int (*get_state) (void *ind_vm_ws);
+ void (*set_state) (void *ind_vm_ws, int state);
+
} s_surf_model_extension_vm_workstation_t;
/** \ingroup SURF_models
* MSG_task_send() before or after, depending on whether you want to do cold or hot
* migration.
*/
-void MSG_vm_migrate(msg_vm_t vm, msg_host_t destination)
+void MSG_vm_migrate(msg_vm_t vm, msg_host_t new_pm)
{
/* some thoughts:
* - One approach is ...
*
*/
- #ifdef HAVE_TRACING
- const char *old_pm_name = simcall_vm_get_phys_host(vm);
- msg_host_t old_pm_ind = xbt_lib_get_elm_or_null(host_lib, old_pm_name);
- #endif
+ msg_host_t old_pm = simcall_vm_get_pm(vm);
- simcall_vm_migrate(vm, destination);
+ simcall_vm_migrate(vm, new_pm);
+ XBT_DEBUG("VM(%s) moved from PM(%s) to PM(%s)", vm->key, old_pm->key, new_pm->key);
#ifdef HAVE_TRACING
- TRACE_msg_vm_change_host(vm, old_pm_ind, destination);
+ TRACE_msg_vm_change_host(vm, old_pm, new_pm);
#endif
}
{
simcall_vm_suspend(vm);
+ XBT_DEBUG("vm_suspend done");
+
#ifdef HAVE_TRACING
TRACE_msg_vm_suspend(vm);
#endif
smx_host_t SIMIX_vm_create(const char *name, smx_host_t ind_phys_host);
smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host);
-void SIMIX_vm_start(smx_host_t ind_vm);
-void SIMIX_pre_vm_start(smx_simcall_t simcall, smx_host_t ind_vm);
-
-void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm);
-void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm);
-
-const char *SIMIX_vm_get_phys_host(smx_host_t ind_vm);
-const char *SIMIX_pre_vm_get_phys_host(smx_simcall_t simcall, smx_host_t ind_vm);
-
-void SIMIX_vm_set_state(smx_host_t ind_vm, int state);
-void SIMIX_pre_vm_set_state(smx_simcall_t simcall, smx_host_t ind_vm, int state);
-
-int SIMIX_vm_get_state(smx_host_t ind_vm);
-int SIMIX_pre_vm_get_state(smx_simcall_t simcall, smx_host_t ind_vm);
-
-void SIMIX_vm_resume(smx_host_t ind_vm);
+void SIMIX_vm_destroy(smx_host_t ind_vm);
+void SIMIX_pre_vm_destroy(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_resume(smx_host_t ind_vm, smx_process_t issuer);
void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm);
-void SIMIX_vm_suspend(smx_host_t ind_vm);
+void SIMIX_vm_suspend(smx_host_t ind_vm, smx_process_t issuer);
void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm);
-
-void SIMIX_vm_save(smx_host_t ind_vm);
+// --
+void SIMIX_vm_save(smx_host_t ind_vm, smx_process_t issuer);
void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm);
-void SIMIX_vm_restore(smx_host_t ind_vm);
+void SIMIX_vm_restore(smx_host_t ind_vm, smx_process_t issuer);
void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_start(smx_host_t ind_vm);
+void SIMIX_pre_vm_start(smx_simcall_t simcall, smx_host_t ind_vm);
void SIMIX_vm_shutdown(smx_host_t ind_vm, smx_process_t issuer);
void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_set_state(smx_host_t ind_vm, int state);
+void SIMIX_pre_vm_set_state(smx_simcall_t simcall, smx_host_t ind_vm, int state);
-void SIMIX_vm_destroy(smx_host_t ind_vm);
-void SIMIX_pre_vm_destroy(smx_simcall_t simcall, smx_host_t ind_vm);
+int SIMIX_vm_get_state(smx_host_t ind_vm);
+int SIMIX_pre_vm_get_state(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm);
+void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm);
+void *SIMIX_vm_get_pm(smx_host_t ind_vm);
+void *SIMIX_pre_vm_get_pm(smx_simcall_t simcall, smx_host_t ind_vm);
#endif
ACTION(SIMCALL_HOST_EXECUTION_GET_STATE, host_execution_get_state, WITH_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
ACTION(SIMCALL_HOST_EXECUTION_SET_PRIORITY, host_execution_set_priority, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t), TDOUBLE(priority)) sep \
ACTION(SIMCALL_HOST_EXECUTION_WAIT, host_execution_wait, WITHOUT_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
-ACTION(SIMCALL_VM_CREATE, vm_create, WITH_ANSWER, TPTR(result), TSTRING(name), TSPEC(phys_host, smx_host_t)) sep \
-ACTION(SIMCALL_VM_START, vm_start, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_phys_host, smx_host_t)) sep \
+ACTION(SIMCALL_VM_CREATE, vm_create, WITH_ANSWER, TPTR(result), TSTRING(name), TSPEC(ind_pm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_START, vm_start, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
ACTION(SIMCALL_VM_SET_STATE, vm_set_state, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TINT(state)) sep \
-ACTION(SIMCALL_VM_GET_STATE, vm_get_state, WITH_ANSWER, TINT(result), TSPEC(ind_vm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_MIGRATE, vm_migrate, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TSPEC(ind_dst_pm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_GET_PHYS_HOST, vm_get_phys_host, WITH_ANSWER, TSTRING(result), TSPEC(ind_vm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_DESTROY, vm_destroy, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_SUSPEND, vm_suspend, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_RESUME, vm_resume, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_SHUTDOWN, vm_shutdown, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_SAVE, vm_save, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_RESTORE, vm_restore, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_GET_STATE, vm_get_state, WITH_ANSWER, TINT(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_MIGRATE, vm_migrate, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TSPEC(ind_dst_pm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_GET_PM, vm_get_pm, WITH_ANSWER, TPTR(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_DESTROY, vm_destroy, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SUSPEND, vm_suspend, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_RESUME, vm_resume, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SHUTDOWN, vm_shutdown, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SAVE, vm_save, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_RESTORE, vm_restore, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
ACTION(SIMCALL_PROCESS_CREATE, process_create, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t*), TSTRING(name), TSPEC(code, xbt_main_func_t), TPTR(data), TSTRING(hostname), TDOUBLE(kill_time), TINT(argc), TSPEC(argv, char**), TSPEC(properties, xbt_dict_t), TINT(auto_restart)) sep \
ACTION(SIMCALL_PROCESS_KILL, process_kill, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
ACTION(SIMCALL_PROCESS_KILLALL, process_killall, WITH_ANSWER, TVOID(result), TINT(reset_pid)) sep \
* \param vm VM
* \return The name of the physical host
*/
-const char *simcall_vm_get_phys_host(smx_host_t vm)
+void *simcall_vm_get_pm(smx_host_t vm)
{
/* will jump to SIMIX_pre_vm_migrate in src/simix/smx_smurf_private.h */
- return simcall_BODY_vm_get_phys_host(vm);
+ return simcall_BODY_vm_get_pm(vm);
}
/**
}
-smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host){
+smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host)
+{
return SIMIX_vm_create(name, ind_phys_host);
}
{
// TODO add checking code related to overcommitment or not.
+#if 0
int overcommit = get_host_property_as_integer(vm, "OverCommit");
int core_nb = get_host_property_as_integer(vm, "CORE_NB");
int mem_cap = get_host_property_as_integer(vm, "MEM_CAP");
int net_cap = get_host_property_as_integer(vm, "NET_CAP");
+#endif
/* we need to get other VM objects on this physical host. */
*/
void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm)
{
- /* TODO: check state */
+ const char *name = SIMIX_host_get_name(ind_vm);
- /* TODO: Using the variable of the MSG layer is not clean. */
- SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_MIGRATING);
+ if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+ THROWF(vm_error, 0, "VM(%s) is not running", name);
/* jump to vm_ws_migrate(). this will update the vm location. */
surf_vm_workstation_model->extension.vm_workstation.migrate(ind_vm, ind_dst_pm);
-
- SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_RUNNING);
}
-void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm){
- SIMIX_vm_migrate(ind_vm, ind_dst_pm);
+void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm)
+{
+ SIMIX_vm_migrate(ind_vm, ind_dst_pm);
}
*
* \param host the vm host to get_phys_host (a smx_host_t)
*/
-const char *SIMIX_vm_get_phys_host(smx_host_t ind_vm)
+void *SIMIX_vm_get_pm(smx_host_t ind_vm)
{
- /* jump to vm_ws_get_phys_host(). this will return the vm name. */
- return surf_vm_workstation_model->extension.vm_workstation.get_phys_host(ind_vm);
+ /* jump to vm_ws_get_pm(). this will return the vm name. */
+ return surf_vm_workstation_model->extension.vm_workstation.get_pm(ind_vm);
}
-const char *SIMIX_pre_vm_get_phys_host(smx_simcall_t simcall, smx_host_t ind_vm){
- return SIMIX_vm_get_phys_host(ind_vm);
+void *SIMIX_pre_vm_get_pm(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+ return SIMIX_vm_get_pm(ind_vm);
}
*
* \param host the vm host to suspend (a smx_host_t)
*/
-void SIMIX_vm_suspend(smx_host_t ind_vm)
+void SIMIX_vm_suspend(smx_host_t ind_vm, smx_process_t issuer)
{
- /* TODO: check state */
+ const char *name = SIMIX_host_get_name(ind_vm);
- XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+ if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+ THROWF(vm_error, 0, "VM(%s) is not running", name);
+
+ XBT_DEBUG("suspend VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+ /* jump to vm_ws_suspend. The state will be set. */
+ surf_vm_workstation_model->extension.vm_workstation.suspend(ind_vm);
smx_process_t smx_process, smx_process_safe;
xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
- XBT_DEBUG("suspend %s", SIMIX_host_get_name(ind_vm));
- /* FIXME: calling a simcall from the SIMIX layer is strange. */
- simcall_process_suspend(smx_process);
+ XBT_DEBUG("suspend %s", smx_process->name);
+ SIMIX_process_suspend(smx_process, issuer);
}
- /* TODO: Using the variable of the MSG layer is not clean. */
- SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_SUSPENDED);
+ XBT_DEBUG("suspend all processes on the VM done done");
}
-void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm){
- SIMIX_vm_suspend(ind_vm);
+void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+ if (simcall->issuer->smx_host == ind_vm) {
+ XBT_ERROR("cannot suspend the VM where I run");
+ DIE_IMPOSSIBLE;
+ }
+
+ SIMIX_vm_suspend(ind_vm, simcall->issuer);
+
+ /* without this, simcall_vm_suspend() does not return to the userland. why? */
+ SIMIX_simcall_answer(simcall);
+
+ XBT_DEBUG("SIMIX_pre_vm_suspend done");
}
*
* \param host the vm host to resume (a smx_host_t)
*/
-void SIMIX_vm_resume(smx_host_t ind_vm)
+void SIMIX_vm_resume(smx_host_t ind_vm, smx_process_t issuer)
{
- /* TODO: check state */
+ const char *name = SIMIX_host_get_name(ind_vm);
- XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+ if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_SUSPENDED)
+ THROWF(vm_error, 0, "VM(%s) was not suspended", name);
+
+ XBT_DEBUG("resume VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+ /* jump to vm_ws_resume() */
+ surf_vm_workstation_model->extension.vm_workstation.resume(ind_vm);
smx_process_t smx_process, smx_process_safe;
xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
- XBT_DEBUG("resume %s", SIMIX_host_get_name(ind_vm));
- /* FIXME: calling a simcall from the SIMIX layer is strange. */
- simcall_process_resume(smx_process);
+ XBT_DEBUG("resume %s", smx_process->name);
+ SIMIX_process_resume(smx_process, issuer);
}
-
- /* TODO: Using the variable of the MSG layer is not clean. */
- SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_RUNNING);
}
-void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm){
- SIMIX_vm_resume(ind_vm);
+void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+ SIMIX_vm_resume(ind_vm, simcall->issuer);
+ SIMIX_simcall_answer(simcall);
}
*
* \param host the vm host to save (a smx_host_t)
*/
-void SIMIX_vm_save(smx_host_t ind_vm)
+void SIMIX_vm_save(smx_host_t ind_vm, smx_process_t issuer)
{
- /* TODO: check state */
+ const char *name = SIMIX_host_get_name(ind_vm);
+
+ if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+ THROWF(vm_error, 0, "VM(%s) is not running", name);
- XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
- /* TODO: do something at the surf level */
+ XBT_DEBUG("save VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+ /* jump to vm_ws_save() */
+ surf_vm_workstation_model->extension.vm_workstation.save(ind_vm);
smx_process_t smx_process, smx_process_safe;
xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
- XBT_DEBUG("save %s", SIMIX_host_get_name(ind_vm));
- /* FIXME: calling a simcall from the SIMIX layer is strange. */
- simcall_process_suspend(smx_process);
+ XBT_DEBUG("suspend %s", smx_process->name);
+ SIMIX_process_suspend(smx_process, issuer);
}
-
- /* TODO: Using the variable of the MSG layer is not clean. */
- SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_SAVED);
}
-void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm){
- SIMIX_vm_save(ind_vm);
+void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+ SIMIX_vm_save(ind_vm, simcall->issuer);
+
+ /* without this, simcall_vm_suspend() does not return to the userland. why? */
+ SIMIX_simcall_answer(simcall);
}
*
* \param host the vm host to restore (a smx_host_t)
*/
-void SIMIX_vm_restore(smx_host_t ind_vm)
+void SIMIX_vm_restore(smx_host_t ind_vm, smx_process_t issuer)
{
- /* TODO: check state */
+ const char *name = SIMIX_host_get_name(ind_vm);
- XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+ if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_SAVED)
+ THROWF(vm_error, 0, "VM(%s) was not saved", name);
+
+ XBT_DEBUG("restore VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
- /* TODO: do something at the surf level */
+ /* jump to vm_ws_restore() */
+ surf_vm_workstation_model->extension.vm_workstation.resume(ind_vm);
smx_process_t smx_process, smx_process_safe;
xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
- XBT_DEBUG("restore %s", SIMIX_host_get_name(ind_vm));
- /* FIXME: calling a simcall from the SIMIX layer is strange. */
- simcall_process_resume(smx_process);
+ XBT_DEBUG("resume %s", smx_process->name);
+ SIMIX_process_resume(smx_process, issuer);
}
-
- /* TODO: Using the variable of the MSG layer is not clean. */
- SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_RUNNING);
}
-void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm){
- SIMIX_vm_restore(ind_vm);
+void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+ SIMIX_vm_restore(ind_vm, simcall->issuer);
+ SIMIX_simcall_answer(simcall);
}
*/
void SIMIX_vm_shutdown(smx_host_t ind_vm, smx_process_t issuer)
{
- /* TODO: check state */
+ const char *name = SIMIX_host_get_name(ind_vm);
+
+ if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+ THROWF(vm_error, 0, "VM(%s) is not running", name);
XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
smx_process_t smx_process, smx_process_safe;
xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
- XBT_DEBUG("kill %s", SIMIX_host_get_name(ind_vm));
-
- SIMIX_process_kill(smx_process, issuer);
+ XBT_DEBUG("shutdown %s", name);
+ SIMIX_process_kill(smx_process, issuer);
}
- /* TODO: Using the variable of the MSG layer is not clean. */
+ /* FIXME: we may have to do something at the surf layer, e.g., vcpu action */
SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_CREATED);
}
-void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm){
- SIMIX_vm_shutdown(ind_vm, simcall->issuer);
+void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+ SIMIX_vm_shutdown(ind_vm, simcall->issuer);
+ SIMIX_simcall_answer(simcall);
}
* If you want to get a workstation_VM2013 object from host_lib, see
* ws->generic_resouce.model->type first. If it is
* SURF_MODEL_TYPE_VM_WORKSTATION, you can cast ws to vm_ws. */
- XBT_INFO("Create VM(%s) @ PM(%s) with %ld mounted disks", name, sub_ws_name, xbt_dynar_length(ws->storage));
+ XBT_INFO("Create VM(%s)@PM(%s) with %ld mounted disks", name, sub_ws_name, xbt_dynar_length(ws->storage));
xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, ws);
/* We create cpu_action corresponding to a VM process on the host operating system. */
- vm_ws->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_phys_workstation, GUESTOS_NOISE);
+ /* FIXME: TODO: we have to peridocally input GUESTOS_NOISE to the system? how ? */
+ // vm_ws->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_phys_workstation, GUESTOS_NOISE);
+ vm_ws->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_phys_workstation, 0);
/* TODO:
- * - rebind each time you migrate a VM
* - check how network requests are scheduled between distinct processes competing for the same card.
*/
}
/*
* Update the physical host of the given VM
*/
-static void vm_ws_migrate(void *ind_vm_workstation, void *ind_dest_phys_workstation)
+static void vm_ws_migrate(void *ind_vm, void *ind_dst_pm)
{
/* ind_phys_workstation equals to smx_host_t */
- workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_workstation);
- xbt_assert(vm_ws);
+ workstation_VM2013_t ws_vm2013 = surf_workstation_resource_priv(ind_vm);
+ workstation_CLM03_t ws_clm03_dst = surf_workstation_resource_priv(ind_dst_pm);
+ const char *vm_name = ws_vm2013->ws.generic_resource.name;
+ const char *pm_name_src = ws_vm2013->sub_ws->generic_resource.name;
+ const char *pm_name_dst = ws_clm03_dst->generic_resource.name;
+
+ xbt_assert(ws_vm2013);
+ xbt_assert(ws_clm03_dst);
+
+ ws_vm2013->current_state = SURF_VM_STATE_MIGRATING;
/* do something */
- vm_ws->sub_ws = surf_workstation_resource_priv(ind_dest_phys_workstation);
+ /* update net_elm with that of the destination physical host */
+ void *old_net_elm = ws_vm2013->ws.net_elm;
+ void *new_net_elm = xbt_lib_get_or_null(host_lib, pm_name_dst, ROUTING_HOST_LEVEL);
+ xbt_assert(new_net_elm);
+
+ /* Unregister the current net_elm from host_lib. Do not call the free callback. */
+ xbt_lib_unset(host_lib, vm_name, ROUTING_HOST_LEVEL, 0);
+
+ /* Then, resister the new one. */
+ ws_vm2013->ws.net_elm = new_net_elm;
+ xbt_lib_set(host_lib, vm_name, ROUTING_HOST_LEVEL, ws_vm2013->ws.net_elm);
+
+ ws_vm2013->sub_ws = ws_clm03_dst;
+
+ XBT_DEBUG("migrate VM(%s): change net_elm (%p to %p)", vm_name, old_net_elm, new_net_elm);
+ XBT_DEBUG("migrate VM(%s): change PM (%s to %s)", vm_name, pm_name_src, pm_name_dst);
+
+ ws_vm2013->current_state = SURF_VM_STATE_RUNNING;
}
/*
xbt_assert(vm_ws->ws.generic_resource.model == surf_vm_workstation_model);
- /* xbt_lib_remove() deletes all entries associated to the VM from host_lib.
- * This function does not invoke the registered freeing callback of each
- * level.
+ /* We deregister objects from host_lib, without invoking the freeing callback
+ * of each level.
*
- * FIXME: But, this function deletes all levels of the key. We must
- * be sure that there is no entry at any level. */
- // xbt_lib_remove(host_lib, name);
- // Remove all others in the lib associated to the VM
- // Please note that you only remove the entries (and not free them)
+ * Do not call xbt_lib_remove() here. It deletes all levels of the key,
+ * including MSG_HOST_LEVEL and others. We should unregister only what we know.
+ */
xbt_lib_unset(host_lib, name, SURF_CPU_LEVEL, 0);
xbt_lib_unset(host_lib, name, ROUTING_HOST_LEVEL, 0);
xbt_lib_unset(host_lib, name, SURF_STORAGE_LEVEL, 0);
surf_resource_free(vm_ws);
}
-static int vm_ws_get_state(void *ind_vm_ws){
+static int vm_ws_get_state(void *ind_vm_ws)
+{
return ((workstation_VM2013_t) surf_workstation_resource_priv(ind_vm_ws))->current_state;
}
-static void vm_ws_set_state(void *ind_vm_ws, int state){
- ((workstation_VM2013_t) surf_workstation_resource_priv(ind_vm_ws))->current_state=state;
+static void vm_ws_set_state(void *ind_vm_ws, int state)
+{
+ ((workstation_VM2013_t) surf_workstation_resource_priv(ind_vm_ws))->current_state = state;
+}
+
+static void vm_ws_suspend(void *ind_vm_ws)
+{
+ workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+ XBT_INFO("vm %p suspend", ind_vm_ws);
+ surf_action_suspend(vm_ws->cpu_action);
+
+ vm_ws->current_state = SURF_VM_STATE_SUSPENDED;
+}
+
+static void vm_ws_resume(void *ind_vm_ws)
+{
+ workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+ surf_action_resume(vm_ws->cpu_action);
+
+ vm_ws->current_state = SURF_VM_STATE_RUNNING;
+}
+
+static void vm_ws_save(void *ind_vm_ws)
+{
+ workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+ vm_ws->current_state = SURF_VM_STATE_SAVING;
+
+ /* FIXME: do something here */
+ surf_action_suspend(vm_ws->cpu_action);
+
+ vm_ws->current_state = SURF_VM_STATE_SAVED;
+}
+
+static void vm_ws_restore(void *ind_vm_ws)
+{
+ workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+ vm_ws->current_state = SURF_VM_STATE_RESTORING;
+
+ /* FIXME: do something here */
+ surf_action_resume(vm_ws->cpu_action);
+
+ vm_ws->current_state = SURF_VM_STATE_RUNNING;
}
workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
{
void *ind_sub_host = xbt_lib_get_elm_or_null(host_lib, ws_vm2013->sub_ws->generic_resource.name);
+ XBT_INFO("cost %f remains %f start %f finish %f", ws_vm2013->cpu_action->cost,
+ ws_vm2013->cpu_action->remains,
+ ws_vm2013->cpu_action->start,
+ ws_vm2013->cpu_action->finish
+ );
+
+#if 0
surf_cpu_model_pm->action_unref(ws_vm2013->cpu_action);
- ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, 100); // cost 0 is okay?
+ /* FIXME: this means busy loop? */
+ // ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, GUESTOS_NOISE);
+ ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, 0);
+#endif
+
}
}
#endif
/*
- * A surf level object will be useless in the upper layer. Returing the name
- * will be simple and suffcient.
+ * A surf level object will be useless in the upper layer. Returing the
+ * dict_elm of the host.
**/
-static const char *vm_ws_get_phys_host(void *ind_vm_ws)
+static void *vm_ws_get_pm(void *ind_vm_ws)
{
workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
- return vm_ws->sub_ws->generic_resource.name;
+ const char *sub_ws_name = vm_ws->sub_ws->generic_resource.name;
+
+ return xbt_lib_get_elm_or_null(host_lib, sub_ws_name);
+}
+
+
+
+/* Adding a task to a VM updates the VCPU task on its physical machine. */
+surf_action_t vm_ws_execute(void *workstation, double size)
+{
+ surf_resource_t ws = ((surf_resource_t) surf_workstation_resource_priv(workstation));
+
+ xbt_assert(ws->model->type == SURF_MODEL_TYPE_VM_WORKSTATION);
+ workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
+
+ double old_cost = vm_ws->cpu_action->cost;
+ double new_cost = old_cost + size;
+
+ XBT_INFO("VM(%s)@PM(%s): update dummy action's cost (%f -> %f)",
+ ws->name, vm_ws->sub_ws->generic_resource.name,
+ old_cost, new_cost);
+
+ vm_ws->cpu_action->cost = new_cost;
+
+ return ws_execute(workstation, size);
}
+static void vm_ws_action_cancel(surf_action_t action)
+{
+ XBT_CRITICAL("FIXME: Not yet implemented. Reduce dummy action's cost by %f", action->cost);
+
+ ws_action_cancel(action);
+}
+
+
static void surf_vm_workstation_model_init_internal(void)
{
surf_model_t model = surf_model_init();
model->name = "Virtual Workstation";
model->type = SURF_MODEL_TYPE_VM_WORKSTATION;
+
// model->action_unref = ws_action_unref;
- // model->action_cancel = ws_action_cancel;
+ model->action_cancel = vm_ws_action_cancel;
// model->action_state_set = ws_action_state_set;
model->model_private->finalize = ws_finalize;
-// model->suspend = ws_action_suspend;
-// model->resume = ws_action_resume;
+ /* operation for an action, not for VM it self */
+ model->suspend = ws_action_suspend;
+ model->resume = ws_action_resume;
// model->is_suspended = ws_action_is_suspended;
// model->set_max_duration = ws_action_set_max_duration;
model->set_priority = ws_action_set_priority;
xbt_assert(surf_cpu_model_vm);
model->extension.workstation.cpu_model = surf_cpu_model_vm;
- model->extension.workstation.execute = ws_execute;
- // model->extension.workstation.sleep = ws_action_sleep;
+ model->extension.workstation.execute = vm_ws_execute;
+ model->extension.workstation.sleep = ws_action_sleep;
model->extension.workstation.get_state = ws_get_state;
// model->extension.workstation.get_speed = ws_get_speed;
// model->extension.workstation.get_available_speed = ws_get_available_speed;
model->extension.vm_workstation.set_state = vm_ws_set_state;
model->extension.vm_workstation.get_state = vm_ws_get_state;
model->extension.vm_workstation.migrate = vm_ws_migrate;
- model->extension.vm_workstation.get_phys_host = vm_ws_get_phys_host;
+ model->extension.vm_workstation.get_pm = vm_ws_get_pm;
model->extension.vm_workstation.destroy = vm_ws_destroy;
+ model->extension.vm_workstation.suspend = vm_ws_suspend;
+ model->extension.vm_workstation.resume = vm_ws_resume;
+ model->extension.vm_workstation.save = vm_ws_save;
+ model->extension.vm_workstation.restore = vm_ws_restore;
surf_vm_workstation_model = model;
}
return -1;
}
-static int ws_action_unref(surf_action_t action)
+int ws_action_unref(surf_action_t action)
{
if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
return surf_network_model->action_unref(action);
return 0;
}
-static void ws_action_cancel(surf_action_t action)
+void ws_action_cancel(surf_action_t action)
{
if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
surf_network_model->action_cancel(action);
return cpu->model->extension.cpu.execute(workstation, size);
}
-static surf_action_t ws_action_sleep(void *workstation, double duration)
+surf_action_t ws_action_sleep(void *workstation, double duration)
{
surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
return cpu->model->extension.cpu.sleep(workstation, duration);
}
-static void ws_action_suspend(surf_action_t action)
+void ws_action_suspend(surf_action_t action)
{
if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
surf_network_model->suspend(action);
DIE_IMPOSSIBLE;
}
-static void ws_action_resume(surf_action_t action)
+void ws_action_resume(surf_action_t action)
{
if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
surf_network_model->resume(action);
void ws_action_set_priority(surf_action_t action, double priority);
surf_action_t ws_execute(void *workstation, double size);
+surf_action_t ws_action_sleep(void *workstation, double duration);
+void ws_action_suspend(surf_action_t action);
+void ws_action_resume(surf_action_t action);
e_surf_resource_state_t ws_get_state(void *workstation);
#endif /* WS_PRIVATE_H_ */