Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge tag 'v3_9_90' into hypervisor
[simgrid.git] / src / surf / vm_workstation.c
index 571caa1..145d1c8 100644 (file)
@@ -11,8 +11,8 @@
 #include "surf/surf_resource.h"
 #include "simgrid/sg_config.h"
 #include "vm_workstation_private.h"
-#include "surf/cpu_cas01_private.h"
-#include "surf/maxmin_private.h"
+#include "cpu_cas01_private.h"
+#include "maxmin_private.h"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_vm_workstation, surf,
                                 "Logging specific to the SURF VM workstation module");
@@ -32,7 +32,7 @@ static void vm_ws_create(const char *name, void *ind_phys_workstation)
    * create a physical workstation resource, but specifying the size of
    * s_workstation_VM2013_t and the vm workstation model object. */
   workstation_CLM03_t ws = (workstation_CLM03_t) surf_resource_new(sizeof(s_workstation_VM2013_t),
-      surf_vm_workstation_model, name, NULL);
+      surf_vm_workstation_model, name, NULL, NULL);
 
   /* Currently, we assume a VM has no storage. */
   ws->storage = NULL;
@@ -71,7 +71,8 @@ static void vm_ws_create(const char *name, void *ind_phys_workstation)
   /* We can assume one core and cas01 cpu for the first step.
    * Do xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, cpu) if you get the resource. */
   cpu_cas01_create_resource(name, // name
-      sub_cpu->power_peak,        // host->power_peak,
+      sub_cpu->power_peak_list,        // host->power_peak,
+      sub_cpu->pstate,
       1,                          // host->power_scale,
       NULL,                       // host->power_trace,
       1,                          // host->core_amount,
@@ -108,8 +109,6 @@ static void vm_ws_migrate(void *ind_vm, void *ind_dst_pm)
    xbt_assert(ws_vm2013);
    xbt_assert(ws_clm03_dst);
 
-   ws_vm2013->current_state = SURF_VM_STATE_MIGRATING;
-
    /* do something */
 
    /* update net_elm with that of the destination physical host */
@@ -126,10 +125,35 @@ static void vm_ws_migrate(void *ind_vm, void *ind_dst_pm)
 
    ws_vm2013->sub_ws = ws_clm03_dst;
 
+   /* Update vcpu's action for the new pm */
+   {
+#if 0
+     XBT_INFO("cpu_action->remains %g", ws_vm2013->cpu_action->remains);
+     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
+         );
+     XBT_INFO("cpu_action state %d", surf_action_state_get(ws_vm2013->cpu_action));
+#endif
+
+     /* create a cpu action bound to the pm model at the destination. */
+     surf_action_t new_cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_dst_pm, 0);
+
+     e_surf_action_state_t state = surf_action_state_get(ws_vm2013->cpu_action);
+     if (state != SURF_ACTION_DONE)
+       XBT_CRITICAL("FIXME: may need a proper handling, %d", state);
+     if (ws_vm2013->cpu_action->remains > 0)
+       XBT_CRITICAL("FIXME: need copy the state(?), %f", ws_vm2013->cpu_action->remains);
+
+     int ret = surf_cpu_model_pm->action_unref(ws_vm2013->cpu_action);
+     xbt_assert(ret == 1, "Bug: some resource still remains");
+
+     ws_vm2013->cpu_action = new_cpu_action;
+   }
+
    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;
 }
 
 /*
@@ -144,7 +168,6 @@ static void vm_ws_destroy(void *ind_vm_workstation)
        workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_workstation);
   cpu_Cas01_t cpu = surf_cpu_resource_priv(ind_vm_workstation);
        const char *name = vm_ws->ws.generic_resource.name;
-  XBT_INFO("%s", name);
 
        xbt_assert(vm_ws);
        xbt_assert(vm_ws->ws.generic_resource.model == surf_vm_workstation_model);
@@ -158,9 +181,11 @@ static void vm_ws_destroy(void *ind_vm_workstation)
    */
   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);
   xbt_lib_unset(host_lib, name, SURF_WKS_LEVEL, 0);
 
+  /* TODO: comment out when VM stroage is implemented. */
+  // xbt_lib_unset(host_lib, name, SURF_STORAGE_LEVEL, 0);
+
 
   /* Free the cpu_action of the VM. */
   int ret = surf_cpu_model_pm->action_unref(vm_ws->cpu_action);
@@ -170,6 +195,17 @@ static void vm_ws_destroy(void *ind_vm_workstation)
    * free other objects than lmm_constraint. */
   surf_model_t cpu_model = cpu->generic_resource.model;
   lmm_constraint_free(cpu_model->model_private->maxmin_system, cpu->constraint);
+  {
+    unsigned long i;
+    for (i = 0; i < cpu->core; i++) {
+      void *cnst_id = cpu->constraint_core[i]->id;
+      lmm_constraint_free(cpu_model->model_private->maxmin_system, cpu->constraint_core[i]);
+      xbt_free(cnst_id);
+    }
+
+    xbt_free(cpu->constraint_core);
+  }
+
   surf_resource_free(cpu);
 
   /* Free the network resource of the VM. */
@@ -196,7 +232,6 @@ 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;
@@ -235,37 +270,25 @@ static void vm_ws_restore(void *ind_vm_ws)
   vm_ws->current_state = SURF_VM_STATE_RUNNING;
 }
 
-
 static double get_solved_value(surf_action_t cpu_action)
 {
-  int found = 0;
-  /* NOTE: Do not use surf_workstation_model's maxmin_system. It is not used. */
-  lmm_system_t pm_system = surf_cpu_model_pm->model_private->maxmin_system;
-  lmm_variable_t var = NULL;
-
-  xbt_swag_foreach(var, &pm_system->variable_set) {
-    XBT_DEBUG("var id %p id_int %d double %f", var->id, var->id_int, var->value);
-    if (var->id == cpu_action) {
-      found = 1;
-      break;
-    }
-  }
+  lmm_variable_t var = ((surf_action_lmm_t) cpu_action)->variable;
 
-  if (found)
-    return var->value;
-
-  XBT_CRITICAL("bug: cannot found the solved variable of the action %p", cpu_action);
-  DIE_IMPOSSIBLE;
-  return -1; /* NOT REACHED */
+  return var->value;
 }
 
+/* In the real world, processes on the guest operating system will be somewhat
+ * degraded due to virtualization overhead. The total CPU share that these
+ * processes get is smaller than that of the VM process gets on a host
+ * operating system. */
+// const double virt_overhead = 0.95;
+const double virt_overhead = 1;
 
 static double vm_ws_share_resources(surf_model_t workstation_model, double now)
 {
   /* TODO: udpate action's cost with the total cost of processes on the VM. */
 
 
-
   /* 0. Make sure that we already calculated the resource share at the physical
    * machine layer. */
   {
@@ -311,9 +334,9 @@ static double vm_ws_share_resources(surf_model_t workstation_model, double now)
     workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
     cpu_Cas01_t cpu_cas01 = ind_host[SURF_CPU_LEVEL];
 
-    /* skip if it is not a virtual machine */
     if (!ws_clm03)
       continue;
+    /* skip if it is not a virtual machine */
     if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
       continue;
     xbt_assert(cpu_cas01, "cpu-less workstation");
@@ -325,7 +348,12 @@ static double vm_ws_share_resources(surf_model_t workstation_model, double now)
     XBT_DEBUG("assign %f to vm %s @ pm %s", solved_value,
         ws_clm03->generic_resource.name, ws_vm2013->sub_ws->generic_resource.name);
 
-    cpu_cas01->constraint->bound = solved_value;
+    // TODO: check lmm_update_constraint_bound() works fine instead of the below manual substitution.
+    // cpu_cas01->constraint->bound = solved_value;
+    surf_model_t cpu_model = cpu_cas01->generic_resource.model;
+    xbt_assert(cpu_model == surf_cpu_model_vm);
+    lmm_system_t vcpu_system = cpu_model->model_private->maxmin_system;
+    lmm_update_constraint_bound(vcpu_system, cpu_cas01->constraint, virt_overhead * solved_value);
   }
 
 
@@ -334,7 +362,7 @@ static double vm_ws_share_resources(surf_model_t workstation_model, double now)
 
 
   /* FIXME: 3. do we have to re-initialize our cpu_action object? */
-#if 1
+#if 0
   /* iterate for all hosts including virtual machines */
   xbt_lib_foreach(host_lib, cursor, key, ind_host) {
     workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
@@ -346,16 +374,17 @@ static double vm_ws_share_resources(surf_model_t workstation_model, double now)
       continue;
 
     /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
-    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);
+#if 0
+      workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;            
       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
           );
-
+#endif
 #if 0
+      void *ind_sub_host = xbt_lib_get_elm_or_null(host_lib, ws_vm2013->sub_ws->generic_resource.name);      
       surf_cpu_model_pm->action_unref(ws_vm2013->cpu_action);
       /* FIXME: this means busy loop? */
       // ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, GUESTOS_NOISE);
@@ -384,9 +413,8 @@ static void *vm_ws_get_pm(void *ind_vm_ws)
 }
 
 
-
 /* Adding a task to a VM updates the VCPU task on its physical machine. */
-surf_action_t vm_ws_execute(void *workstation, double size)
+static surf_action_t vm_ws_execute(void *workstation, double size)
 {
   surf_resource_t ws = ((surf_resource_t) surf_workstation_resource_priv(workstation));
 
@@ -396,7 +424,7 @@ surf_action_t vm_ws_execute(void *workstation, double size)
   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)",
+  XBT_DEBUG("VM(%s)@PM(%s): update dummy action's cost (%f -> %f)",
       ws->name, vm_ws->sub_ws->generic_resource.name,
       old_cost, new_cost);
 
@@ -413,6 +441,30 @@ static void vm_ws_action_cancel(surf_action_t action)
 }
 
 
+/* Now we can set bound for each task by using MSG_task_set_bound. But, it does
+ * not work for the dummy CPU action of a VM. Here, we add the set_bound
+ * function for the dummy CPU action. */
+static void vm_ws_set_vm_bound(void *vm, double bound)
+{
+  surf_resource_t ws = ((surf_resource_t) surf_workstation_resource_priv(vm));
+  xbt_assert(ws->model->type == SURF_MODEL_TYPE_VM_WORKSTATION);
+  workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
+
+  surf_action_set_bound(vm_ws->cpu_action, bound);
+}
+
+
+/* set the affinity of a VM to the CPU cores of a PM */
+static void vm_ws_set_vm_affinity(void *vm, void *pm, unsigned long mask)
+{
+  surf_resource_t ws = ((surf_resource_t) surf_workstation_resource_priv(vm));
+  xbt_assert(ws->model->type == SURF_MODEL_TYPE_VM_WORKSTATION);
+  workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
+
+  surf_cpu_model_pm->set_affinity(vm_ws->cpu_action, pm, mask);
+}
+
+
 static void surf_vm_workstation_model_init_internal(void)
 {
   surf_model_t model = surf_model_init();
@@ -438,10 +490,12 @@ static void surf_vm_workstation_model_init_internal(void)
 //   model->is_suspended     = ws_action_is_suspended;
 //   model->set_max_duration = ws_action_set_max_duration;
   model->set_priority     = ws_action_set_priority;
+  model->set_bound        = ws_action_set_bound;
+  model->set_affinity     = ws_action_set_affinity;
 // #ifdef HAVE_TRACING
 //   model->set_category     = ws_action_set_category;
 // #endif
-//   model->get_remains      = ws_action_get_remains;
+  model->get_remains      = ws_action_get_remains;
 // #ifdef HAVE_LATENCY_BOUND_TRACKING
 //   model->get_latency_limited = ws_get_latency_limited;
 // #endif
@@ -458,7 +512,7 @@ static void surf_vm_workstation_model_init_internal(void)
   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_speed = ws_get_speed;
   // model->extension.workstation.get_available_speed = ws_get_available_speed;
 
   // model->extension.workstation.communicate           = ws_communicate;
@@ -482,12 +536,17 @@ static void surf_vm_workstation_model_init_internal(void)
   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_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;
+  model->extension.vm_workstation.get_pm        = vm_ws_get_pm;
+  model->extension.vm_workstation.set_vm_bound  = vm_ws_set_vm_bound;
+  model->extension.vm_workstation.set_vm_affinity  = vm_ws_set_vm_affinity;
+
+  model->extension.workstation.set_params    = ws_set_params;
+  model->extension.workstation.get_params    = ws_get_params;
 
   surf_vm_workstation_model = model;
 }