<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<?fileVersion 5.0.0?>
--
--<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage2">
++<?fileVersion 5.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage2">
<storageModule moduleId="org.eclipse.cdt.core.settings">
- <cconfiguration id="0.1454192080">
- <storageModule externalCElementFile="0.1454192080_org.eclipse.cdt.core.settings" id="0.1454192080" name="Default"/>
- <storageModule externalCElementFile="0.1454192080_cdtBuildSystem" version="4.0.0"/>
- <storageModule externalCElementFile="0.1454192080_org.eclipse.cdt.core.externalSettings"/>
- <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1353180652">
- <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1353180652_org.eclipse.cdt.core.settings" id="cdt.managedbuild.toolchain.gnu.base.1353180652" name="Default"/>
- <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1353180652_cdtBuildSystem" version="4.0.0"/>
- <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1353180652_org.eclipse.cdt.core.externalSettings"/>
++ <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1053321950">
++ <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1053321950_org.eclipse.cdt.core.settings" id="cdt.managedbuild.toolchain.gnu.base.1053321950" name="Default"/>
++ <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1053321950_cdtBuildSystem" version="4.0.0"/>
++ <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1053321950_org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
- <storageModule moduleId="org.eclipse.cdt.core.pathentry">
- <pathentry kind="mac" name="main" path="" value="smpi_simulated_main"/>
- <pathentry include="/usr/include/lua5.1" kind="inc" path="" system="true"/>
- <pathentry include="/usr/include" kind="inc" path="" system="true"/>
- <pathentry base-path="simgrid" include="include" kind="inc" path="" system="true"/>
- <pathentry base-path="simgrid" include="src/include" kind="inc" path="" system="true"/>
- <pathentry base-path="simgrid" include="src" kind="inc" path="" system="true"/>
- <pathentry excluding="**/CMakeFiles/" kind="out" path=""/>
- <pathentry kind="src" path=""/>
- </storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
- <project id="simgrid.null.1424519849" name="simgrid"/>
- <project id="simgrid.null.697056024" name="simgrid"/>
++ <project id="simgrid.null.1652888656" name="simgrid"/>
+ </storageModule>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
- <scannerConfigBuildInfo instanceId="0.1454192080">
- <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
- </scannerConfigBuildInfo>
+ </storageModule>
++ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="refreshScope" versionNumber="2">
+ <configuration configurationName="Default">
+ <resource resourceType="PROJECT" workspacePath="/simgrid"/>
+ </configuration>
</storageModule>
- <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
- <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
- <storageModule moduleId="scannerConfiguration">
- <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
- <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
- <buildOutputProvider>
- <openAction enabled="true" filePath=""/>
- <parser enabled="true"/>
- </buildOutputProvider>
- <scannerInfoProvider id="specsFile">
- <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="/usr/bin/gcc" useDefault="true"/>
- <parser enabled="true"/>
- </scannerInfoProvider>
- </profile>
- <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
- <buildOutputProvider>
- <openAction enabled="true" filePath=""/>
- <parser enabled="true"/>
- </buildOutputProvider>
- <scannerInfoProvider id="makefileGenerator">
- <runAction arguments="-f ${project_name}_scd.mk" command="/usr/bin/make" useDefault="true"/>
- <parser enabled="true"/>
- </scannerInfoProvider>
- </profile>
- <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1353180652;cdt.managedbuild.toolchain.gnu.base.1353180652.1797514135;cdt.managedbuild.tool.gnu.c.compiler.base.2037544368;cdt.managedbuild.tool.gnu.c.compiler.input.1851803849">
- <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
- <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
- <buildOutputProvider>
- <openAction enabled="true" filePath=""/>
- <parser enabled="true"/>
- </buildOutputProvider>
- <scannerInfoProvider id="specsFile">
- <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="/usr/bin/gcc" useDefault="true"/>
- <parser enabled="true"/>
- </scannerInfoProvider>
- </profile>
- <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
- <buildOutputProvider>
- <openAction enabled="true" filePath=""/>
- <parser enabled="true"/>
- </buildOutputProvider>
- <scannerInfoProvider id="makefileGenerator">
- <runAction arguments="-f ${project_name}_scd.mk" command="/usr/bin/make" useDefault="true"/>
- <parser enabled="true"/>
- </scannerInfoProvider>
- </profile>
- </scannerConfigBuildInfo>
- <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1353180652;cdt.managedbuild.toolchain.gnu.base.1353180652.1797514135;cdt.managedbuild.tool.gnu.cpp.compiler.base.1129818443;cdt.managedbuild.tool.gnu.cpp.compiler.input.500761747">
- <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
- <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
- <buildOutputProvider>
- <openAction enabled="true" filePath=""/>
- <parser enabled="true"/>
- </buildOutputProvider>
- <scannerInfoProvider id="specsFile">
- <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="/usr/bin/gcc" useDefault="true"/>
- <parser enabled="true"/>
- </scannerInfoProvider>
- </profile>
- <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
- <buildOutputProvider>
- <openAction enabled="true" filePath=""/>
- <parser enabled="true"/>
- </buildOutputProvider>
- <scannerInfoProvider id="makefileGenerator">
- <runAction arguments="-f ${project_name}_scd.mk" command="/usr/bin/make" useDefault="true"/>
- <parser enabled="true"/>
- </scannerInfoProvider>
- </profile>
- </scannerConfigBuildInfo>
- </storageModule>
</cproject>
--- /dev/null
- <name>simgrid</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
- <triggers>clean,full,incremental,</triggers>
- <arguments>
- <dictionary>
- <key>?name?</key>
- <value></value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.append_environment</key>
- <value>true</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.autoBuildTarget</key>
- <value>all</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.buildArguments</key>
- <value></value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.buildCommand</key>
- <value>make</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
- <value>clean</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.contents</key>
- <value>org.eclipse.cdt.make.core.activeConfigSettings</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.enableAutoBuild</key>
- <value>false</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.enableCleanBuild</key>
- <value>true</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.enableFullBuild</key>
- <value>true</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.fullBuildTarget</key>
- <value>all</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.stopOnError</key>
- <value>true</value>
- </dictionary>
- <dictionary>
- <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
- <value>true</value>
- </dictionary>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.rubypeople.rdt.core.rubybuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
- <triggers>full,incremental,</triggers>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.cdt.core.ccnature</nature>
- <nature>org.eclipse.cdt.core.cnature</nature>
- <nature>org.rubypeople.rdt.core.rubynature</nature>
- <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
- <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
+ <?xml version="1.0" encoding="UTF-8"?>
+ <projectDescription>
++ <name>simgrid</name>
++ <comment></comment>
++ <projects>
++ </projects>
++ <buildSpec>
++ <buildCommand>
++ <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
++ <triggers>clean,full,incremental,</triggers>
++ <arguments>
++ </arguments>
++ </buildCommand>
++ <buildCommand>
++ <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
++ <triggers>full,incremental,</triggers>
++ <arguments>
++ </arguments>
++ </buildCommand>
++ </buildSpec>
++ <natures>
++ <nature>org.eclipse.cdt.core.cnature</nature>
++ <nature>org.eclipse.cdt.core.ccnature</nature>
++ <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
++ <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
++ </natures>
+ </projectDescription>
--- /dev/null
- 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));
+/* 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 <stdio.h>
+#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_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);
+}
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,
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,
#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 **********************************/
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 */
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,
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 */
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
/*
- * 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
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 */
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
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
*/
* \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 *************************/
/*******************************************/
#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
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;
+ }
#endif
msg_host_t __MSG_host_create(smx_host_t workstation);
-void __MSG_host_destroy(msg_host_priv_t host);
+ msg_storage_t __MSG_storage_create(smx_storage_t storage);
+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,
smx_process_arg_t arg = NULL;
smx_process_t process_created = NULL;
- arg->name = (char*)(arg->argv)[0];
+ 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; i<process->argc; i++)
+ arg->argv[i] = xbt_strdup(process->argv[i]);
++ 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];
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();
/* 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.
*
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);
}
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);
}
}
#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);
+ }
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,
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);
- /* 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
#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)) 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_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 \
* \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!");
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
#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,
"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;
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,
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)
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
if (tmgr_trace_event_free(event_type))
cpu->power_event = NULL;
} else if (event_type == cpu->state_event) {
- if (value > 0)
+ /* 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(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;
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 =
return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_scale;
}
-static void cpu_finalize(void)
+ 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(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;
} 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;
}
/*********************************************************************/
--
-/* 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
#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;
tmgr_trace_event_t state_event;
lmm_constraint_t constraint;
- energy_cpu_cas01_t energy; /*< Structure with energy-consumption data */
+ 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;
++
+ /* Note (hypervisor): */
+ lmm_constraint_t *constraint_core;
} s_cpu_Cas01_t, *cpu_Cas01_t;
- double 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,
+ 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 */
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;
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;
{
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)
{
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);
- }
return action->remains;
}
- if(model == surf_cpu_model){
+ /**
+ * Update the CPU total energy for a finished action
+ *
+ */
+ void update_resource_energy(surf_model_t model, surf_action_lmm_t action)
+ {
++ 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;
}
#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;
--- /dev/null
- surf_vm_workstation_model, name, NULL);
+/* 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),
- sub_cpu->power_peak, // host->power_peak,
++ 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_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);
+}
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)
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);
}
- return surf_cpu_model->extension.cpu.
+ 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)
+ {
- 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)
+ {
- return 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)
+ {
++ 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,
return fd->size;
}
-static void surf_workstation_model_init_internal(void)
+ 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;
+ }
+
+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();