From: Paul Bédaride Date: Fri, 8 Nov 2013 10:50:47 +0000 (+0100) Subject: Merge tag 'v3_9_90' into hypervisor X-Git-Tag: v3_11_beta~297^2^2~1 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/9b73466ada27682d1729f394549479da83ef4a99 Merge tag 'v3_9_90' into hypervisor Conflicts: include/msg/msg.h include/simgrid/simix.h src/include/surf/surf.h src/msg/msg_global.c src/msg/msg_host.c src/msg/msg_private.h src/msg/msg_process.c src/simix/smx_host.c src/simix/smx_host_private.h src/simix/smx_smurf_private.h src/surf/cpu_cas01.c src/surf/cpu_cas01_private.h src/surf/cpu_ti.c src/surf/surf.c src/surf/workstation.c --- 9b73466ada27682d1729f394549479da83ef4a99 diff --cc .cproject index 7722fbd6ae,2d167a86b9..70f5e1ac39 --- a/.cproject +++ b/.cproject @@@ -1,21 -1,101 +1,22 @@@ -- -- -- ++ - - - - - - - - ++ ++ ++ ++ - - - - - - - - - - - - ++ + + + - - - + ++ + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --cc .project index 0000000000,d935a7abe1..a3b80ff503 mode 000000,100644..100644 --- a/.project +++ b/.project @@@ -1,0 -1,91 +1,27 @@@ + + - simgrid - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - ?name? - - - - org.eclipse.cdt.make.core.append_environment - true - - - org.eclipse.cdt.make.core.autoBuildTarget - all - - - org.eclipse.cdt.make.core.buildArguments - - - - org.eclipse.cdt.make.core.buildCommand - make - - - org.eclipse.cdt.make.core.cleanBuildTarget - clean - - - org.eclipse.cdt.make.core.contents - org.eclipse.cdt.make.core.activeConfigSettings - - - org.eclipse.cdt.make.core.enableAutoBuild - false - - - org.eclipse.cdt.make.core.enableCleanBuild - true - - - org.eclipse.cdt.make.core.enableFullBuild - true - - - org.eclipse.cdt.make.core.fullBuildTarget - all - - - org.eclipse.cdt.make.core.stopOnError - true - - - org.eclipse.cdt.make.core.useDefaultBuildCmd - true - - - - - org.rubypeople.rdt.core.rubybuilder - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.core.cnature - org.rubypeople.rdt.core.rubynature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - org.eclipse.jdt.core.javanature - ++ simgrid ++ ++ ++ ++ ++ ++ org.eclipse.cdt.managedbuilder.core.genmakebuilder ++ clean,full,incremental, ++ ++ ++ ++ ++ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder ++ full,incremental, ++ ++ ++ ++ ++ ++ org.eclipse.cdt.core.cnature ++ org.eclipse.cdt.core.ccnature ++ org.eclipse.cdt.managedbuilder.core.managedBuildNature ++ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature ++ + diff --cc examples/msg/cloud/multicore.c index 6fec15d036,0000000000..47adfc4d34 mode 100644,000000..100644 --- a/examples/msg/cloud/multicore.c +++ b/examples/msg/cloud/multicore.c @@@ -1,433 -1,0 +1,433 @@@ +/* Copyright (c) 2007-2013. The SimGrid Team. All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include +#include "msg/msg.h" +#include "xbt/sysdep.h" /* calloc, printf */ + +/* Create a log channel to have nice outputs. */ +#include "xbt/log.h" +#include "xbt/asserts.h" +XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test, "Messages specific for this msg example"); + + +struct worker_data { + double computation_amount; +}; + + +static int worker_main(int argc, char *argv[]) +{ + struct worker_data *params = MSG_process_get_data(MSG_process_self()); + double computation_amount = params->computation_amount; + + { + double clock_sta = MSG_get_clock(); + + msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL); + MSG_task_execute(task); + MSG_task_destroy(task); + + double clock_end = MSG_get_clock(); + + double duration = clock_end - clock_sta; + double flops_per_sec = computation_amount / duration; + + XBT_INFO("%s: amount %f duration %f (%f flops/s)", + MSG_host_get_name(MSG_host_self()), computation_amount, duration, flops_per_sec); + } + + + + xbt_free(params); + + return 0; +} + + + + +static void test_one_task(msg_host_t hostA, double computation) +{ + + struct worker_data *params = xbt_new(struct worker_data, 1); + params->computation_amount = computation; + + MSG_process_create("worker", worker_main, params, hostA); + + //xbt_free(params); +} + +#if 0 +static void test_two_tasks(msg_host_t hostA, msg_host_t hostB) +{ + const double cpu_speed = MSG_get_host_speed(hostA); + xbt_assert(cpu_speed == MSG_get_host_speed(hostB)); + const double computation_amount = cpu_speed * 10; + const char *hostA_name = MSG_host_get_name(hostA); + const char *hostB_name = MSG_host_get_name(hostB); + + { + XBT_INFO("### Test: no bound for Task1@%s, no bound for Task2@%s", hostA_name, hostB_name); + launch_worker(hostA, "worker0", computation_amount, 0, 0); + launch_worker(hostB, "worker1", computation_amount, 0, 0); + } + + MSG_process_sleep(1000); + + { + XBT_INFO("### Test: 0 for Task1@%s, 0 for Task2@%s (i.e., unlimited)", hostA_name, hostB_name); + launch_worker(hostA, "worker0", computation_amount, 1, 0); + launch_worker(hostB, "worker1", computation_amount, 1, 0); + } + + MSG_process_sleep(1000); + + { + XBT_INFO("### Test: 50%% for Task1@%s, 50%% for Task2@%s", hostA_name, hostB_name); + launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2); + launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 2); + } + + MSG_process_sleep(1000); + + { + XBT_INFO("### Test: 25%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name); + launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 4); + launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4); + } + + MSG_process_sleep(1000); + + { + XBT_INFO("### Test: 75%% for Task1@%s, 100%% for Task2@%s", hostA_name, hostB_name); + launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75); + launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed); + } + + MSG_process_sleep(1000); + + { + XBT_INFO("### Test: no bound for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name); + launch_worker(hostA, "worker0", computation_amount, 0, 0); + launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4); + } + + MSG_process_sleep(1000); + + { + XBT_INFO("### Test: 75%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name); + launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75); + launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4); + } + + MSG_process_sleep(1000); +} +#endif + +static void test_pm(void) +{ + xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar(); + msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t); + msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t); + msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t); + + const double cpu_speed = MSG_get_host_speed(pm0); + const double computation_amount = cpu_speed * 10; + + { + XBT_INFO("# 1. Put a single task on each PM. "); + test_one_task(pm0, computation_amount); + MSG_process_sleep(100); + test_one_task(pm1, computation_amount); + MSG_process_sleep(100); + test_one_task(pm2, computation_amount); + } + + MSG_process_sleep(100); + + { + XBT_INFO("# 2. Put 2 tasks on each PM. "); + test_one_task(pm0, computation_amount); + test_one_task(pm0, computation_amount); + MSG_process_sleep(100); + + test_one_task(pm1, computation_amount); + test_one_task(pm1, computation_amount); + MSG_process_sleep(100); + + test_one_task(pm2, computation_amount); + test_one_task(pm2, computation_amount); + } + + MSG_process_sleep(100); + + { + XBT_INFO("# 3. Put 4 tasks on each PM. "); + test_one_task(pm0, computation_amount); + test_one_task(pm0, computation_amount); + test_one_task(pm0, computation_amount); + test_one_task(pm0, computation_amount); + MSG_process_sleep(100); + + test_one_task(pm1, computation_amount); + test_one_task(pm1, computation_amount); + test_one_task(pm1, computation_amount); + test_one_task(pm1, computation_amount); + MSG_process_sleep(100); + + test_one_task(pm2, computation_amount); + test_one_task(pm2, computation_amount); + test_one_task(pm2, computation_amount); + test_one_task(pm2, computation_amount); + } + + MSG_process_sleep(100); +} + + +static void test_vm(void) +{ + xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar(); + msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t); + msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t); + msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t); + + + const double cpu_speed = MSG_get_host_speed(pm0); + const double computation_amount = cpu_speed * 10; + + + { + msg_host_t vm0 = MSG_vm_create_core(pm0, "vm0"); + msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1"); + msg_host_t vm2 = MSG_vm_create_core(pm2, "vm2"); + + XBT_INFO("# 1. Put a single task on each VM."); + test_one_task(vm0, computation_amount); + MSG_process_sleep(100); + + test_one_task(vm1, computation_amount); + MSG_process_sleep(100); + + test_one_task(vm2, computation_amount); + MSG_process_sleep(100); + + MSG_vm_destroy(vm0); + MSG_vm_destroy(vm1); + MSG_vm_destroy(vm2); + } + + + { + msg_host_t vm0 = MSG_vm_create_core(pm0, "vm0"); + msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1"); + msg_host_t vm2 = MSG_vm_create_core(pm2, "vm2"); + + XBT_INFO("# 2. Put 2 tasks on each VM."); + test_one_task(vm0, computation_amount); + test_one_task(vm0, computation_amount); + MSG_process_sleep(100); + + test_one_task(vm1, computation_amount); + test_one_task(vm1, computation_amount); + MSG_process_sleep(100); + + test_one_task(vm2, computation_amount); + test_one_task(vm2, computation_amount); + MSG_process_sleep(100); + + MSG_vm_destroy(vm0); + MSG_vm_destroy(vm1); + MSG_vm_destroy(vm2); + } + + + { + msg_host_t vm0 = MSG_vm_create_core(pm0, "vm0"); + msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1"); + msg_host_t vm2 = MSG_vm_create_core(pm2, "vm2"); + + XBT_INFO("# 3. Put a task on each VM, and put a task on its PM."); + test_one_task(vm0, computation_amount); + test_one_task(pm0, computation_amount); + MSG_process_sleep(100); + + test_one_task(vm1, computation_amount); + test_one_task(pm1, computation_amount); + MSG_process_sleep(100); + + test_one_task(vm2, computation_amount); + test_one_task(pm2, computation_amount); + MSG_process_sleep(100); + + MSG_vm_destroy(vm0); + MSG_vm_destroy(vm1); + MSG_vm_destroy(vm2); + } + + + { + { + /* 1-core PM */ + XBT_INFO("# 4. Put 2 VMs on a 1-core PM."); + msg_host_t vm0 = MSG_vm_create_core(pm0, "vm0"); + msg_host_t vm1 = MSG_vm_create_core(pm0, "vm1"); + + test_one_task(vm0, computation_amount); + test_one_task(vm1, computation_amount); + MSG_process_sleep(100); + + MSG_vm_destroy(vm0); + MSG_vm_destroy(vm1); + } + + { + /* 2-core PM */ + XBT_INFO("# 5. Put 2 VMs on a 2-core PM."); + msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0"); + msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1"); + + test_one_task(vm0, computation_amount); + test_one_task(vm1, computation_amount); + MSG_process_sleep(100); + + MSG_vm_destroy(vm0); + MSG_vm_destroy(vm1); + } + + { + /* 2-core PM */ + XBT_INFO("# 6. Put 2 VMs on a 2-core PM and 1 task on the PM."); + msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0"); + msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1"); + + test_one_task(vm0, computation_amount); + test_one_task(vm1, computation_amount); + test_one_task(pm1, computation_amount); + MSG_process_sleep(100); + + MSG_vm_destroy(vm0); + MSG_vm_destroy(vm1); + } + + { + /* 2-core PM */ + XBT_INFO("# 7. Put 2 VMs and 2 tasks on a 2-core PM. Put two tasks on one of the VMs."); + msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0"); + msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1"); + test_one_task(pm1, computation_amount); + test_one_task(pm1, computation_amount); + + /* Reduce computation_amount to make all tasks finish at the same time. Simplify results. */ + test_one_task(vm0, computation_amount / 2); + test_one_task(vm0, computation_amount / 2); + test_one_task(vm1, computation_amount); + MSG_process_sleep(100); + + MSG_vm_destroy(vm0); + MSG_vm_destroy(vm1); + } + + { + /* 2-core PM */ + XBT_INFO("# 8. Put 2 VMs and a task on a 2-core PM. Cap the load of VM1 at 50%%."); + /* This is a tricky case. The process schedular of the host OS may not work as expected. */ + + /* VM0 gets 50%. VM1 and VM2 get 75%, respectively. */ + msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0"); + MSG_vm_set_bound(vm0, cpu_speed / 2); + msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1"); + test_one_task(pm1, computation_amount); + + test_one_task(vm0, computation_amount); + test_one_task(vm1, computation_amount); + + MSG_process_sleep(100); + + MSG_vm_destroy(vm0); + MSG_vm_destroy(vm1); + } + + + /* In all the above cases, tasks finish at the same time. + * TODO: more complex cases must be done. + **/ + +#if 0 + { + /* 2-core PM */ + XBT_INFO("# 8. Put 2 VMs and a task on a 2-core PM. Put two tasks on one of the VMs."); + msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0"); + msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1"); + + test_one_task(vm0, computation_amount); + test_one_task(vm0, computation_amount); + test_one_task(vm1, computation_amount); + test_one_task(pm1, computation_amount); + MSG_process_sleep(100); + + MSG_vm_destroy(vm0); + MSG_vm_destroy(vm1); + } +#endif + } +} + + + +static int master_main(int argc, char *argv[]) +{ + XBT_INFO("=== Test PM ==="); + test_pm(); + + XBT_INFO(" "); + XBT_INFO(" "); + XBT_INFO("=== Test VM ==="); + test_vm(); + + return 0; +} + + + + + +int main(int argc, char *argv[]) +{ + /* Get the arguments */ + MSG_init(&argc, argv); + + /* load the platform file */ + if (argc != 2) { + printf("Usage: %s examples/msg/cloud/multicore_plat.xml\n", argv[0]); + return 1; + } + + MSG_create_environment(argv[1]); + + xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar(); + msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t); + msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t); + msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t); + + - XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm0), MSG_get_host_core(pm0), MSG_get_host_speed(pm0)); - XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm1), MSG_get_host_core(pm1), MSG_get_host_speed(pm1)); - XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm2), MSG_get_host_core(pm2), MSG_get_host_speed(pm2)); ++ XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm0), MSG_host_get_core_number(pm0), MSG_get_host_speed(pm0)); ++ XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm1), MSG_host_get_core_number(pm1), MSG_get_host_speed(pm1)); ++ XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm2), MSG_host_get_core_number(pm2), MSG_get_host_speed(pm2)); + + + + MSG_process_create("master", master_main, NULL, pm0); + + + + + int res = MSG_main(); + XBT_INFO("Bye (simulation time %g)", MSG_get_clock()); + + + return !(res == MSG_OK); +} diff --cc include/msg/msg.h index 756f9be932,fa2fc66e6b..c254c1a953 --- a/include/msg/msg.h +++ b/include/msg/msg.h @@@ -102,11 -120,17 +122,18 @@@ XBT_PUBLIC(msg_host_t) MSG_host_self(vo XBT_PUBLIC(int) MSG_get_host_msgload(msg_host_t host); /* int MSG_get_msgload(void); This function lacks specification; discard it */ XBT_PUBLIC(double) MSG_get_host_speed(msg_host_t h); - XBT_PUBLIC(int) MSG_get_host_core(msg_host_t h); + XBT_PUBLIC(int) MSG_host_get_core_number(msg_host_t h); + XBT_PUBLIC(xbt_swag_t) MSG_host_get_process_list(msg_host_t h); XBT_PUBLIC(int) MSG_host_is_avail(msg_host_t h); -XBT_PUBLIC(void) __MSG_host_destroy(msg_host_priv_t host); +XBT_PUBLIC(void) __MSG_host_priv_free(msg_host_priv_t priv); +XBT_PUBLIC(void) __MSG_host_destroy(msg_host_t host); + XBT_PUBLIC(double) MSG_get_host_power_peak_at(msg_host_t h, int pstate_index); + XBT_PUBLIC(double) MSG_get_host_current_power_peak(msg_host_t h); + XBT_PUBLIC(int) MSG_get_host_nb_pstates(msg_host_t h); + XBT_PUBLIC(void) MSG_set_host_power_peak_at(msg_host_t h, int pstate); + XBT_PUBLIC(double) MSG_get_host_consumed_energy(msg_host_t h); + /*property handlers*/ XBT_PUBLIC(xbt_dict_t) MSG_host_get_properties(msg_host_t host); XBT_PUBLIC(const char *) MSG_host_get_property_value(msg_host_t host, @@@ -121,10 -145,8 +148,10 @@@ XBT_PUBLIC(void) MSG_create_environment XBT_PUBLIC(msg_host_t) MSG_get_host_by_name(const char *name); XBT_PUBLIC(xbt_dynar_t) MSG_hosts_as_dynar(void); XBT_PUBLIC(int) MSG_get_host_number(void); - +XBT_PUBLIC(void) MSG_host_get_params(msg_host_t ind_pm, ws_params_t params); +XBT_PUBLIC(void) MSG_host_set_params(msg_host_t ind_pm, ws_params_t params); - + XBT_PUBLIC(xbt_dict_t) MSG_host_get_storage_list(msg_host_t host); + XBT_PUBLIC(xbt_dict_t) MSG_host_get_storage_content(msg_host_t host); /************************** Process handling *********************************/ XBT_PUBLIC(msg_process_t) MSG_process_create(const char *name, xbt_main_func_t code, diff --cc include/simgrid/simix.h index 7901cdf4a2,ecdd1d62ed..3b98414075 --- a/include/simgrid/simix.h +++ b/include/simgrid/simix.h @@@ -13,9 -13,8 +13,10 @@@ #include "xbt/function_types.h" #include "xbt/parmap.h" #include "xbt/swag.h" + #include "simgrid/platf.h" +#include "simgrid/platf.h" // ws_params_t + SG_BEGIN_DECL() /**************************** Scalar Values **********************************/ @@@ -297,9 -303,8 +307,10 @@@ XBT_PUBLIC(void) SIMIX_file_set_data(sm XBT_PUBLIC(smx_host_t) simcall_host_get_by_name(const char *name); XBT_PUBLIC(const char *) simcall_host_get_name(smx_host_t host); XBT_PUBLIC(xbt_dict_t) simcall_host_get_properties(smx_host_t host); +XBT_PUBLIC(void) simcall_host_on(smx_host_t host); +XBT_PUBLIC(void) simcall_host_off(smx_host_t host); XBT_PUBLIC(int) simcall_host_get_core(smx_host_t host); + XBT_PUBLIC(xbt_swag_t) simcall_host_get_process_list(smx_host_t host); XBT_PUBLIC(double) simcall_host_get_speed(smx_host_t host); XBT_PUBLIC(double) simcall_host_get_available_speed(smx_host_t host); /* Two possible states, 1 - CPU ON and 0 CPU OFF */ @@@ -308,9 -313,15 +319,15 @@@ XBT_PUBLIC(void *) simcall_host_get_dat XBT_PUBLIC(void) simcall_host_set_data(smx_host_t host, void *data); + XBT_PUBLIC(double) simcall_host_get_current_power_peak(smx_host_t host); + XBT_PUBLIC(double) simcall_host_get_power_peak_at(smx_host_t host, int pstate_index); + XBT_PUBLIC(int) simcall_host_get_nb_pstates(smx_host_t host); + XBT_PUBLIC(void) simcall_host_set_power_peak_at(smx_host_t host, int pstate_index); + XBT_PUBLIC(double) simcall_host_get_consumed_energy(smx_host_t host); + XBT_PUBLIC(smx_action_t) simcall_host_execute(const char *name, smx_host_t host, double computation_amount, - double priority); + double priority, double bound, unsigned long affinity_mask); XBT_PUBLIC(smx_action_t) simcall_host_parallel_execute(const char *name, int host_nb, smx_host_t *host_list, @@@ -323,27 -334,8 +340,28 @@@ XBT_PUBLIC(void) simcall_host_execution XBT_PUBLIC(double) simcall_host_execution_get_remains(smx_action_t execution); XBT_PUBLIC(e_smx_state_t) simcall_host_execution_get_state(smx_action_t execution); XBT_PUBLIC(void) simcall_host_execution_set_priority(smx_action_t execution, double priority); +XBT_PUBLIC(void) simcall_host_execution_set_bound(smx_action_t execution, double bound); +XBT_PUBLIC(void) simcall_host_execution_set_affinity(smx_action_t execution, smx_host_t host, unsigned long mask); XBT_PUBLIC(e_smx_state_t) simcall_host_execution_wait(smx_action_t execution); + XBT_PUBLIC(xbt_dict_t) simcall_host_get_storage_list(smx_host_t host); +XBT_PUBLIC(void) simcall_host_get_params(smx_host_t vm, ws_params_t param); +XBT_PUBLIC(void) simcall_host_set_params(smx_host_t vm, ws_params_t param); + +/******************************* VM simcalls ********************************/ +// Create the vm_workstation at the SURF level +XBT_PUBLIC(void*) simcall_vm_create(const char *name, smx_host_t host); +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(void *) simcall_vm_get_pm(smx_host_t vm); +XBT_PUBLIC(void) simcall_vm_set_bound(smx_host_t vm, double bound); +XBT_PUBLIC(void) simcall_vm_set_affinity(smx_host_t vm, smx_host_t pm, unsigned long mask); +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); +XBT_PUBLIC(void) simcall_vm_suspend(smx_host_t vm); +XBT_PUBLIC(void) simcall_vm_destroy(smx_host_t vm); +XBT_PUBLIC(void) simcall_vm_shutdown(smx_host_t vm); /**************************** Process simcalls ********************************/ /* Constructor and Destructor */ diff --cc src/bindings/java/jmsg_task.h index 80789845b1,197d86a6da..eec36475a9 --- a/src/bindings/java/jmsg_task.h +++ b/src/bindings/java/jmsg_task.h @@@ -124,6 -124,6 +124,14 @@@ JNIEXPORT void JNICALL Java_org_simgrid JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_execute (JNIEnv *, jobject); ++/* ++ * Class org_simgrid_msg_Task ++ * Method setBound ++ * Signature ()V ++ */ ++JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_setBound ++ (JNIEnv *, jobject, jdouble); ++ /* * Class org_simgrid_msg_Task * Method getName diff --cc src/bindings/java/org/simgrid/msg/VM.java index 68c92a4e38,5c9c8e333a..7b7340492c --- a/src/bindings/java/org/simgrid/msg/VM.java +++ b/src/bindings/java/org/simgrid/msg/VM.java @@@ -1,7 -1,7 +1,7 @@@ /* - * JNI interface to Cloud interface in Simgrid + * JNI interface to virtual machine in Simgrid * - * Copyright 2006-2012 The SimGrid Team. + * Copyright (c) 2006-2013. The SimGrid Team. * All right reserved. * * This program is free software; you can redistribute diff --cc src/include/surf/surf.h index d0c6714081,0f0694a186..dffd664e84 --- a/src/include/surf/surf.h +++ b/src/include/surf/surf.h @@@ -243,23 -233,21 +241,24 @@@ typedef struct surf_network_model_exten typedef struct surf_storage_model_extension_public { surf_action_t(*open) (void *storage, const char* mount, const char* path); surf_action_t(*close) (void *storage, surf_file_t fd); - surf_action_t(*read) (void *storage, void* ptr, size_t size, - surf_file_t fd); - surf_action_t(*write) (void *storage, const void* ptr, size_t size, - surf_file_t fd); + surf_action_t(*read) (void *storage, surf_file_t fd, sg_storage_size_t size); + surf_action_t(*write) (void *storage, surf_file_t fd, sg_storage_size_t size); surf_action_t(*stat) (void *storage, surf_file_t fd); surf_action_t(*ls) (void *storage, const char *path); + xbt_dict_t(*get_properties) (const void *storage); + xbt_dict_t(*get_content) (void *storage); + sg_storage_size_t(*get_size) (void *storage); } s_surf_model_extension_storage_t; - /** \ingroup SURF_models - * \brief Workstation model extension public - * - * Public functions specific to the workstation model. - */ +/** \ingroup SURF_models + * \brief Workstation model extension public + * + * Public functions specific to the workstation model. + */ typedef struct surf_workstation_model_extension_public { + /* This points to the surf cpu model object bound to the workstation model. */ + surf_model_t cpu_model; + surf_action_t(*execute) (void *workstation, double size); /**< Execute a computation amount on a workstation and create the corresponding action */ surf_action_t(*sleep) (void *workstation, double duration); /**< Make a workstation sleep during a given duration */ @@@ -291,67 -285,21 +296,71 @@@ surf_action_t(*stat) (void *workstation, surf_file_t fd); int(*unlink) (void *workstation, surf_file_t fd); surf_action_t(*ls) (void *workstation, const char* mount, const char *path); - size_t (*get_size) (void *workstation, surf_file_t fd); + sg_storage_size_t (*get_size) (void *workstation, surf_file_t fd); + xbt_dynar_t (*get_info) (void *workstation, surf_file_t fd); int (*link_shared) (const void *link); - xbt_dict_t(*get_properties) (const void *resource); + xbt_dict_t(*get_properties) (const void *resource); void (*add_traces) (void); + void (*get_params) (void *ind_vm_ws, ws_params_t param); + void (*set_params) (void *ind_vm_ws, ws_params_t param); + xbt_dynar_t (*get_vms) (void *ind_vm_ws); + + sg_storage_size_t (*get_free_size) (void *workstation,const char* name); + sg_storage_size_t (*get_used_size) (void *workstation,const char* name); + xbt_dict_t (*get_storage_list) (void *workstation); - } s_surf_model_extension_workstation_t; +typedef struct surf_vm_workstation_model_extension_public { + /* The vm workstation model object has all members of the physical machine + * workstation model object. If these members are correctly initialized also + * in the vm workstation model object, we can access the vm workstation model + * object as if it is the pm workstatoin model object. + * + * But, it's not so clean. Think it again later. + * */ + s_surf_model_extension_workstation_t basic; + + // start does not appear here as it corresponds to turn the state from created to running (see smx_vm.c) + + 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() + + int (*get_state) (void *ind_vm_ws); + void (*set_state) (void *ind_vm_ws, int state); + + void * (*get_pm) (void *ind_vm_ws); // will be vm_ws_get_pm() + + void (*set_vm_bound) (void *ind_vm_ws, double bound); // will be vm_ws_set_vm_bound() + void (*set_vm_affinity) (void *ind_vm_ws, void *ind_pm_ws, unsigned long mask); // will be vm_ws_set_vm_affinity() + +} s_surf_model_extension_vm_workstation_t; + +/** \ingroup SURF_models + * \brief Model types + * + * The type of the model object. For example, we will have two model objects + * of the surf cpu model. One is for physical machines, and the other is for + * virtual machines. + * + */ +typedef enum { + SURF_MODEL_TYPE_CPU = 0, + SURF_MODEL_TYPE_NETWORK, + SURF_MODEL_TYPE_STORAGE, + SURF_MODEL_TYPE_WORKSTATION, + SURF_MODEL_TYPE_VM_WORKSTATION, + SURF_MODEL_TYPE_NEW_MODEL +} e_surf_model_type_t; /** \ingroup SURF_models * \brief Model datatype @@@ -438,15 -375,13 +447,20 @@@ static inline void *surf_storage_resour return xbt_lib_get_elm_or_null(storage_lib, name); } + typedef struct surf_resource { + surf_model_t model; + char *name; + xbt_dict_t properties; + void_f_pvoid_t free_f; + } s_surf_resource_t, *surf_resource_t; + +static inline surf_model_t surf_resource_model(const void *host, int level) { + /* If level is SURF_WKS_LEVEL, ws is a workstation_CLM03 object. It has + * surf_resource at the generic_resource field. */ + surf_resource_t ws = xbt_lib_get_level((void *) host, level); + return ws->model; +} + - - /** * Resource which have a metric handled by a maxmin system */ @@@ -726,8 -648,17 +742,18 @@@ XBT_PUBLIC_DATA(s_surf_model_descriptio * \brief List of initialized models */ XBT_PUBLIC_DATA(xbt_dynar_t) model_list; +XBT_PUBLIC_DATA(xbt_dynar_t) model_list_invoke; + /** \ingroup SURF_simulation + * \brief List of hosts that have juste restarted and whose autorestart process should be restarted. + */ + XBT_PUBLIC_DATA(xbt_dynar_t) host_that_restart; + + /** \ingroup SURF_simulation + * \brief List of hosts for which one want to be notified if they ever restart. + */ + XBT_PUBLIC(xbt_dict_t) watched_hosts_lib; + /*******************************************/ /*** SURF Platform *************************/ /*******************************************/ diff --cc src/msg/msg_global.c index 7290f944f8,d98766c398..77ce1e0392 --- a/src/msg/msg_global.c +++ b/src/msg/msg_global.c @@@ -68,9 -71,10 +69,10 @@@ void MSG_init_nocheck(int *argc, char * #endif XBT_DEBUG("ADD MSG LEVELS"); - MSG_HOST_LEVEL = xbt_lib_add_level(host_lib, (void_f_pvoid_t) __MSG_host_destroy); + MSG_HOST_LEVEL = xbt_lib_add_level(host_lib, (void_f_pvoid_t) __MSG_host_priv_free); + MSG_STORAGE_LEVEL = xbt_lib_add_level(storage_lib, (void_f_pvoid_t) __MSG_storage_destroy); - atexit(MSG_exit); + if(sg_cfg_get_boolean("clean_atexit")) atexit(MSG_exit); } #ifdef MSG_USE_DEPRECATED diff --cc src/msg/msg_host.c index 6657f0abc4,4dbe948fe8..894ae72b28 --- a/src/msg/msg_host.c +++ b/src/msg/msg_host.c @@@ -301,25 -280,95 +318,116 @@@ int MSG_host_is_avail(msg_host_t host xbt_assert((host != NULL), "Invalid parameters (host is NULL)"); return (simcall_host_get_state(host)); } - +/** \ingroup m_host_management + * \brief Set the parameters of a given host + * + * \param host a host + * \param params a prameter object + */ +void MSG_host_set_params(msg_host_t ind_pm, ws_params_t params) +{ + simcall_host_set_params(ind_pm, params); +} + +/** \ingroup m_host_management + * \brief Get the parameters of a given host + * + * \param host a host + * \param params a prameter object + */ +void MSG_host_get_params(msg_host_t ind_pm, ws_params_t params) +{ + simcall_host_get_params(ind_pm, params); +} + + /** \ingroup m_host_management + * \brief Return the speed of the processor (in flop/s) at a given pstate + * + * \param host host to test + * \param pstate_index pstate to test + * \return Returns the processor speed associated with pstate_index + */ + double MSG_get_host_power_peak_at(msg_host_t host, int pstate_index) { + xbt_assert((host != NULL), "Invalid parameters (host is NULL)"); + return (simcall_host_get_power_peak_at(host, pstate_index)); + } + + /** \ingroup m_host_management + * \brief Return the current speed of the processor (in flop/s) + * + * \param host host to test + * \return Returns the current processor speed + */ + double MSG_get_host_current_power_peak(msg_host_t host) { + xbt_assert((host != NULL), "Invalid parameters (host is NULL)"); + return simcall_host_get_current_power_peak(host); + } + + /** \ingroup m_host_management + * \brief Return the number of pstates defined for a host + * + * \param host host to test + */ + int MSG_get_host_nb_pstates(msg_host_t host) { + + xbt_assert((host != NULL), "Invalid parameters (host is NULL)"); + return (simcall_host_get_nb_pstates(host)); + } + + /** \ingroup m_host_management + * \brief Sets the speed of the processor (in flop/s) at a given pstate + * + * \param host host to test + * \param pstate_index pstate to switch to + */ + void MSG_set_host_power_peak_at(msg_host_t host, int pstate_index) { + xbt_assert((host != NULL), "Invalid parameters (host is NULL)"); + + simcall_host_set_power_peak_at(host, pstate_index); + } + + /** \ingroup m_host_management + * \brief Return the total energy consumed by a host (in Joules) + * + * \param host host to test + * \return Returns the consumed energy + */ + double MSG_get_host_consumed_energy(msg_host_t host) { + xbt_assert((host != NULL), "Invalid parameters (host is NULL)"); + return simcall_host_get_consumed_energy(host); + } + + /** \ingroup m_host_management + * \brief Return the list of mount point names on an host. + * \param host a host + * \return a dict containing all mount point on the host (mount_name => msg_storage_t) + */ + xbt_dict_t MSG_host_get_storage_list(msg_host_t host) + { + xbt_assert((host != NULL), "Invalid parameters"); + return (simcall_host_get_storage_list(host)); + } + + /** \ingroup msg_host_management + * \brief Return the content of mounted storages on an host. + * \param host a host + * \return a dict containing content (as a dict) of all storages mounted on the host + */ + xbt_dict_t MSG_host_get_storage_content(msg_host_t host) + { + xbt_assert((host != NULL), "Invalid parameters"); + xbt_dict_t contents = xbt_dict_new_homogeneous(NULL); + msg_storage_t storage; + char* storage_name; + char* mount_name; + xbt_dict_cursor_t cursor = NULL; + + xbt_dict_t storage_list = simcall_host_get_storage_list(host); + + xbt_dict_foreach(storage_list,cursor,mount_name,storage_name){ + storage = (msg_storage_t)xbt_lib_get_elm_or_null(storage_lib,storage_name); + xbt_dict_t content = simcall_storage_get_content(storage); + xbt_dict_set(contents,mount_name, content,NULL); + } + return contents; + } diff --cc src/msg/msg_private.h index c2c2e07c44,f3e1b89f36..950c5074f2 --- a/src/msg/msg_private.h +++ b/src/msg/msg_private.h @@@ -138,7 -141,9 +143,9 @@@ XBT_PUBLIC_DATA(MSG_Global_t) msg_globa #endif msg_host_t __MSG_host_create(smx_host_t workstation); + msg_storage_t __MSG_storage_create(smx_storage_t storage); -void __MSG_host_destroy(msg_host_priv_t host); +void __MSG_host_destroy(msg_host_t host); + void __MSG_storage_destroy(msg_storage_priv_t host); void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc); void MSG_process_create_from_SIMIX(smx_process_t *process, const char *name, diff --cc src/simix/smx_deployment.c index 72072a3e40,3b53ec8ac8..50b4588152 --- a/src/simix/smx_deployment.c +++ b/src/simix/smx_deployment.c @@@ -36,23 -36,6 +36,23 @@@ static void parse_process(sg_platf_proc smx_process_arg_t arg = NULL; smx_process_t process_created = NULL; + arg = xbt_new0(s_smx_process_arg_t, 1); + arg->code = parse_code; + arg->data = NULL; + arg->hostname = sg_host_name(host); + arg->argc = process->argc; + arg->argv = xbt_new(char *,process->argc); + int i; + for (i=0; iargc; i++) + arg->argv[i] = xbt_strdup(process->argv[i]); - arg->name = (char*)(arg->argv)[0]; ++ arg->name = xbt_strdup(arg->argv[0]); + arg->kill_time = kill_time; + arg->properties = current_property_set; + if (!SIMIX_host_priv(host)->boot_processes) { + SIMIX_host_priv(host)->boot_processes = xbt_dynar_new(sizeof(smx_process_arg_t), _SIMIX_host_free_process_arg); + } + xbt_dynar_push_as(SIMIX_host_priv(host)->boot_processes,smx_process_arg_t,arg); + if (start_time > SIMIX_get_clock()) { arg = xbt_new0(s_smx_process_arg_t, 1); arg->name = (char*)(process->argv)[0]; diff --cc src/simix/smx_global.c index e171cd787f,48127cbcf4..58397da7ee --- a/src/simix/smx_global.c +++ b/src/simix/smx_global.c @@@ -323,15 -330,20 +330,25 @@@ void SIMIX_run(void while ((action = xbt_swag_extract(set))) SIMIX_simcall_post((smx_action_t) action->data); set = model->states.done_action_set; - while ((action = xbt_swag_extract(set))) - SIMIX_simcall_post((smx_action_t) action->data); + + while ((action = xbt_swag_extract(set))) { + if (action->data == NULL) + XBT_DEBUG("probably vcpu's action %p, skip", action); + else + SIMIX_simcall_post((smx_action_t) action->data); + } } + /* Autorestart all process */ + if(host_that_restart) { + char *hostname = NULL; + xbt_dynar_foreach(host_that_restart,iter,hostname) { + XBT_INFO("Restart processes on host: %s",hostname); + SIMIX_host_autorestart(SIMIX_host_get_by_name(hostname)); + } + xbt_dynar_reset(host_that_restart); + } + /* Clean processes to destroy */ SIMIX_process_empty_trash(); diff --cc src/simix/smx_host.c index 3c3272234f,2480bbdcf2..68d36e48ce --- a/src/simix/smx_host.c +++ b/src/simix/smx_host.c @@@ -34,92 -34,10 +34,92 @@@ smx_host_t SIMIX_host_create(const cha /* Update global variables */ xbt_lib_set(host_lib,name,SIMIX_HOST_LEVEL,smx_host); - - return xbt_lib_get_elm_or_null(host_lib, name); + + return xbt_lib_get_or_null(host_lib, name, SIMIX_HOST_LEVEL); } +void SIMIX_pre_host_on(smx_simcall_t simcall, smx_host_t h) +{ + SIMIX_host_on(h); +} + +/** + * \brief Start the host if it is off + * + */ +void SIMIX_host_on(smx_host_t h) +{ + smx_host_priv_t host = SIMIX_host_priv(h); + + xbt_assert((host != NULL), "Invalid parameters"); + + surf_model_t ws_model = surf_resource_model(h, SURF_WKS_LEVEL); + if (ws_model->extension.workstation.get_state(h)==SURF_RESOURCE_OFF) { + ws_model->extension.workstation.set_state(h, SURF_RESOURCE_ON); + unsigned int cpt; + smx_process_arg_t arg; + xbt_dynar_foreach(host->boot_processes,cpt,arg) { + smx_process_t process; + + XBT_DEBUG("Booting Process %s(%s) right now", arg->argv[0], arg->hostname); + if (simix_global->create_process_function) { + simix_global->create_process_function(&process, + arg->argv[0], + arg->code, + NULL, + arg->hostname, + arg->kill_time, + arg->argc, + arg->argv, + arg->properties, + arg->auto_restart); + } + else { + simcall_process_create(&process, + arg->argv[0], + arg->code, + NULL, + arg->hostname, + arg->kill_time, + arg->argc, + arg->argv, + arg->properties, + arg->auto_restart); + } + } + } +} + +void SIMIX_pre_host_off(smx_simcall_t simcall, smx_host_t h) +{ + SIMIX_host_off(h, simcall->issuer); +} + +/** + * \brief Stop the host if it is on + * + */ +void SIMIX_host_off(smx_host_t h, smx_process_t issuer) +{ + smx_host_priv_t host = SIMIX_host_priv(h); + + xbt_assert((host != NULL), "Invalid parameters"); + + surf_model_t ws_model = surf_resource_model(h, SURF_WKS_LEVEL); + if (ws_model->extension.workstation.get_state(h)==SURF_RESOURCE_ON) { + ws_model->extension.workstation.set_state(h, SURF_RESOURCE_OFF); + + /* Clean Simulator data */ + if (xbt_swag_size(host->process_list) != 0) { + smx_process_t process = NULL; + xbt_swag_foreach(process, host->process_list) { + SIMIX_process_kill(process, issuer); + XBT_DEBUG("Killing %s on %s by %s", process->name, sg_host_name(process->smx_host), issuer->name); + } + } + } +} + /** * \brief Internal function to destroy a SIMIX host. * @@@ -250,10 -176,59 +260,59 @@@ double SIMIX_pre_host_get_available_spe double SIMIX_host_get_available_speed(smx_host_t host){ xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); - return surf_workstation_model->extension.workstation. - get_available_speed(host); + surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL); + return ws_model->extension.workstation.get_available_speed(host); } + double SIMIX_pre_host_get_current_power_peak(smx_simcall_t simcall, smx_host_t host){ + return SIMIX_host_get_current_power_peak(host); + } + double SIMIX_host_get_current_power_peak(smx_host_t host) { + xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); + return surf_workstation_model->extension.workstation. + get_current_power_peak(host); + } + + double SIMIX_pre_host_get_power_peak_at(smx_simcall_t simcall, smx_host_t host, int pstate_index){ + return SIMIX_host_get_power_peak_at(host, pstate_index); + } + double SIMIX_host_get_power_peak_at(smx_host_t host, int pstate_index) { + xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); + + return surf_workstation_model->extension.workstation. + get_power_peak_at(host, pstate_index); + } + + int SIMIX_pre_host_get_nb_pstates(smx_simcall_t simcall, smx_host_t host){ + return SIMIX_host_get_nb_pstates(host); + } + int SIMIX_host_get_nb_pstates(smx_host_t host) { + xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); + + return surf_workstation_model->extension.workstation. + get_nb_pstates(host); + } + + + void SIMIX_pre_host_set_power_peak_at(smx_simcall_t simcall, smx_host_t host, int pstate_index){ + SIMIX_host_set_power_peak_at(host, pstate_index); + } + void SIMIX_host_set_power_peak_at(smx_host_t host, int pstate_index) { + xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); + + surf_workstation_model->extension.workstation. + set_power_peak_at(host, pstate_index); + } + + double SIMIX_pre_host_get_consumed_energy(smx_simcall_t simcall, smx_host_t host){ + return SIMIX_host_get_consumed_energy(host); + } + double SIMIX_host_get_consumed_energy(smx_host_t host) { + xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); + return surf_workstation_model->extension.workstation. + get_consumed_energy(host); + } + int SIMIX_pre_host_get_state(smx_simcall_t simcall, smx_host_t host){ return SIMIX_host_get_state(host); } @@@ -288,9 -263,13 +347,13 @@@ void* SIMIX_host_get_data(smx_host_t ho return SIMIX_host_priv(host)->data; } -static void _SIMIX_host_free_process_arg(void *data) +void _SIMIX_host_free_process_arg(void *data) { smx_process_arg_t arg = *(void**)data; + int i; + for (i = 0; i < arg->argc; i++) + xbt_free(arg->argv[i]); + xbt_free(arg->argv); xbt_free(arg->name); xbt_free(arg); } @@@ -728,31 -635,11 +799,40 @@@ void SIMIX_set_category(smx_action_t ac } #endif - +/** + * \brief Function to get the parameters of the given the SIMIX host. + * + * \param host the host to get_phys_host (a smx_host_t) + * \param param the parameter object space to be overwritten (a ws_params_t) + */ +void SIMIX_host_get_params(smx_host_t ind_vm, ws_params_t params) +{ + /* jump to ws_get_params(). */ + surf_workstation_model->extension.workstation.get_params(ind_vm, params); +} + +void SIMIX_pre_host_get_params(smx_simcall_t simcall, smx_host_t ind_vm, ws_params_t params) +{ + SIMIX_host_get_params(ind_vm, params); +} + +void SIMIX_host_set_params(smx_host_t ind_vm, ws_params_t params) +{ + /* jump to ws_set_params(). */ + surf_workstation_model->extension.workstation.set_params(ind_vm, params); +} + +void SIMIX_pre_host_set_params(smx_simcall_t simcall, smx_host_t ind_vm, ws_params_t params) +{ + SIMIX_host_set_params(ind_vm, params); +} ++ + xbt_dict_t SIMIX_pre_host_get_storage_list(smx_simcall_t simcall, smx_host_t host){ + return SIMIX_host_get_storage_list(host); + } ++ + xbt_dict_t SIMIX_host_get_storage_list(smx_host_t host){ + xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); + + return surf_workstation_model->extension.workstation.get_storage_list(host); + } diff --cc src/simix/smx_host_private.h index cfb4a2c421,f91d19df29..c2f7d97eb8 --- a/src/simix/smx_host_private.h +++ b/src/simix/smx_host_private.h @@@ -44,10 -43,13 +45,15 @@@ xbt_swag_t SIMIX_host_get_process_list( double SIMIX_host_get_speed(smx_host_t host); double SIMIX_host_get_available_speed(smx_host_t host); int SIMIX_host_get_state(smx_host_t host); +void SIMIX_host_on(smx_host_t host); +void SIMIX_host_off(smx_host_t host, smx_process_t issuer); + double SIMIX_host_get_current_power_peak(smx_host_t host); + double SIMIX_host_get_power_peak_at(smx_host_t host, int pstate_index); + int SIMIX_host_get_nb_pstates(smx_host_t host); + double SIMIX_host_get_consumed_energy(smx_host_t host); + void SIMIX_host_set_power_peak_at(smx_host_t host, int pstate_index); smx_action_t SIMIX_host_execute(const char *name, - smx_host_t host, double computation_amount, double priority); + smx_host_t host, double computation_amount, double priority, double bound, unsigned long affinity_mask); smx_action_t SIMIX_host_parallel_execute(const char *name, int host_nb, smx_host_t *host_list, double *computation_amount, double *communication_amount, @@@ -57,18 -59,16 +63,20 @@@ void SIMIX_host_execution_cancel(smx_ac double SIMIX_host_execution_get_remains(smx_action_t action); e_smx_state_t SIMIX_host_execution_get_state(smx_action_t action); void SIMIX_host_execution_set_priority(smx_action_t action, double priority); +void SIMIX_host_execution_set_bound(smx_action_t action, double bound); +void SIMIX_host_execution_set_affinity(smx_action_t action, smx_host_t host, unsigned long mask); void SIMIX_pre_host_execution_wait(smx_simcall_t simcall, smx_action_t action); + xbt_dict_t SIMIX_host_get_storage_list(smx_host_t host); // pre prototypes smx_host_t SIMIX_pre_host_get_by_name(smx_simcall_t, const char*); const char* SIMIX_pre_host_self_get_name(smx_simcall_t); const char* SIMIX_pre_host_get_name(smx_simcall_t, smx_host_t); +void SIMIX_pre_host_on(smx_simcall_t, smx_host_t host); +void SIMIX_pre_host_off(smx_simcall_t, smx_host_t host); xbt_dict_t SIMIX_pre_host_get_properties(smx_simcall_t, smx_host_t); int SIMIX_pre_host_get_core(smx_simcall_t, smx_host_t); + xbt_swag_t SIMIX_pre_host_get_process_list(smx_simcall_t, smx_host_t host); double SIMIX_pre_host_get_speed(smx_simcall_t, smx_host_t); double SIMIX_pre_host_get_available_speed(smx_simcall_t, smx_host_t); int SIMIX_pre_host_get_state(smx_simcall_t, smx_host_t); diff --cc src/simix/smx_smurf_private.h index 546079c92a,1e191f71e4..9d05379a8b --- a/src/simix/smx_smurf_private.h +++ b/src/simix/smx_smurf_private.h @@@ -1,4 -1,4 +1,4 @@@ - /* Copyright (c) 2007, 2008, 2009, 2010. The SimGrid Team. -/* Copyright (c) 2007-2010, 2012-2013. The SimGrid Team. ++ /* Copyright (c) 2007-2010, 2012-2013. The SimGrid Team. * All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it @@@ -261,41 -261,28 +261,48 @@@ #define SIMCALL_LIST1(ACTION, sep) \ ACTION(SIMCALL_HOST_GET_BY_NAME, host_get_by_name, WITH_ANSWER, TSPEC(result, smx_host_t), TSTRING(name)) sep \ ACTION(SIMCALL_HOST_GET_NAME, host_get_name, WITH_ANSWER, TSTRING(result), TSPEC(host, smx_host_t)) sep \ +ACTION(SIMCALL_HOST_ON, host_on, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t)) sep \ +ACTION(SIMCALL_HOST_OFF, host_off, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t)) sep \ ACTION(SIMCALL_HOST_GET_PROPERTIES, host_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(host, smx_host_t)) sep \ ACTION(SIMCALL_HOST_GET_CORE, host_get_core, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \ + ACTION(SIMCALL_HOST_GET_PROCESS_LIST, host_get_process_list, WITH_ANSWER, TSPEC(result, xbt_swag_t), TSPEC(host, smx_host_t)) sep \ ACTION(SIMCALL_HOST_GET_SPEED, host_get_speed, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \ ACTION(SIMCALL_HOST_GET_AVAILABLE_SPEED, host_get_available_speed, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \ ACTION(SIMCALL_HOST_GET_STATE, host_get_state, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \ ACTION(SIMCALL_HOST_GET_DATA, host_get_data, WITH_ANSWER, TPTR(result), TSPEC(host, smx_host_t)) sep \ ACTION(SIMCALL_HOST_SET_DATA, host_set_data, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t), TPTR(data)) sep \ +ACTION(SIMCALL_HOST_EXECUTE, host_execute, WITH_ANSWER, TSPEC(result, smx_action_t), TSTRING(name), TSPEC(host, smx_host_t), TDOUBLE(computation_amount), TDOUBLE(priority), TDOUBLE(bound), TULONG(affinity_mask)) sep \ + ACTION(SIMCALL_HOST_GET_CURRENT_POWER_PEAK, host_get_current_power_peak, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \ + ACTION(SIMCALL_HOST_GET_POWER_PEAK_AT, host_get_power_peak_at, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t), TINT(pstate_index)) sep \ + ACTION(SIMCALL_HOST_GET_NB_PSTATES, host_get_nb_pstates, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \ + ACTION(SIMCALL_HOST_SET_POWER_PEAK_AT, host_set_power_peak_at, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t), TINT(pstate_index)) sep \ + ACTION(SIMCALL_HOST_GET_CONSUMED_ENERGY, host_get_consumed_energy, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \ -ACTION(SIMCALL_HOST_EXECUTE, host_execute, WITH_ANSWER, TSPEC(result, smx_action_t), TSTRING(name), TSPEC(host, smx_host_t), TDOUBLE(computation_amount), TDOUBLE(priority)) sep \ ACTION(SIMCALL_HOST_PARALLEL_EXECUTE, host_parallel_execute, WITH_ANSWER, TSPEC(result, smx_action_t), TSTRING(name), TINT(host_nb), TSPEC(host_list, smx_host_t*), TSPEC(computation_amount, double*), TSPEC(communication_amount, double*), TDOUBLE(amount), TDOUBLE(rate)) sep \ ACTION(SIMCALL_HOST_EXECUTION_DESTROY, host_execution_destroy, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t)) sep \ ACTION(SIMCALL_HOST_EXECUTION_CANCEL, host_execution_cancel, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t)) sep \ ACTION(SIMCALL_HOST_EXECUTION_GET_REMAINS, host_execution_get_remains, WITH_ANSWER, TDOUBLE(result), TSPEC(execution, smx_action_t)) sep \ 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_SET_BOUND, host_execution_set_bound, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t), TDOUBLE(bound)) sep \ +ACTION(SIMCALL_HOST_EXECUTION_SET_AFFINITY, host_execution_set_affinity, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t), TSPEC(ws, smx_host_t), TULONG(mask)) sep \ ACTION(SIMCALL_HOST_EXECUTION_WAIT, host_execution_wait, WITHOUT_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \ +ACTION(SIMCALL_HOST_GET_PARAMS, host_get_params, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TSPEC(params, ws_params_t)) sep \ +ACTION(SIMCALL_HOST_SET_PARAMS, host_set_params, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TSPEC(params, ws_params_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, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \ +ACTION(SIMCALL_VM_SET_STATE, vm_set_state, WITH_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, WITH_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_SET_BOUND, vm_set_bound, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TDOUBLE(bound)) sep \ +ACTION(SIMCALL_VM_SET_AFFINITY, vm_set_affinity, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TSPEC(ind_pm, smx_host_t), TULONG(mask)) sep \ +ACTION(SIMCALL_VM_DESTROY, vm_destroy, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \ +ACTION(SIMCALL_VM_SUSPEND, vm_suspend, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \ +ACTION(SIMCALL_VM_RESUME, vm_resume, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \ +ACTION(SIMCALL_VM_SHUTDOWN, vm_shutdown, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \ +ACTION(SIMCALL_VM_SAVE, vm_save, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \ +ACTION(SIMCALL_VM_RESTORE, vm_restore, WITH_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \ + ACTION(SIMCALL_HOST_GET_STORAGE_LIST, host_get_storage_list, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(host, 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 \ diff --cc src/simix/smx_user.c index 84382c5286,a4453a8cbd..a2261cde73 --- a/src/simix/smx_user.c +++ b/src/simix/smx_user.c @@@ -180,10 -233,9 +255,9 @@@ double simcall_host_get_consumed_energy * \param priority computation priority * \return A new SIMIX execution action */ - smx_action_t simcall_host_execute(const char *name, smx_host_t host, double computation_amount, - double priority) + double priority, double bound, unsigned long affinity_mask) { /* checking for infinite values */ xbt_assert(isfinite(computation_amount), "computation_amount is not finite!"); diff --cc src/smpi/smpi_bench.c index 357e6f806b,6feda0fcd4..f83d36b557 --- a/src/smpi/smpi_bench.c +++ b/src/smpi/smpi_bench.c @@@ -127,7 -129,7 +129,7 @@@ void smpi_execute_flops(double flops) host = SIMIX_host_self(); XBT_DEBUG("Handle real computation time: %f flops", flops); -- action = simcall_host_execute("computation", host, flops, 1); ++ action = simcall_host_execute("computation", host, flops, 1, 0, 0); #ifdef HAVE_TRACING simcall_set_category (action, TRACE_internal_smpi_get_category()); #endif diff --cc src/surf/cpu_cas01.c index aa3379993a,15cf9981c3..c267e86aa2 --- a/src/surf/cpu_cas01.c +++ b/src/surf/cpu_cas01.c @@@ -8,31 -8,37 +8,38 @@@ #include "surf/surf_resource.h" #include "maxmin_private.h" #include "simgrid/sg_config.h" - #include "surf/cpu_cas01_private.h" + #include "cpu_cas01_private.h" + + #include "string.h" + #include "stdlib.h" -surf_model_t surf_cpu_model = NULL; - +/* the model objects for physical machines and virtual machines */ +surf_model_t surf_cpu_model_pm = NULL; +surf_model_t surf_cpu_model_vm = NULL; - #undef GENERIC_LMM_ACTION - #undef GENERIC_ACTION - #undef ACTION_GET_CPU - #define GENERIC_LMM_ACTION(action) action->generic_lmm_action - #define GENERIC_ACTION(action) GENERIC_LMM_ACTION(action).generic_action - #define ACTION_GET_CPU(action) ((surf_action_cpu_Cas01_t) action)->cpu - - typedef struct surf_action_cpu_cas01 { - s_surf_action_lmm_t generic_lmm_action; - } s_surf_action_cpu_Cas01_t, *surf_action_cpu_Cas01_t; - XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu, surf, "Logging specific to the SURF CPU IMPROVED module"); static xbt_swag_t cpu_running_action_set_that_does_not_need_being_checked = NULL; + /* Additionnal callback function to cleanup some data, called from surf_resource_free */ + + static void cpu_cas01_cleanup(void* r){ + cpu_Cas01_t cpu = (cpu_Cas01_t)r; + unsigned int iter; + xbt_dynar_t power_tuple = NULL; + xbt_dynar_foreach(cpu->energy->power_range_watts_list, iter, power_tuple) + xbt_dynar_free(&power_tuple); + xbt_dynar_free(&cpu->energy->power_range_watts_list); + xbt_dynar_free(&cpu->power_peak_list); + xbt_free(cpu->energy); + return; + } - void *cpu_cas01_create_resource(const char *name, double power_peak, + /* This function is registered as a callback to sg_platf_new_host() and never called directly */ -static void *cpu_create_resource(const char *name, xbt_dynar_t power_peak, ++void *cpu_cas01_create_resource(const char *name, xbt_dynar_t power_peak, + int pstate, double power_scale, tmgr_trace_t power_trace, int core, @@@ -47,9 -52,19 +54,19 @@@ "Host '%s' declared several times in the platform file", name); cpu = (cpu_Cas01_t) surf_resource_new(sizeof(s_cpu_Cas01_t), - surf_cpu_model, name, - cpu_properties, &cpu_cas01_cleanup); + cpu_model, name, - cpu_properties); - cpu->power_peak = power_peak; ++ cpu_properties, &cpu_cas01_cleanup); + cpu->power_peak = xbt_dynar_get_as(power_peak, pstate, double); + cpu->power_peak_list = power_peak; + cpu->pstate = pstate; + + cpu->energy = xbt_new(s_energy_cpu_cas01_t, 1); + cpu->energy->total_energy = 0; + cpu->energy->power_range_watts_list = cpu_get_watts_range_list(cpu); + cpu->energy->last_updated = surf_get_clock(); + + XBT_DEBUG("CPU create: peak=%f, pstate=%d",cpu->power_peak, cpu->pstate); + xbt_assert(cpu->power_peak > 0, "Power has to be >0"); cpu->power_scale = power_scale; cpu->core = core; @@@ -96,11 -91,9 +113,12 @@@ static void parse_cpu_init(sg_platf_host_cbarg_t host) { - cpu_create_resource(host->id, + /* This function is called when a platform file is parsed. Physical machines + * are defined there. Thus, we use the cpu model object for the physical + * machine layer. */ + cpu_cas01_create_resource(host->id, host->power_peak, + host->pstate, host->power_scale, host->power_trace, host->core_amount, @@@ -174,19 -159,123 +192,123 @@@ static double cpu_share_resources_full( xbt_swag_offset(action, generic_lmm_action. variable), - surf_cpu_model->model_private->maxmin_system, lmm_solve); + cpu_model->model_private->maxmin_system, lmm_solve); } -static void cpu_update_actions_state_lazy(double now, double delta) +static void cpu_update_actions_state_lazy(surf_model_t cpu_model, double now, double delta) { - generic_update_actions_state_lazy(now, delta, surf_cpu_model); + generic_update_actions_state_lazy(now, delta, cpu_model); } -static void cpu_update_actions_state_full(double now, double delta) +static void cpu_update_actions_state_full(surf_model_t cpu_model, double now, double delta) { - generic_update_actions_state_full(now, delta, surf_cpu_model); + generic_update_actions_state_full(now, delta, cpu_model); } + xbt_dynar_t cpu_get_watts_range_list(cpu_Cas01_t cpu_model) + { + xbt_dynar_t power_range_list; + xbt_dynar_t power_tuple; + int i = 0, pstate_nb=0; + xbt_dynar_t current_power_values; + double min_power, max_power; + xbt_dict_t props = cpu_model->generic_resource.properties; + + if (props == NULL) + return NULL; + + char* all_power_values_str = xbt_dict_get_or_null(props, "power_per_state"); + + if (all_power_values_str == NULL) + return NULL; + + + power_range_list = xbt_dynar_new(sizeof(xbt_dynar_t), NULL); + xbt_dynar_t all_power_values = xbt_str_split(all_power_values_str, ","); + + pstate_nb = xbt_dynar_length(all_power_values); + for (i=0; i< pstate_nb; i++) + { + /* retrieve the power values associated with the current pstate */ + current_power_values = xbt_str_split(xbt_dynar_get_as(all_power_values, i, char*), ":"); + xbt_assert(xbt_dynar_length(current_power_values) > 1, + "Power properties incorrectly defined - could not retrieve min and max power values for host %s", + cpu_model->generic_resource.name); + + /* min_power corresponds to the idle power (cpu load = 0) */ + /* max_power is the power consumed at 100% cpu load */ + min_power = atof(xbt_dynar_get_as(current_power_values, 0, char*)); + max_power = atof(xbt_dynar_get_as(current_power_values, 1, char*)); + + power_tuple = xbt_dynar_new(sizeof(double), NULL); + xbt_dynar_push_as(power_tuple, double, min_power); + xbt_dynar_push_as(power_tuple, double, max_power); + + xbt_dynar_push_as(power_range_list, xbt_dynar_t, power_tuple); + xbt_dynar_free(¤t_power_values); + } + xbt_dynar_free(&all_power_values); + return power_range_list; + + } + + /** + * Computes the power consumed by the host according to the current pstate and processor load + * + */ + static double cpu_get_current_watts_value(cpu_Cas01_t cpu_model, double cpu_load) + { + xbt_dynar_t power_range_list = cpu_model->energy->power_range_watts_list; + + if (power_range_list == NULL) + { + XBT_DEBUG("No power range properties specified for host %s", cpu_model->generic_resource.name); + return 0; + } + xbt_assert(xbt_dynar_length(power_range_list) == xbt_dynar_length(cpu_model->power_peak_list), + "The number of power ranges in the properties does not match the number of pstates for host %s", + cpu_model->generic_resource.name); + + /* retrieve the power values associated with the current pstate */ + xbt_dynar_t current_power_values = xbt_dynar_get_as(power_range_list, cpu_model->pstate, xbt_dynar_t); + + /* min_power corresponds to the idle power (cpu load = 0) */ + /* max_power is the power consumed at 100% cpu load */ + double min_power = xbt_dynar_get_as(current_power_values, 0, double); + double max_power = xbt_dynar_get_as(current_power_values, 1, double); + double power_slope = max_power - min_power; + + double current_power = min_power + cpu_load * power_slope; + + XBT_DEBUG("[get_current_watts] min_power=%f, max_power=%f, slope=%f", min_power, max_power, power_slope); + XBT_DEBUG("[get_current_watts] Current power (watts) = %f, load = %f", current_power, cpu_load); + + return current_power; + + } + + /** + * Updates the total energy consumed as the sum of the current energy and + * the energy consumed by the current action + */ + void cpu_update_energy(cpu_Cas01_t cpu_model, double cpu_load) + { + + double start_time = cpu_model->energy->last_updated; + double finish_time = surf_get_clock(); + + XBT_DEBUG("[cpu_update_energy] action time interval=(%f-%f), current power peak=%f, current pstate=%d", + start_time, finish_time, cpu_model->power_peak, cpu_model->pstate); + double current_energy = cpu_model->energy->total_energy; + double action_energy = cpu_get_current_watts_value(cpu_model, cpu_load)*(finish_time-start_time); + + cpu_model->energy->total_energy = current_energy + action_energy; + cpu_model->energy->last_updated = finish_time; + + XBT_DEBUG("[cpu_update_energy] old_energy_value=%f, action_energy_value=%f", current_energy, action_energy); + + } + static void cpu_update_resource_state(void *id, tmgr_trace_event_t event_type, double value, double date) @@@ -194,16 -283,10 +316,14 @@@ cpu_Cas01_t cpu = id; lmm_variable_t var = NULL; lmm_element_t elem = NULL; + surf_model_t cpu_model = ((surf_resource_t) cpu)->model; - surf_watched_hosts(); - if (event_type == cpu->power_event) { + /* TODO (Hypervisor): do the same thing for constraint_core[i] */ + xbt_assert(cpu->core == 1, "FIXME: add power scaling code also for constraint_core[i]"); + cpu->power_scale = value; - lmm_update_constraint_bound(surf_cpu_model->model_private->maxmin_system, cpu->constraint, + lmm_update_constraint_bound(cpu_model->model_private->maxmin_system, cpu->constraint, cpu->core * cpu->power_scale * cpu->power_peak); #ifdef HAVE_TRACING @@@ -221,12 -304,11 +341,14 @@@ if (tmgr_trace_event_free(event_type)) cpu->power_event = NULL; } else if (event_type == cpu->state_event) { + /* TODO (Hypervisor): do the same thing for constraint_core[i] */ + xbt_assert(cpu->core == 1, "FIXME: add state change code also for constraint_core[i]"); + - if (value > 0) + if (value > 0) { + if(cpu->state_current == SURF_RESOURCE_OFF) + xbt_dynar_push_as(host_that_restart, char*, (cpu->generic_resource.name)); cpu->state_current = SURF_RESOURCE_ON; - else { + } else { lmm_constraint_t cnst = cpu->constraint; cpu->state_current = SURF_RESOURCE_OFF; @@@ -335,8 -338,9 +457,9 @@@ static void cpu_action_set_affinity(sur static surf_action_t cpu_execute(void *cpu, double size) { surf_action_cpu_Cas01_t action = NULL; + //xbt_dict_cursor_t cursor = NULL; cpu_Cas01_t CPU = surf_cpu_resource_priv(cpu); - //xbt_dict_t props = CPU->generic_resource.properties; + surf_model_t cpu_model = ((surf_resource_t) CPU)->model; XBT_IN("(%s,%g)", surf_resource_name(CPU), size); action = @@@ -430,17 -424,51 +553,51 @@@ static double cpu_get_available_speed(v return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_scale; } + static double cpu_get_current_power_peak(void *cpu) + { + return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak; + } + + static double cpu_get_power_peak_at(void *cpu, int pstate_index) + { + xbt_dynar_t plist = ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak_list; + xbt_assert((pstate_index <= xbt_dynar_length(plist)), "Invalid parameters (pstate index out of bounds)"); + + return xbt_dynar_get_as(plist, pstate_index, double); + } + + static int cpu_get_nb_pstates(void *cpu) + { + return xbt_dynar_length(((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak_list); + } + + static void cpu_set_power_peak_at(void *cpu, int pstate_index) + { + cpu_Cas01_t cpu_implem = (cpu_Cas01_t)surf_cpu_resource_priv(cpu); + xbt_dynar_t plist = cpu_implem->power_peak_list; + xbt_assert((pstate_index <= xbt_dynar_length(plist)), "Invalid parameters (pstate index out of bounds)"); + + double new_power_peak = xbt_dynar_get_as(plist, pstate_index, double); + cpu_implem->pstate = pstate_index; + cpu_implem->power_peak = new_power_peak; + } + + static double cpu_get_consumed_energy(void *cpu) + { + return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->energy->total_energy; + } + -static void cpu_finalize(void) +static void cpu_finalize(surf_model_t cpu_model) { - lmm_system_free(surf_cpu_model->model_private->maxmin_system); - surf_cpu_model->model_private->maxmin_system = NULL; + lmm_system_free(cpu_model->model_private->maxmin_system); + cpu_model->model_private->maxmin_system = NULL; - if (surf_cpu_model->model_private->action_heap) - xbt_heap_free(surf_cpu_model->model_private->action_heap); - xbt_swag_free(surf_cpu_model->model_private->modified_set); + if (cpu_model->model_private->action_heap) + xbt_heap_free(cpu_model->model_private->action_heap); + xbt_swag_free(cpu_model->model_private->modified_set); - surf_model_exit(surf_cpu_model); - surf_cpu_model = NULL; + surf_model_exit(cpu_model); + cpu_model = NULL; xbt_swag_free(cpu_running_action_set_that_does_not_need_being_checked); cpu_running_action_set_that_does_not_need_being_checked = NULL; @@@ -497,46 -524,47 +654,52 @@@ static surf_model_t surf_cpu_model_init } else xbt_die("Invalid cpu update mechanism!"); - surf_cpu_model->model_private->update_resource_state = + cpu_model->model_private->update_resource_state = cpu_update_resource_state; - surf_cpu_model->model_private->finalize = cpu_finalize; - - surf_cpu_model->suspend = surf_action_suspend; - surf_cpu_model->resume = surf_action_resume; - surf_cpu_model->is_suspended = surf_action_is_suspended; - surf_cpu_model->set_max_duration = surf_action_set_max_duration; - surf_cpu_model->set_priority = surf_action_set_priority; + cpu_model->model_private->finalize = cpu_finalize; + + cpu_model->suspend = surf_action_suspend; + cpu_model->resume = surf_action_resume; + cpu_model->is_suspended = surf_action_is_suspended; + cpu_model->set_max_duration = surf_action_set_max_duration; + cpu_model->set_priority = surf_action_set_priority; + cpu_model->set_bound = surf_action_set_bound; + cpu_model->set_affinity = cpu_action_set_affinity; #ifdef HAVE_TRACING - surf_cpu_model->set_category = surf_action_set_category; + cpu_model->set_category = surf_action_set_category; #endif - surf_cpu_model->get_remains = surf_action_get_remains; + cpu_model->get_remains = surf_action_get_remains; - surf_cpu_model->extension.cpu.execute = cpu_execute; - surf_cpu_model->extension.cpu.sleep = cpu_action_sleep; + cpu_model->extension.cpu.execute = cpu_execute; + cpu_model->extension.cpu.sleep = cpu_action_sleep; - surf_cpu_model->extension.cpu.get_state = cpu_get_state; - surf_cpu_model->extension.cpu.get_core = cpu_get_core; - surf_cpu_model->extension.cpu.get_speed = cpu_get_speed; - surf_cpu_model->extension.cpu.get_available_speed = + cpu_model->extension.cpu.get_state = cpu_get_state; + cpu_model->extension.cpu.set_state = cpu_set_state; + cpu_model->extension.cpu.get_core = cpu_get_core; + cpu_model->extension.cpu.get_speed = cpu_get_speed; + cpu_model->extension.cpu.get_available_speed = cpu_get_available_speed; - surf_cpu_model->extension.cpu.get_current_power_peak = cpu_get_current_power_peak; - surf_cpu_model->extension.cpu.get_power_peak_at = cpu_get_power_peak_at; - surf_cpu_model->extension.cpu.get_nb_pstates = cpu_get_nb_pstates; - surf_cpu_model->extension.cpu.set_power_peak_at = cpu_set_power_peak_at; - surf_cpu_model->extension.cpu.get_consumed_energy = cpu_get_consumed_energy; ++ cpu_model->extension.cpu.get_current_power_peak = cpu_get_current_power_peak; ++ cpu_model->extension.cpu.get_power_peak_at = cpu_get_power_peak_at; ++ cpu_model->extension.cpu.get_nb_pstates = cpu_get_nb_pstates; ++ cpu_model->extension.cpu.set_power_peak_at = cpu_set_power_peak_at; ++ cpu_model->extension.cpu.get_consumed_energy = cpu_get_consumed_energy; + - surf_cpu_model->extension.cpu.add_traces = cpu_add_traces_cpu; + cpu_model->extension.cpu.add_traces = cpu_add_traces_cpu; - if (!surf_cpu_model->model_private->maxmin_system) { - surf_cpu_model->model_private->maxmin_system = lmm_system_new(surf_cpu_model->model_private->selective_update); + if (!cpu_model->model_private->maxmin_system) { + cpu_model->model_private->maxmin_system = lmm_system_new(cpu_model->model_private->selective_update); } - if (surf_cpu_model->model_private->update_mechanism == UM_LAZY) { - surf_cpu_model->model_private->action_heap = xbt_heap_new(8, NULL); - xbt_heap_set_update_callback(surf_cpu_model->model_private->action_heap, + if (cpu_model->model_private->update_mechanism == UM_LAZY) { + cpu_model->model_private->action_heap = xbt_heap_new(8, NULL); + xbt_heap_set_update_callback(cpu_model->model_private->action_heap, surf_action_lmm_update_index_heap); - surf_cpu_model->model_private->modified_set = + cpu_model->model_private->modified_set = xbt_swag_new(xbt_swag_offset(comp, generic_lmm_action.action_list_hookup)); - surf_cpu_model->model_private->maxmin_system->keep_track = surf_cpu_model->model_private->modified_set; + cpu_model->model_private->maxmin_system->keep_track = cpu_model->model_private->modified_set; } + + return cpu_model; } /*********************************************************************/ diff --cc src/surf/cpu_cas01_private.h index b126a3b907,cb133501ae..c212ca5ab4 --- a/src/surf/cpu_cas01_private.h +++ b/src/surf/cpu_cas01_private.h @@@ -1,5 -1,5 +1,4 @@@ -- -/* Copyright (c) 2009-2010, 2013. The SimGrid Team. +/* Copyright (c) 2013. The SimGrid Team. * All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it @@@ -8,6 -8,28 +7,27 @@@ #ifndef _SURF_CPU_CAS01_PRIVATE_H #define _SURF_CPU_CAS01_PRIVATE_H + #undef GENERIC_LMM_ACTION + #undef GENERIC_ACTION + #undef ACTION_GET_CPU + #define GENERIC_LMM_ACTION(action) action->generic_lmm_action + #define GENERIC_ACTION(action) GENERIC_LMM_ACTION(action).generic_action + #define ACTION_GET_CPU(action) ((surf_action_cpu_Cas01_t) action)->cpu + + typedef struct surf_action_cpu_cas01 { + s_surf_action_lmm_t generic_lmm_action; + } s_surf_action_cpu_Cas01_t, *surf_action_cpu_Cas01_t; + - + /* + * Energy-related properties for the cpu_cas01 model + */ + typedef struct energy_cpu_cas01 { + xbt_dynar_t power_range_watts_list; /*< List of (min_power,max_power) pairs corresponding to each cpu pstate */ + double total_energy; /*< Total energy consumed by the host */ + double last_updated; /*< Timestamp of the last energy update event*/ + } s_energy_cpu_cas01_t, *energy_cpu_cas01_t; + + typedef struct cpu_Cas01 { s_surf_resource_t generic_resource; s_xbt_swag_hookup_t modified_cpu_hookup; @@@ -19,19 -41,13 +39,27 @@@ tmgr_trace_event_t state_event; lmm_constraint_t constraint; + xbt_dynar_t power_peak_list; /*< List of supported CPU capacities */ + int pstate; /*< Current pstate (index in the power_peak_list)*/ - energy_cpu_cas01_t energy; /*< Structure with energy-consumption data */ ++ energy_cpu_cas01_t energy; ++ + /* Note (hypervisor): */ + lmm_constraint_t *constraint_core; } s_cpu_Cas01_t, *cpu_Cas01_t; +void *cpu_cas01_create_resource(const char *name, - double power_peak, ++ xbt_dynar_t power_peak, ++ int pstate, + double power_scale, + tmgr_trace_t power_trace, + int core, + e_surf_resource_state_t state_initial, + tmgr_trace_t state_trace, + xbt_dict_t cpu_properties, + surf_model_t cpu_model); + + xbt_dynar_t cpu_get_watts_range_list(cpu_Cas01_t cpu_model); + void cpu_update_energy(cpu_Cas01_t cpu_model, double cpu_load); + #endif /* _SURF_CPU_CAS01_PRIVATE_H */ diff --cc src/surf/cpu_ti.c index 8ba0f400c5,b14ceecb14..44cbf6ed54 --- a/src/surf/cpu_ti.c +++ b/src/surf/cpu_ti.c @@@ -161,12 -161,18 +162,18 @@@ static void* cpu_ti_create_resource(con name); xbt_assert(core==1,"Multi-core not handled with this model yet"); cpu = (cpu_ti_t) surf_resource_new(sizeof(s_cpu_ti_t), - cpu_model, name,cpu_properties); - surf_cpu_model, name,cpu_properties, NULL); ++ cpu_model, name,cpu_properties, NULL); cpu->action_set = xbt_swag_new(xbt_swag_offset(ti_action, cpu_list_hookup)); - cpu->power_peak = power_peak; + + xbt_dynar_get_cpy(power_peak, 0, &cpu->power_peak); + xbt_dynar_free(&power_peak); /* kill memory leak */ + //cpu->power_peak = power_peak; + cpu->pstate = pstate; + XBT_DEBUG("CPU create: peak=%f, pstate=%d",cpu->power_peak, cpu->pstate); + xbt_assert(cpu->power_peak > 0, "Power has to be >0"); - XBT_DEBUG("power scale %lf", power_scale); + XBT_DEBUG("power scale %f", power_scale); cpu->power_scale = power_scale; cpu->avail_trace = cpu_ti_parse_trace(power_trace, power_scale); cpu->state_current = state_initial; @@@ -502,20 -500,17 +510,18 @@@ static void cpu_ti_update_resource_stat double value, double date) { cpu_ti_t cpu = id; + surf_model_t cpu_model = ((surf_resource_t) cpu)->model; surf_action_cpu_ti_t action; - surf_watched_hosts(); - if (event_type == cpu->power_event) { tmgr_trace_t power_trace; surf_cpu_ti_tgmr_t trace; s_tmgr_event_t val; - XBT_DEBUG("Finish trace date: %lf value %lf date %lf", surf_get_clock(), + XBT_DEBUG("Finish trace date: %f value %f date %f", surf_get_clock(), value, date); /* update remaining of actions and put in modified cpu swag */ - cpu_ti_update_remaining_amount(cpu, date); + cpu_ti_update_remaining_amount(cpu_model, cpu, date); xbt_swag_insert(cpu, cpu_ti_modified_cpu); power_trace = cpu->avail_trace->power_trace; diff --cc src/surf/storage.c index 9db9c852e1,53691367bd..8984495657 --- a/src/surf/storage.c +++ b/src/surf/storage.c @@@ -252,11 -293,9 +293,9 @@@ static void storage_update_actions_stat { surf_action_storage_t action = NULL; surf_action_storage_t next_action = NULL; - xbt_swag_t running_actions = surf_storage_model->states.running_action_set; + xbt_swag_t running_actions = storage_model->states.running_action_set; - // Update the disk usage - // Update the file size - // For each action of type write + xbt_swag_foreach_safe(action, next_action, running_actions) { if(action->type == WRITE) { diff --cc src/surf/surf.c index 157cbe2639,de54e4373c..e6947fed68 --- a/src/surf/surf.c +++ b/src/surf/surf.c @@@ -676,60 -678,6 +689,6 @@@ static void surf_share_resources(surf_m static void surf_update_actions_state(surf_model_t model) { - model->model_private->update_actions_state(NOW, min); + model->model_private->update_actions_state(model, NOW, min); } - /* This function is a pimple that we ought to fix. But it won't be easy. - * - * The surf_solve() function does properly return the set of actions that changed. - * Instead, each model change a global data, and then the caller of surf_solve must - * pick into these sets of action_failed and action_done. - * - * This was not clean but ok as long as we didn't had to restart the processes when the resource comes back up. - * We worked by putting sentinel actions on every resources we are interested in, - * so that surf informs us if/when the corresponding resource fails. - * - * But this does not work to get Simix informed of when a resource comes back up, and this is where this pimple comes. - * We have a set of resources that are currently down and for which simix needs to know when it comes back up. - * And the current function is called *at every simulation step* to sweep over that set, searching for a resource - * that was turned back up in the meanwhile. This is UGLY and slow. - * - * The proper solution would be to not rely on globals for the action_failed and action_done swags. - * They must be passed as parameter by the caller (the handling of these actions in simix may let you - * think that these two sets can be merged, but their handling in SimDag induce the contrary unless this - * simdag code can check by itself whether the action is done of failed -- seems very doable, but yet more - * cleanup to do). - * - * Once surf_solve() is passed the set of actions that changed, you want to add a new set of resources back up - * as parameter to this function. You also want to add a boolean field "restart_watched" to each resource, and - * make sure that whenever a resource with this field enabled comes back up, it's added to that set so that Simix - * sees it and react accordingly. This would kill that need for surf to call simix. - * - */ - - static void remove_watched_host(void *key) - { - xbt_dict_remove(watched_hosts_lib, *(char**)key); - } - - void surf_watched_hosts(void) - { - char *key; - void *host; - xbt_dict_cursor_t cursor; - xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL); - - XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib"); - xbt_dict_foreach(watched_hosts_lib,cursor,key,host) - { - if(SIMIX_host_get_state(host) == SURF_RESOURCE_ON){ - XBT_INFO("Restart processes on host: %s",SIMIX_host_get_name(host)); - SIMIX_host_autorestart(host); - xbt_dynar_push_as(hosts, char*, key); - } - else - XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key); - } - xbt_dynar_map(hosts, remove_watched_host); - xbt_dynar_free(&hosts); - } diff --cc src/surf/surf_action.c index bb3006f229,86e752db18..0189b49801 --- a/src/surf/surf_action.c +++ b/src/surf/surf_action.c @@@ -380,6 -371,27 +383,27 @@@ double surf_action_get_remains(surf_act return action->remains; } + /** + * Update the CPU total energy for a finished action + * + */ + void update_resource_energy(surf_model_t model, surf_action_lmm_t action) + { - if(model == surf_cpu_model){ ++ if(model->type == SURF_MODEL_TYPE_CPU){ + cpu_Cas01_t cpu_model = (cpu_Cas01_t)lmm_constraint_id(lmm_get_cnst_from_var + (model->model_private->maxmin_system, + action->variable, 0)); + + if( cpu_model->energy->last_updated < surf_get_clock()) { + double load = lmm_constraint_get_usage(cpu_model->constraint) / cpu_model->power_peak; + cpu_update_energy(cpu_model, load); + } + } + } + + + + void generic_update_actions_state_lazy(double now, double delta, surf_model_t model) { surf_action_lmm_t action; @@@ -421,9 -433,10 +445,10 @@@ } #endif - if(model == surf_cpu_model){ + if(model->type == SURF_MODEL_TYPE_CPU){ action->generic_action.finish = surf_get_clock(); - XBT_DEBUG("Action %p finished", action); + + update_resource_energy(model, action); /* set the remains to 0 due to precision problems when updating the remaining amount */ action->generic_action.remains = 0; diff --cc src/surf/vm_workstation.c index 1d0a398933,0000000000..145d1c891b mode 100644,000000..100644 --- a/src/surf/vm_workstation.c +++ b/src/surf/vm_workstation.c @@@ -1,558 -1,0 +1,559 @@@ +/* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "xbt/ex.h" +#include "xbt/dict.h" +#include "portable.h" +#include "surf_private.h" +#include "surf/surf_resource.h" +#include "simgrid/sg_config.h" +#include "vm_workstation_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"); + + +surf_model_t surf_vm_workstation_model = NULL; + +/* ind means ''indirect'' that this is a reference on the whole dict_elm + * structure (i.e not on the surf_resource_private infos) */ + +static void vm_ws_create(const char *name, void *ind_phys_workstation) +{ + workstation_CLM03_t sub_ws = surf_workstation_resource_priv(ind_phys_workstation); + const char *sub_ws_name = sub_ws->generic_resource.name; + + /* The workstation_VM2013 struct inherits the workstation_CLM03 struct. We + * 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; + + /* Currently, a VM uses the network resource of its physical host. In + * host_lib, this network resource object is refered from two different keys. + * When deregistering the reference that points the network resource object + * from the VM name, we have to make sure that the system does not call the + * free callback for the network resource object. The network resource object + * is still used by the physical machine. */ + ws->net_elm = xbt_lib_get_or_null(host_lib, sub_ws_name, ROUTING_HOST_LEVEL); + xbt_lib_set(host_lib, name, ROUTING_HOST_LEVEL, ws->net_elm); + + /* The SURF_WKS_LEVEL at host_lib saves workstation_CLM03 objects. Please + * note workstation_VM2013 objects, inheriting the workstation_CLM03 + * structure, are also saved there. + * + * 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_lib_set(host_lib, name, SURF_WKS_LEVEL, ws); + + + /* We initialize the VM-specific members. */ + workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws; + vm_ws->sub_ws = sub_ws; + vm_ws->current_state = SURF_VM_STATE_CREATED; + + + + // //// CPU RELATED STUFF //// + // Roughly, create a vcpu resource by using the values of the sub_cpu one. + cpu_Cas01_t sub_cpu = surf_cpu_resource_priv(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, + SURF_RESOURCE_ON, // host->initial_state, + NULL, // host->state_trace, + NULL, // host->properties, + surf_cpu_model_vm); + + + + /* We create cpu_action corresponding to a VM process on the host operating system. */ + /* 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: + * - 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, void *ind_dst_pm) +{ + /* ind_phys_workstation equals to smx_host_t */ + 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); + + /* do something */ + + /* 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; + + /* 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); +} + +/* + * A physical host does not disapper in the current SimGrid code, but a VM may + * disapper during a simulation. + */ +static void vm_ws_destroy(void *ind_vm_workstation) +{ + /* ind_phys_workstation equals to smx_host_t */ + + /* Before clearing the entries in host_lib, we have to pick up resources. */ + 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_assert(vm_ws); + xbt_assert(vm_ws->ws.generic_resource.model == surf_vm_workstation_model); + + + /* We deregister objects from host_lib, without invoking the freeing callback + * of each level. + * + * 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_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); + xbt_assert(ret == 1, "Bug: some resource still remains"); + + /* Free the cpu resource of the VM. If using power_trace, we will have to + * 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. */ + // Nothing has to be done, because net_elmts is just a pointer on the physical one + + /* Free the storage resource of the VM. */ + // Not relevant yet + + /* Free the workstation resource of the VM. */ + surf_resource_free(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_suspend(void *ind_vm_ws) +{ + workstation_VM2013_t vm_ws = surf_workstation_resource_priv(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; +} + +static double get_solved_value(surf_action_t cpu_action) +{ + lmm_variable_t var = ((surf_action_lmm_t) cpu_action)->variable; + + 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. */ + { + unsigned int index_of_pm_ws_model = xbt_dynar_search(model_list_invoke, &surf_workstation_model); + unsigned int index_of_vm_ws_model = xbt_dynar_search(model_list_invoke, &surf_vm_workstation_model); + xbt_assert((index_of_pm_ws_model < index_of_vm_ws_model), "Cannot assume surf_workstation_model comes before"); + + /* Another option is that we call sub_ws->share_resource() here. The + * share_resource() function has no side-effect. We can call it here to + * ensure that. */ + } + + + /* 1. Now we know how many resource should be assigned to each virtual + * machine. We update constraints of the virtual machine layer. + * + * + * If we have two virtual machine (VM1 and VM2) on a physical machine (PM1). + * X1 + X2 = C (Equation 1) + * where + * the resource share of VM1: X1 + * the resource share of VM2: X2 + * the capacity of PM1: C + * + * Then, if we have two process (P1 and P2) on VM1. + * X1_1 + X1_2 = X1 (Equation 2) + * where + * the resource share of P1: X1_1 + * the resource share of P2: X1_2 + * the capacity of VM1: X1 + * + * Equation 1 was solved in the physical machine layer. + * Equation 2 is solved in the virtual machine layer (here). + * X1 must be passed to the virtual machine laye as a constraint value. + * + **/ + + /* iterate for all hosts including virtual machines */ + xbt_lib_cursor_t cursor; + char *key; + void **ind_host; + xbt_lib_foreach(host_lib, cursor, key, ind_host) { + workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL]; + cpu_Cas01_t cpu_cas01 = ind_host[SURF_CPU_LEVEL]; + + 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"); + + /* It is a virtual machine, so we can cast it to workstation_VM2013_t */ + workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03; + + double solved_value = get_solved_value(ws_vm2013->cpu_action); + XBT_DEBUG("assign %f to vm %s @ pm %s", solved_value, + ws_clm03->generic_resource.name, ws_vm2013->sub_ws->generic_resource.name); + + // 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); + } + + + /* 2. Calculate resource share at the virtual machine layer. */ + double ret = ws_share_resources(workstation_model, now); + + + /* FIXME: 3. do we have to re-initialize our cpu_action object? */ +#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]; + + /* skip if it is not a virtual machine */ + if (!ws_clm03) + continue; + if (ws_clm03->generic_resource.model != surf_vm_workstation_model) + continue; + + /* It is a virtual machine, so we can cast it to workstation_VM2013_t */ + { +#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); + ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, 0); +#endif + + } + } +#endif + + + return ret; +} + + +/* + * A surf level object will be useless in the upper layer. Returing the + * dict_elm of the host. + **/ +static void *vm_ws_get_pm(void *ind_vm_ws) +{ + workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws); + 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. */ +static 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_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); + + 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); +} + + +/* 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(); + + model->name = "Virtual Workstation"; + model->type = SURF_MODEL_TYPE_VM_WORKSTATION; + + model->action_unref = ws_action_unref; + model->action_cancel = vm_ws_action_cancel; + // model->action_state_set = ws_action_state_set; + + + model->model_private->share_resources = vm_ws_share_resources; + model->model_private->resource_used = ws_resource_used; + model->model_private->update_actions_state = ws_update_actions_state; + model->model_private->update_resource_state = ws_update_resource_state; + model->model_private->finalize = ws_finalize; + + + /* 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; + 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; +// #ifdef HAVE_LATENCY_BOUND_TRACKING +// model->get_latency_limited = ws_get_latency_limited; +// #endif + + + + + + + + xbt_assert(surf_cpu_model_vm); + model->extension.workstation.cpu_model = surf_cpu_model_vm; + + 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.workstation.communicate = ws_communicate; + // model->extension.workstation.get_route = ws_get_route; + // model->extension.workstation.execute_parallel_task = ws_execute_parallel_task; + // model->extension.workstation.get_link_bandwidth = ws_get_link_bandwidth; + // model->extension.workstation.get_link_latency = ws_get_link_latency; + // model->extension.workstation.link_shared = ws_link_shared; + // model->extension.workstation.get_properties = ws_get_properties; + + // model->extension.workstation.open = ws_action_open; + // model->extension.workstation.close = ws_action_close; + // model->extension.workstation.read = ws_action_read; + // model->extension.workstation.write = ws_action_write; + // model->extension.workstation.stat = ws_action_stat; + // model->extension.workstation.unlink = ws_action_unlink; + // model->extension.workstation.ls = ws_action_ls; + + + model->extension.vm_workstation.create = vm_ws_create; + 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.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; +} + +void surf_vm_workstation_model_init(void) +{ + surf_vm_workstation_model_init_internal(); + xbt_dynar_push(model_list, &surf_vm_workstation_model); + xbt_dynar_push(model_list_invoke, &surf_vm_workstation_model); +} diff --cc src/surf/workstation.c index 8dce18f661,f50cf05b3d..452e269c5d --- a/src/surf/workstation.c +++ b/src/surf/workstation.c @@@ -21,20 -23,22 +21,20 @@@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_wo surf_model_t surf_workstation_model = NULL; + static void workstation_new(sg_platf_host_cbarg_t host) { - workstation_CLM03_t workstation = xbt_new0(s_workstation_CLM03_t, 1); + const char *name = host->id; - workstation->generic_resource.model = surf_workstation_model; - workstation->generic_resource.name = xbt_strdup(host->id); - workstation->storage = xbt_lib_get_or_null(storage_lib,host->id,ROUTING_STORAGE_HOST_LEVEL); - workstation->net_elm = xbt_lib_get_or_null(host_lib,host->id,ROUTING_HOST_LEVEL); - XBT_DEBUG("Create workstation %s with %ld mounted disks",host->id,xbt_dynar_length(workstation->storage)); - xbt_lib_set(host_lib, host->id, SURF_WKS_LEVEL, workstation); -} + /* NOTE: The properties object is NULL, because the current code uses that of + * that of a cpu resource. */ - workstation_CLM03_t ws = (workstation_CLM03_t) surf_resource_new(sizeof(s_workstation_CLM03_t), surf_workstation_model, name, NULL); ++ workstation_CLM03_t ws = (workstation_CLM03_t) surf_resource_new(sizeof(s_workstation_CLM03_t), surf_workstation_model, name, NULL, NULL); -static int ws_resource_used(void *resource_id) -{ - THROW_IMPOSSIBLE; /* This model does not implement parallel tasks */ - return -1; + ws->storage = xbt_lib_get_or_null(storage_lib, name, ROUTING_STORAGE_HOST_LEVEL); + ws->net_elm = xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL); + + XBT_DEBUG("Create ws %s with %ld mounted disks", name, xbt_dynar_length(ws->storage)); + xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, ws); } static void ws_parallel_action_cancel(surf_action_t action) @@@ -371,35 -215,63 +371,71 @@@ static surf_action_t ws_communicate(voi dst->net_elm, size, rate); } -static e_surf_resource_state_t ws_get_state(void *workstation) +e_surf_resource_state_t ws_get_state(void *workstation) { - return surf_cpu_model->extension.cpu. - get_state(workstation); + surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); + return cpu->model->extension.cpu.get_state(workstation); } -static double ws_get_speed(void *workstation, double load) +static void ws_set_state(void *workstation, e_surf_resource_state_t state) { - return surf_cpu_model->extension.cpu. - get_speed(workstation, load); + surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); + cpu->model->extension.cpu.set_state(workstation, state); } -static int ws_get_core(void *workstation) +double ws_get_speed(void *workstation, double load) { - return surf_cpu_model->extension.cpu. - get_core(workstation); + surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); + return cpu->model->extension.cpu.get_speed(workstation, load); } - - +static int ws_get_core(void *workstation) +{ + surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); + return cpu->model->extension.cpu.get_core(workstation); +} static double ws_get_available_speed(void *workstation) { - return surf_cpu_model->extension.cpu. - get_available_speed(workstation); + surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); + return cpu->model->extension.cpu.get_available_speed(workstation); } + static double ws_get_current_power_peak(void *workstation) + { - return surf_cpu_model->extension.cpu. ++ surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); ++ return cpu->model->extension.cpu. + get_current_power_peak(workstation); + } + + static double ws_get_power_peak_at(void *workstation, int pstate_index) + { - return surf_cpu_model->extension.cpu. ++ surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); ++ return cpu->model->extension.cpu. + get_power_peak_at(workstation, pstate_index); + } + + static int ws_get_nb_pstates(void *workstation) + { - return surf_cpu_model->extension.cpu. ++ surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); ++ return cpu->model->extension.cpu. + get_nb_pstates(workstation); + } + + static void ws_set_power_peak_at(void *workstation, int pstate_index) + { - surf_cpu_model->extension.cpu. ++ surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); ++ cpu->model->extension.cpu. + set_power_peak_at(workstation, pstate_index); + } + + static double ws_get_consumed_energy(void *workstation) + { - return surf_cpu_model->extension.cpu. ++ surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation)); ++ return cpu->model->extension.cpu. + get_consumed_energy(workstation); + } + + static surf_action_t ws_execute_parallel_task(int workstation_nb, void **workstation_list, double *computation_amount, @@@ -565,116 -458,108 +616,153 @@@ static sg_storage_size_t ws_file_get_si return fd->size; } + static xbt_dynar_t ws_file_get_info(void *workstation, surf_file_t fd) + { + storage_t st = find_storage_on_mount_list(workstation, fd->mount); + sg_storage_size_t *psize = xbt_new(sg_storage_size_t, 1); + *psize = fd->size; + xbt_dynar_t info = xbt_dynar_new(sizeof(void*), NULL); + xbt_dynar_push_as(info, sg_storage_size_t *, psize); + xbt_dynar_push_as(info, void *, fd->mount); + xbt_dynar_push_as(info, void *, st->generic_resource.name); + xbt_dynar_push_as(info, void *, st->type_id); + xbt_dynar_push_as(info, void *, st->content_type); + + return info; + } + + static sg_storage_size_t ws_storage_get_free_size(void *workstation,const char* name) + { + storage_t st = find_storage_on_mount_list(workstation, name); + return st->size - st->used_size; + } + + static sg_storage_size_t ws_storage_get_used_size(void *workstation,const char* name) + { + storage_t st = find_storage_on_mount_list(workstation, name); + return st->used_size; + } + -static void surf_workstation_model_init_internal(void) +void ws_get_params(void *ws, ws_params_t params) { - surf_workstation_model = surf_model_init(); - - surf_workstation_model->name = "Workstation"; - surf_workstation_model->action_unref = ws_action_unref; - surf_workstation_model->action_cancel = ws_action_cancel; - surf_workstation_model->action_state_set = ws_action_state_set; - - surf_workstation_model->model_private->resource_used = ws_resource_used; - surf_workstation_model->model_private->share_resources = - ws_share_resources; - surf_workstation_model->model_private->update_actions_state = - ws_update_actions_state; - surf_workstation_model->model_private->update_resource_state = - ws_update_resource_state; - surf_workstation_model->model_private->finalize = ws_finalize; - - surf_workstation_model->suspend = ws_action_suspend; - surf_workstation_model->resume = ws_action_resume; - surf_workstation_model->is_suspended = ws_action_is_suspended; - surf_workstation_model->set_max_duration = ws_action_set_max_duration; - surf_workstation_model->set_priority = ws_action_set_priority; -#ifdef HAVE_TRACING - surf_workstation_model->set_category = ws_action_set_category; -#endif - surf_workstation_model->get_remains = ws_action_get_remains; -#ifdef HAVE_LATENCY_BOUND_TRACKING - surf_workstation_model->get_latency_limited = ws_get_latency_limited; -#endif + workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws); + memcpy(params, &ws_clm03->params, sizeof(s_ws_params_t)); +} + +void ws_set_params(void *ws, ws_params_t params) +{ + workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws); + /* may check something here. */ + memcpy(&ws_clm03->params, params, sizeof(s_ws_params_t)); +} + +static xbt_dynar_t ws_get_vms(void *pm) +{ + xbt_dynar_t dyn = xbt_dynar_new(sizeof(smx_host_t), NULL); + + /* iterate for all hosts including virtual machines */ + xbt_lib_cursor_t cursor; + char *key; + void **ind_host; + xbt_lib_foreach(host_lib, cursor, key, ind_host) { + workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL]; + if (!ws_clm03) + continue; + /* skip if it is not a virtual machine */ + if (ws_clm03->generic_resource.model != surf_vm_workstation_model) + 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; + if (pm == ws_vm2013->sub_ws) + xbt_dynar_push(dyn, &ws_vm2013->sub_ws); + } + + return dyn; +} + - surf_workstation_model->extension.workstation.execute = ws_execute; - surf_workstation_model->extension.workstation.sleep = ws_action_sleep; - surf_workstation_model->extension.workstation.get_state = ws_get_state; - surf_workstation_model->extension.workstation.get_core = ws_get_core; - surf_workstation_model->extension.workstation.get_speed = ws_get_speed; - surf_workstation_model->extension.workstation.get_available_speed = +static void surf_workstation_model_init_internal(void) +{ + surf_model_t model = surf_model_init(); + + model->name = "Workstation"; + model->type = SURF_MODEL_TYPE_WORKSTATION; + model->action_unref = ws_action_unref; + model->action_cancel = ws_action_cancel; + model->action_state_set = ws_action_state_set; + + model->model_private->resource_used = ws_resource_used; + model->model_private->share_resources = ws_share_resources; + model->model_private->update_actions_state = ws_update_actions_state; + model->model_private->update_resource_state = ws_update_resource_state; + model->model_private->finalize = ws_finalize; + + 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; + 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; + #ifdef HAVE_LATENCY_BOUND_TRACKING + model->get_latency_limited = ws_get_latency_limited; + #endif + + /* For VM support, we have a surf cpu model object for each workstation model + * object. The physical workstation model object has the cpu model object of + * the physical machine layer. */ + xbt_assert(surf_cpu_model_pm); + model->extension.workstation.cpu_model = surf_cpu_model_pm; + + model->extension.workstation.execute = ws_execute; + model->extension.workstation.sleep = ws_action_sleep; + model->extension.workstation.get_state = ws_get_state; + model->extension.workstation.set_state = ws_set_state; + model->extension.workstation.get_core = ws_get_core; + model->extension.workstation.get_speed = ws_get_speed; + model->extension.workstation.get_available_speed = ws_get_available_speed; - surf_workstation_model->extension.workstation.get_current_power_peak = ws_get_current_power_peak; - surf_workstation_model->extension.workstation.get_power_peak_at = ws_get_power_peak_at; - surf_workstation_model->extension.workstation.get_nb_pstates = ws_get_nb_pstates; - surf_workstation_model->extension.workstation.set_power_peak_at = ws_set_power_peak_at; - surf_workstation_model->extension.workstation.get_consumed_energy = ws_get_consumed_energy; -- - model->extension.workstation.communicate = ws_communicate; - model->extension.workstation.get_route = ws_get_route; - surf_workstation_model->extension.workstation.communicate = - ws_communicate; - surf_workstation_model->extension.workstation.get_route = ws_get_route; - surf_workstation_model->extension.workstation.execute_parallel_task = - ws_execute_parallel_task; - surf_workstation_model->extension.workstation.get_link_bandwidth = - ws_get_link_bandwidth; - surf_workstation_model->extension.workstation.get_link_latency = - ws_get_link_latency; - surf_workstation_model->extension.workstation.link_shared = - ws_link_shared; - surf_workstation_model->extension.workstation.get_properties = - ws_get_properties; - - surf_workstation_model->extension.workstation.open = ws_action_open; - surf_workstation_model->extension.workstation.close = ws_action_close; - surf_workstation_model->extension.workstation.read = ws_action_read; - surf_workstation_model->extension.workstation.write = ws_action_write; - surf_workstation_model->extension.workstation.unlink = ws_file_unlink; - surf_workstation_model->extension.workstation.ls = ws_action_ls; - surf_workstation_model->extension.workstation.get_size = ws_file_get_size; - surf_workstation_model->extension.workstation.get_info = ws_file_get_info; - surf_workstation_model->extension.workstation.get_free_size = ws_storage_get_free_size; - surf_workstation_model->extension.workstation.get_used_size = ws_storage_get_used_size; - surf_workstation_model->extension.workstation.get_storage_list = ws_get_storage_list; ++ model->extension.workstation.get_current_power_peak = ws_get_current_power_peak; ++ model->extension.workstation.get_power_peak_at = ws_get_power_peak_at; ++ model->extension.workstation.get_nb_pstates = ws_get_nb_pstates; ++ model->extension.workstation.set_power_peak_at = ws_set_power_peak_at; ++ model->extension.workstation.get_consumed_energy = ws_get_consumed_energy; ++ ++ model->extension.workstation.communicate = ws_communicate; ++ model->extension.workstation.get_route = ws_get_route; + model->extension.workstation.execute_parallel_task = ws_execute_parallel_task; - model->extension.workstation.get_link_bandwidth = ws_get_link_bandwidth; - model->extension.workstation.get_link_latency = ws_get_link_latency; - model->extension.workstation.link_shared = ws_link_shared; - model->extension.workstation.get_properties = ws_get_properties; - - model->extension.workstation.open = ws_action_open; - model->extension.workstation.close = ws_action_close; - model->extension.workstation.read = ws_action_read; - model->extension.workstation.write = ws_action_write; ++ model->extension.workstation.get_link_bandwidth = ws_get_link_bandwidth; ++ model->extension.workstation.get_link_latency = ws_get_link_latency; ++ model->extension.workstation.link_shared = ws_link_shared; ++ model->extension.workstation.get_properties = ws_get_properties; ++ ++ model->extension.workstation.open = ws_action_open; ++ model->extension.workstation.close = ws_action_close; ++ model->extension.workstation.read = ws_action_read; ++ model->extension.workstation.write = ws_action_write; + model->extension.workstation.unlink = ws_file_unlink; - model->extension.workstation.ls = ws_action_ls; ++ model->extension.workstation.ls = ws_action_ls; ++ model->extension.workstation.get_size = ws_file_get_size; ++ model->extension.workstation.get_info = ws_file_get_info; ++ model->extension.workstation.get_free_size = ws_storage_get_free_size; ++ model->extension.workstation.get_used_size = ws_storage_get_used_size; ++ model->extension.workstation.get_storage_list = ws_get_storage_list; + + model->extension.workstation.get_params = ws_get_params; + model->extension.workstation.set_params = ws_set_params; + model->extension.workstation.get_vms = ws_get_vms; + + surf_workstation_model = model; } void surf_workstation_model_init_current_default(void) { - xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", xbt_strdup("yes")); - surf_workstation_model_init_internal(); + xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", "yes"); surf_cpu_model_init_Cas01(); surf_network_model_init_LegrandVelho();