Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'hypervisor' into surf++
authorPaul Bédaride <paul.bedaride@gmail.com>
Fri, 15 Nov 2013 13:06:27 +0000 (14:06 +0100)
committerPaul Bédaride <paul.bedaride@gmail.com>
Fri, 15 Nov 2013 13:06:27 +0000 (14:06 +0100)
Conflicts:
.cproject
buildtools/Cmake/DefinePackages.cmake
src/include/surf/surf.h
src/simix/smx_global.c
src/simix/smx_host.c
src/simix/smx_host_private.h
src/simix/smx_io.c
src/simix/smx_network.c
src/simix/smx_new_api.c
src/simix/smx_process.c
src/simix/smx_smurf_private.h
src/simix/smx_synchro.c
src/surf/cpu_cas01.c
src/surf/cpu_cas01_private.h
src/surf/cpu_ti.c
src/surf/network.c
src/surf/network_constant.c
src/surf/network_gtnets.c
src/surf/new_model.c
src/surf/storage.c
src/surf/surf.c
src/surf/surf_action.c
src/surf/surf_private.h
src/surf/workstation.c
testsuite/surf/surf_usage.c

26 files changed:
1  2 
buildtools/Cmake/DefinePackages.cmake
include/msg/datatypes.h
include/simgrid/simix.h
src/include/surf/maxmin.h
src/include/surf/surf.h
src/simdag/sd_global.c
src/simgrid/sg_config.c
src/simix/smx_global.c
src/simix/smx_host.c
src/simix/smx_host_private.h
src/simix/smx_process.c
src/simix/smx_smurf_private.h
src/simix/smx_synchro.c
src/simix/smx_vm.c
src/surf/cpu.cpp
src/surf/cpu.hpp
src/surf/cpu_cas01.cpp
src/surf/cpu_ti.cpp
src/surf/surf.cpp
src/surf/surf.hpp
src/surf/surf_interface.cpp
src/surf/workstation.cpp
src/surf/workstation.hpp
src/surf/workstation_ptask_L07.cpp
src/surf/workstation_ptask_L07.hpp
testsuite/surf/surf_usage.c

@@@ -35,26 -35,20 +35,26 @@@ set(EXTRA_DIS
    src/simix/smx_smurf_private.h
    src/simix/smx_synchro_private.h
    src/smpi/README
 +  src/smpi/colls/COPYRIGHTS
    src/smpi/colls/colls.h
    src/smpi/colls/colls_private.h
    src/smpi/colls/coll_tuned_topo.h
    src/smpi/private.h
    src/smpi/smpi_mpi_dt_private.h
 -  src/surf/cpu_cas01_private.h
 +  src/surf/cpu.hpp
 +  src/surf/cpu_ti.hpp
 +  src/surf/cpu_cas01.hpp
    src/surf/cpu_ti_private.h
    src/surf/gtnets/gtnets_interface.h
    src/surf/gtnets/gtnets_simulator.h
    src/surf/gtnets/gtnets_topology.h
    src/surf/maxmin_private.h
 -  src/surf/network_gtnets_private.h
 +  src/surf/network_gtnets.hpp
    src/surf/network_ns3_private.h
    src/surf/network_private.h
 +  src/surf/network.hpp
 +  src/surf/network_smpi.hpp
 +  src/surf/network_constant.hpp
    src/surf/ns3/my-point-to-point-helper.h
    src/surf/ns3/ns3_interface.h
    src/surf/ns3/ns3_simulator.h
    src/surf/platf_generator_private.h
    src/surf/simgrid.dtd
    src/surf/simgrid_dtd.c
 +  src/surf/storage.hpp
    src/surf/storage_private.h
 +  src/surf/surf.hpp
    src/surf/surf_private.h
    src/surf/surf_routing_private.h
 +  src/surf/surf_routing_private.hpp
 +  src/surf/surf_routing.hpp
 +  src/surf/surf_routing_cluster.hpp
 +  src/surf/surf_routing_dijkstra.hpp
 +  src/surf/surf_routing_floyd.hpp
 +  src/surf/surf_routing_full.hpp
 +  src/surf/surf_routing_generic.hpp
 +  src/surf/surf_routing_none.hpp
 +  src/surf/surf_routing_vivaldi.hpp
    src/surf/surfxml_parse.c
    src/surf/trace_mgr_private.h
 +  src/surf/workstation.hpp
 +  src/surf/workstation_ptask_L07.hpp
    src/win32/config.h
    src/xbt/automaton/automaton_lexer.yy.c
    src/xbt/automaton/parserPromela.lex
@@@ -286,7 -267,7 +286,7 @@@ set(GTNETS_SR
    src/surf/gtnets/gtnets_interface.cc
    src/surf/gtnets/gtnets_simulator.cc
    src/surf/gtnets/gtnets_topology.cc
 -  src/surf/network_gtnets.c
 +  src/surf/network_gtnets.cpp
    )
  
  set(NS3_SRC
    )
  
  set(SURF_SRC
 -  src/surf/cpu_cas01.c
 -  src/surf/cpu_ti.c
 +  src/surf/cpu.cpp
 +  src/surf/cpu_ti.cpp
 +  src/surf/cpu_cas01.cpp
    src/surf/fair_bottleneck.c
    src/surf/instr_routing.c
    src/surf/instr_surf.c
    src/surf/lagrange.c
    src/surf/maxmin.c
 -  src/surf/network.c
 -  src/surf/network_constant.c
 +  src/surf/network.cpp
 +  src/surf/network_smpi.cpp  
 +  src/surf/network_constant.cpp
    src/surf/platf_generator.c
    src/surf/random_mgr.c
    src/surf/sg_platf.c
 -  src/surf/storage.c
 -  src/surf/surf.c
 -  src/surf/surf_action.c
 -  src/surf/surf_model.c
 -  src/surf/surf_routing.c
 -  src/surf/surf_routing_cluster.c
 -  src/surf/surf_routing_dijkstra.c
 -  src/surf/surf_routing_floyd.c
 -  src/surf/surf_routing_full.c
 -  src/surf/surf_routing_generic.c
 -  src/surf/surf_routing_none.c
 -  src/surf/surf_routing_vivaldi.c
 +  src/surf/storage.cpp
 +  src/surf/surf.cpp
 +  src/surf/surf_interface.cpp
 +  src/surf/surf_routing.cpp  
 +  src/surf/surf_routing_cluster.cpp
 +  src/surf/surf_routing_dijkstra.cpp
 +  src/surf/surf_routing_floyd.cpp
 +  src/surf/surf_routing_full.cpp
 +  src/surf/surf_routing_generic.cpp
 +  src/surf/surf_routing_none.cpp
 +  src/surf/surf_routing_vivaldi.cpp
    src/surf/surfxml_parse.c
    src/surf/surfxml_parseplatf.c
    src/surf/trace_mgr.c
 -  src/surf/workstation.c
 -  src/surf/workstation_ptask_L07.c
 -  src/surf/vm_workstation.c
 +  src/surf/workstation.cpp
 +  src/surf/workstation_ptask_L07.cpp
++  src/surf/vm_workstation.cpp
    src/xbt/xbt_sg_stubs.c
    )
  
@@@ -345,6 -326,7 +346,7 @@@ set(SIMIX_SR
    src/simix/smx_smurf.c
    src/simix/smx_synchro.c
    src/simix/smx_user.c
+   src/simix/smx_vm.c
    )
  
  set(SIMGRID_SRC
@@@ -386,17 -368,19 +388,6 @@@ set(SIMIX_SR
  )
  #* ****************************************************************************************** *#
  
--#* ****************************************************************************************** *#
--#* TUTORIAL: New Model                                                                        *#
--
--set(SURF_SRC
--  ${SURF_SRC}
 -  src/surf/new_model.c
--  )
--set(EXTRA_DIST
--  ${EXTRA_DIST}
 -  src/surf/new_model_private.h
--  )
--#* ****************************************************************************************** *#
--
  set(SIMDAG_SRC
    src/simdag/instr_sd_task.c
    src/simdag/sd_daxloader.c
diff --combined include/msg/datatypes.h
@@@ -28,7 -28,7 +28,7 @@@ SG_BEGIN_DECL(
  typedef struct s_smx_rvpoint *msg_mailbox_t;
  
  /* ******************************** Environment ************************************ */
 -typedef struct s_as *msg_as_t;
 +typedef struct As *msg_as_t;
  
  /* ******************************** Host ************************************ */
  
@@@ -48,7 -48,12 +48,12 @@@ typedef xbt_dictelm_t msg_host_t
  typedef s_xbt_dictelm_t s_msg_host_t;
  
  typedef struct msg_host_priv {
-   xbt_swag_t vms;
+   int        dp_enabled;
+   xbt_dict_t dp_objs;
+   double     dp_updated_by_deleted_tasks;
+   xbt_dict_t affinity_mask_db;
  #ifdef MSG_USE_DEPRECATED
    msg_mailbox_t *mailboxes;     /**< the channels  */
  #endif
@@@ -83,22 -88,13 +88,13 @@@ typedef struct msg_task 
   */
  typedef struct msg_task *msg_task_t;
  
- /* ********************************  VM ************************************* */
- typedef struct msg_vm *msg_vm_t;
- typedef enum {
-   msg_vm_state_suspended, msg_vm_state_running, msg_vm_state_migrating
- } e_msg_vm_state_t;
- typedef struct msg_vm {
-   char *name;
-   s_xbt_swag_hookup_t all_vms_hookup;
-   s_xbt_swag_hookup_t host_vms_hookup;
-   xbt_dynar_t processes;
-   e_msg_vm_state_t state;
-   msg_host_t location;
-   int coreAmount;
- } s_msg_vm_t;
+ /* ******************************** VM ************************************* */
+ typedef msg_host_t msg_vm_t;
+ typedef msg_host_priv_t msg_vm_priv_t;
+ static inline msg_vm_priv_t MSG_vm_priv(msg_vm_t vm){
 -  return xbt_lib_get_level(vm, MSG_HOST_LEVEL);
++  return (msg_vm_priv_t) xbt_lib_get_level(vm, MSG_HOST_LEVEL);
+ }
  
  /* ******************************** File ************************************ */
  typedef struct simdata_file *simdata_file_t;
diff --combined include/simgrid/simix.h
@@@ -14,6 -14,8 +14,7 @@@
  #include "xbt/parmap.h"
  #include "xbt/swag.h"
  #include "simgrid/platf.h"
 -
 -#include "simgrid/platf.h" // ws_params_t
++#include "surf/surf.h"
  
  SG_BEGIN_DECL()
  
@@@ -260,6 -262,8 +261,8 @@@ XBT_PUBLIC(smx_host_t) SIMIX_host_get_b
  XBT_PUBLIC(smx_host_t) SIMIX_host_self(void);
  XBT_PUBLIC(const char*) SIMIX_host_self_get_name(void);
  XBT_PUBLIC(const char*) SIMIX_host_get_name(smx_host_t host); /* FIXME: make private: only the name of SIMIX_host_self() should be public without request */
+ XBT_PUBLIC(void) SIMIX_host_on(smx_host_t host);
+ XBT_PUBLIC(void) SIMIX_host_off(smx_host_t host, smx_process_t issuer);
  XBT_PUBLIC(void) SIMIX_host_self_set_data(void *data);
  XBT_PUBLIC(void*) SIMIX_host_self_get_data(void);
  XBT_PUBLIC(void*) SIMIX_host_get_data(smx_host_t host);
@@@ -303,6 -307,8 +306,8 @@@ XBT_PUBLIC(void) SIMIX_file_set_data(sm
  XBT_PUBLIC(smx_host_t) simcall_host_get_by_name(const char *name);
  XBT_PUBLIC(const char *) simcall_host_get_name(smx_host_t host);
  XBT_PUBLIC(xbt_dict_t) simcall_host_get_properties(smx_host_t host);
+ XBT_PUBLIC(void) simcall_host_on(smx_host_t host);
+ XBT_PUBLIC(void) simcall_host_off(smx_host_t host);
  XBT_PUBLIC(int) simcall_host_get_core(smx_host_t host);
  XBT_PUBLIC(xbt_swag_t) simcall_host_get_process_list(smx_host_t host);
  XBT_PUBLIC(double) simcall_host_get_speed(smx_host_t host);
@@@ -321,7 -327,7 +326,7 @@@ XBT_PUBLIC(double) simcall_host_get_con
  
  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,
@@@ -334,8 -340,28 +339,28 @@@ XBT_PUBLIC(void) simcall_host_execution
  XBT_PUBLIC(double) simcall_host_execution_get_remains(smx_action_t execution);
  XBT_PUBLIC(e_smx_state_t) simcall_host_execution_get_state(smx_action_t execution);
  XBT_PUBLIC(void) simcall_host_execution_set_priority(smx_action_t execution, double priority);
+ XBT_PUBLIC(void) simcall_host_execution_set_bound(smx_action_t execution, double bound);
+ XBT_PUBLIC(void) simcall_host_execution_set_affinity(smx_action_t execution, smx_host_t host, unsigned long mask);
  XBT_PUBLIC(e_smx_state_t) simcall_host_execution_wait(smx_action_t execution);
  XBT_PUBLIC(xbt_dict_t) simcall_host_get_storage_list(smx_host_t host);
+ XBT_PUBLIC(void) simcall_host_get_params(smx_host_t vm, ws_params_t param);
+ XBT_PUBLIC(void) simcall_host_set_params(smx_host_t vm, ws_params_t param);
+ /******************************* VM simcalls ********************************/
+ // Create the vm_workstation at the SURF level
+ XBT_PUBLIC(void*) simcall_vm_create(const char *name, smx_host_t host);
+ XBT_PUBLIC(int) simcall_vm_get_state(smx_host_t vm);
+ XBT_PUBLIC(void) simcall_vm_start(smx_host_t vm);
+ XBT_PUBLIC(void) simcall_vm_migrate(smx_host_t vm, smx_host_t dst_pm);
+ XBT_PUBLIC(void *) simcall_vm_get_pm(smx_host_t vm);
+ XBT_PUBLIC(void) simcall_vm_set_bound(smx_host_t vm, double bound);
+ XBT_PUBLIC(void) simcall_vm_set_affinity(smx_host_t vm, smx_host_t pm, unsigned long mask);
+ XBT_PUBLIC(void) simcall_vm_resume(smx_host_t vm);
+ XBT_PUBLIC(void) simcall_vm_save(smx_host_t vm);
+ XBT_PUBLIC(void) simcall_vm_restore(smx_host_t vm);
+ XBT_PUBLIC(void) simcall_vm_suspend(smx_host_t vm);
+ XBT_PUBLIC(void) simcall_vm_destroy(smx_host_t vm);
+ XBT_PUBLIC(void) simcall_vm_shutdown(smx_host_t vm);
  
  /**************************** Process simcalls ********************************/
  /* Constructor and Destructor */
@@@ -31,10 -31,6 +31,10 @@@ static XBT_INLINE int double_equals(dou
    return (fabs(value1 - value2) < MAXMIN_PRECISION);
  }
  
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
  XBT_PUBLIC(lmm_system_t) lmm_system_new(int selective_update);
  XBT_PUBLIC(void) lmm_system_free(lmm_system_t sys);
  void lmm_variable_disable(lmm_system_t sys, lmm_variable_t var);
@@@ -56,6 -52,8 +56,8 @@@ XBT_PUBLIC(void) lmm_variable_free(lmm_
  XBT_PUBLIC(double) lmm_variable_getvalue(lmm_variable_t var);
  XBT_PUBLIC(double) lmm_variable_getbound(lmm_variable_t var);
  
+ XBT_PUBLIC(void) lmm_shrink(lmm_system_t sys, lmm_constraint_t cnst,
+                             lmm_variable_t var);
  XBT_PUBLIC(void) lmm_expand(lmm_system_t sys, lmm_constraint_t cnst,
                              lmm_variable_t var, double value);
  void lmm_expand_add(lmm_system_t sys, lmm_constraint_t cnst,
@@@ -132,8 -130,5 +134,8 @@@ XBT_PUBLIC(double func_vegas_f) (lmm_va
  XBT_PUBLIC(double func_vegas_fp) (lmm_variable_t var, double x);
  XBT_PUBLIC(double func_vegas_fpi) (lmm_variable_t var, double x);
  
 +#ifdef __cplusplus
 +}
 +#endif
  
  #endif                          /* _SURF_MAXMIN_H */
diff --combined src/include/surf/surf.h
@@@ -35,6 -35,7 +35,6 @@@ extern int sg_gtnets_jitter_seed
  #endif
  extern xbt_dynar_t surf_path;
  
 -
  typedef enum {
    SURF_NETWORK_ELEMENT_NULL = 0,        /* NULL */
    SURF_NETWORK_ELEMENT_HOST,    /* host type */
    SURF_NETWORK_ELEMENT_AS       /* AS type */
  } e_surf_network_element_type_t;
  
 +#ifdef __cplusplus
 +class Model;
 +class CpuModel;
 +class WorkstationModel;
++class WorkstationVMModel;
 +class NetworkCm02Model;
 +class StorageModel;
 +class Resource;
 +class ResourceLmm;
 +class WorkstationCLM03;
 +class NetworkCm02Link;
 +class Cpu;
 +class Action;
 +class ActionLmm;
 +class StorageActionLmm;
 +class As;
 +class RoutingEdge;
 +class RoutingPlatf;
 +#else
 +typedef struct Model Model;
 +typedef struct CpuModel CpuModel;
 +typedef struct WorkstationModel WorkstationModel;
++typedef struct WorkstationVMModel WorkstationVMModel;
 +typedef struct NetworkCm02Model NetworkCm02Model;
 +typedef struct StorageModel StorageModel;
 +typedef struct Resource Resource;
 +typedef struct ResourceLmm ResourceLmm;
 +typedef struct WorkstationCLM03 WorkstationCLM03;
 +typedef struct NetworkCm02Link NetworkCm02Link;
 +typedef struct Cpu Cpu;
 +typedef struct Action Action;
 +typedef struct ActionLmm ActionLmm;
 +typedef struct StorageActionLmm StorageActionLmm;
 +typedef struct As As;
 +typedef struct RoutingEdge RoutingEdge;
 +typedef struct RoutingPlatf RoutingPlatf;
 +#endif
 +
 +/** \ingroup SURF_models
 + *  \brief Model datatype
 + *
 + *  Generic data structure for a model. The workstations,
 + *  the CPUs and the network links are examples of models.
 + */
 +typedef Model *surf_model_t;
 +typedef CpuModel *surf_cpu_model_t;
 +typedef WorkstationModel *surf_workstation_model_t;
++typedef WorkstationVMModel *surf_vm_workstation_model_t;
++
 +typedef NetworkCm02Model *surf_network_model_t;
 +typedef StorageModel *surf_storage_model_t;
 +
 +typedef xbt_dictelm_t surf_resource_t;
 +typedef Resource *surf_cpp_resource_t;
 +typedef WorkstationCLM03 *surf_workstation_CLM03_t;
 +typedef NetworkCm02Link *surf_network_link_t;
 +typedef Cpu *surf_cpu_t;
 +
 +/** \ingroup SURF_actions
 + *  \brief Action structure
 + *
 + *  Never create s_surf_action_t by yourself ! The actions are created
 + *  on the fly when you call execute or communicate on a model.
 + *
 + *  \see e_surf_action_state_t
 + */
 +typedef Action *surf_action_t;
 +typedef ActionLmm *surf_action_lmm_t;
 +typedef StorageActionLmm *surf_storage_action_lmm_t;
 +
 +typedef As *AS_t;
 +typedef RoutingEdge *routing_edge_t;
 +typedef RoutingPlatf *routing_platf_t;
 +
 +typedef struct surf_file *surf_file_t;
 +
  XBT_PUBLIC(e_surf_network_element_type_t)
    routing_get_network_element_type(const char* name);
  
@@@ -143,8 -72,64 +147,6 @@@ XBT_PUBLIC(int) find_model_description(
  XBT_PUBLIC(void) model_help(const char *category,
                              s_surf_model_description_t * table);
  
 -enum heap_action_type{
 -  LATENCY = 100,
 -  MAX_DURATION,
 -  NORMAL,
 -  NOTSET
 -};
 -
 -/** \ingroup SURF_actions
 - *  \brief Action structure
 - *
 - *  Never create s_surf_action_t by yourself ! The actions are created
 - *  on the fly when you call execute or communicate on a model.
 - *
 - *  \see e_surf_action_state_t
 - */
 -typedef struct surf_action {
 -  s_xbt_swag_hookup_t state_hookup;
 -  xbt_swag_t state_set;
 -  double cost;                  /**< cost        */
 -  double priority;              /**< priority (1.0 by default) */
 -  double bound;              /**< the capping of the CPU use  */
 -  double max_duration;          /**< max_duration (may fluctuate until
 -           the task is completed) */
 -  double remains;               /**< How much of that cost remains to
 -         * be done in the currently running task */
 -#ifdef HAVE_LATENCY_BOUND_TRACKING
 -  int latency_limited;               /**< Set to 1 if is limited by latency, 0 otherwise */
 -#endif
 -
 -  double start;                 /**< start time  */
 -  double finish;                /**< finish time : this is modified during the run
 -         * and fluctuates until the task is completed */
 -  void *data;                   /**< for your convenience */
 -  int refcount;
 -
 -  /* The previous name was model_type. For VM support, we have to distinguish a
 -   * model type and its model object. Thus, we use model_obj here. The type of
 -   * a model object is available by looking at the inside of the model object. */
 -  surf_model_t model_obj;       /**< the surf model object */
 -
 -#ifdef HAVE_TRACING
 -  char *category;               /**< tracing category for categorized resource utilization monitoring */
 -#endif
 -  surf_file_t file;        /**< surf_file_t for storage model */
 -  xbt_dict_t ls_dict;
 -} s_surf_action_t;
--
 -typedef struct surf_action_lmm {
 -  s_surf_action_t generic_action;
 -  lmm_variable_t variable;
 -  int suspended;
 -  s_xbt_swag_hookup_t action_list_hookup;
 -  int index_heap;
 -  double last_update;
 -  double last_value;
 -  enum heap_action_type hat;
 -} s_surf_action_lmm_t, *surf_action_lmm_t;
--
  /** \ingroup SURF_actions
   *  \brief Action states
   *
   *
   *  \see surf_action_t, surf_action_state_t
   */
 +
  typedef enum {
    SURF_ACTION_READY = 0,        /**< Ready        */
    SURF_ACTION_RUNNING,          /**< Running      */
                                  /**< Not in the system anymore. Why did you ask ? */
  } e_surf_action_state_t;
  
 -/** \ingroup SURF_actions
 - *  \brief Action state sets
 - *
 - *  This structure contains some sets of actions.
 - *  It provides a fast access to the actions in each state.
 - *
 - *  \see surf_action_t, e_surf_action_state_t
 - */
 -typedef struct surf_action_state {
 -  xbt_swag_t ready_action_set;
 -                                 /**< Actions in state SURF_ACTION_READY */
 -  xbt_swag_t running_action_set;
 -                                 /**< Actions in state SURF_ACTION_RUNNING */
 -  xbt_swag_t failed_action_set;
 -                                 /**< Actions in state SURF_ACTION_FAILED */
 -  xbt_swag_t done_action_set;
 -                                 /**< Actions in state SURF_ACTION_DONE */
 -} s_surf_action_state_t, *surf_action_state_t;
 -
 -/***************************/
 -/* Generic model object */
 -/***************************/
 -typedef struct s_routing_platf s_routing_platf_t, *routing_platf_t;
 -XBT_PUBLIC_DATA(routing_platf_t) routing_platf;
 -
 -/*******************************************
 - *  TUTORIAL: New model
 - *  New model extension public
 - *  Public functions specific to a New model.
 - */
 -typedef struct surf_new_model_extension_public {
 -  surf_action_t(*fct) ();
 -  void* (*create_resource) ();
 -} s_surf_model_extension_new_model_t;
 -/*******************************************/
++/* FIXME: Where should the VM state be defined? */
++typedef enum {
++  /* created, but not yet started */
++  SURF_VM_STATE_CREATED,
 -/** \ingroup SURF_models
 - *  \brief Private data available on all models
 - */
 -typedef struct surf_model_private *surf_model_private_t;
 -
 -     /* Cpu model */
 -
 -     /** \ingroup SURF_models
 -      *  \brief CPU model extension public
 -      *
 -      *  Public functions specific to the CPU model.
 -      */
 -typedef struct surf_cpu_model_extension_public {
 -  surf_action_t(*execute) (void *cpu, double size);
 -  surf_action_t(*sleep) (void *cpu, double duration);
 -  e_surf_resource_state_t(*get_state) (void *cpu);
 -  void(*set_state) (void *cpu, e_surf_resource_state_t state);
 -
 -  int (*get_core) (void *cpu);
 -  double (*get_speed) (void *cpu, double load);
 -  double (*get_available_speed) (void *cpu);
 -  double (*get_current_power_peak) (void *cpu);
 -  double (*get_power_peak_at) (void *cpu, int pstate_index);
 -  int (*get_nb_pstates) (void *cpu);
 -  void (*set_power_peak_at) (void *cpu, int pstate_index);
 -  double (*get_consumed_energy) (void *cpu);
 -  void (*add_traces) (void);
 -} s_surf_model_extension_cpu_t;
 -
 -     /* Network model */
 -
 -     /** \ingroup SURF_models
 -      *  \brief Network model extension public
 -      *
 -      *  Public functions specific to the network model
 -      */
 -typedef struct surf_network_model_extension_public {
 -  surf_action_t (*communicate) (sg_routing_edge_t src,
 -                                sg_routing_edge_t dst,
 -                                double size, double rate);
 -  xbt_dynar_t(*get_route) (void *src, void *dst); //FIXME: kill field? That is done by the routing nowadays
 -  double (*get_link_bandwidth) (const void *link);
 -  double (*get_link_latency) (const void *link);
 -  int (*link_shared) (const void *link);
 -  void (*add_traces) (void);
 -} s_surf_model_extension_network_t;
 -
 -/* Storage model */
++  SURF_VM_STATE_RUNNING,
++  SURF_VM_STATE_MIGRATING,
 -/** \ingroup SURF_models
 - *  \brief Storage model extension public
 - *
 - *  Public functions specific to the Storage model.
 - */
++  /* Suspend/resume does not involve disk I/O, so we assume there is no transition states. */
++  SURF_VM_STATE_SUSPENDED,
 -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, 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;
++  /* Save/restore involves disk I/O, so there should be transition states. */
++  SURF_VM_STATE_SAVING,
++  SURF_VM_STATE_SAVED,
++  SURF_VM_STATE_RESTORING,
 -/** \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 */
 -  e_surf_resource_state_t(*get_state) (void *workstation);                                      /**< Return the CPU state of a workstation */
 -  void(*set_state) (void *workstation, e_surf_resource_state_t state);
 -  int (*get_core) (void *workstation); 
 -  double (*get_speed) (void *workstation, double load);                                    /**< Return the speed of a workstation */
 -  double (*get_available_speed) (void *workstation);                                       /**< Return tha available speed of a workstation */
 -
 -  double (*get_current_power_peak) (void *workstation);                                         /**< Return the current CPU speed of a workstation */
 -  double (*get_power_peak_at) (void *workstation, int pstate_index);                    /**< Return the speed of a workstation for a specific pstate,
 -                                                                                               (where higher pstate values represent lower processor speeds) */
 -  int (*get_nb_pstates) (void *workstation);                                            /**< Return the number of pstates defined for a workstation (default is 1) */
 -  void (*set_power_peak_at) (void *workstation, int pstate_index);                      /**< Set the processor speed of a workstation to the speed associated with the pstate_index pstate */
 -  double (*get_consumed_energy) (void *workstation);                                    /**< Return the total energy consumed by a workstation */
 -
 -   surf_action_t(*communicate) (void *workstation_src,                                     /**< Execute a communication amount between two workstations */
 -                                void *workstation_dst, double size,
 -                                double max_rate);
 -   // FIXME: kill next field, which duplicates the routing
 -   xbt_dynar_t(*get_route) (void *workstation_src, void *workstation_dst);                 /**< Get the list of links between two ws */
 -
 -   surf_action_t(*execute_parallel_task) (int workstation_nb,                              /**< Execute a parallel task on several workstations */
 -                                          void **workstation_list,
 -                                          double *computation_amount,
 -                                          double *communication_amount,
 -                                          double rate);
 -  double (*get_link_bandwidth) (const void *link);                                         /**< Return the current bandwidth of a network link */
 -  double (*get_link_latency) (const void *link);                                           /**< Return the current latency of a network link */
 -  surf_action_t(*open) (void *workstation, const char* storage,
 -                        const char* path);
 -  surf_action_t(*close) (void *workstation, surf_file_t fd);
 -  surf_action_t(*read) (void *workstation, surf_file_t fd, sg_storage_size_t size);
 -  surf_action_t(*write) (void *workstation, surf_file_t fd, sg_storage_size_t size);
 -  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);
 -  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);
 -  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;
++} e_surf_vm_state_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;
++typedef struct ws_params {
++  int ncpus;
++  long ramsize;
++  int overcommit;
 -/** \ingroup SURF_models
 - *  \brief Model datatype
 - *
 - *  Generic data structure for a model. The workstations,
 - *  the CPUs and the network links are examples of models.
 - */
 -typedef struct surf_model {
 -  const char *name;     /**< Name of this model */
 -  s_surf_action_state_t states;      /**< Any living action on this model */
 -
 -  e_surf_model_type_t type; /**< See e_surf_model_type_t */
 -
 -  e_surf_action_state_t(*action_state_get) (surf_action_t action);
 -                                                                       /**< Return the state of an action */
 -  void (*action_state_set) (surf_action_t action,
 -                            e_surf_action_state_t state);
 -                                                                  /**< Change an action state*/
 -
 -  double (*action_get_start_time) (surf_action_t action);     /**< Return the start time of an action */
 -  double (*action_get_finish_time) (surf_action_t action);     /**< Return the finish time of an action */
 -  int (*action_unref) (surf_action_t action);     /**< Specify that we don't use that action anymore. Returns true if the action was destroyed and false if someone still has references on it. */
 -  void (*action_cancel) (surf_action_t action);     /**< Cancel a running action */
 -  void (*action_recycle) (surf_action_t action);     /**< Recycle an action */
 -  void (*action_data_set) (surf_action_t action, void *data);     /**< Set the user data of an action */
 -  void (*suspend) (surf_action_t action);     /**< Suspend an action */
 -  void (*resume) (surf_action_t action);     /**< Resume a suspended action */
 -  int (*is_suspended) (surf_action_t action);     /**< Return whether an action is suspended */
 -  void (*set_max_duration) (surf_action_t action, double duration);     /**< Set the max duration of an action*/
 -  void (*set_priority) (surf_action_t action, double priority);     /**< Set the priority of an action */
 -  void (*set_bound) (surf_action_t action, double bound);     /**< Set the bound (the maximum CPU utilization) of an action */
 -
 -  /* Note (hypervisor): set_affinity() may be used only in CPU models. It might
 -   * be better to move this member to the extension field.
 -   **/
 -  void (*set_affinity) (surf_action_t action, void *workstation, unsigned long mask);     /**< Set the CPU affinity of an action */
 -
 -#ifdef HAVE_TRACING
 -  void (*set_category) (surf_action_t action, const char *category); /**< Set the category of an action */
 -#endif
 -  double (*get_remains) (surf_action_t action);     /**< Get the remains of an action */
 -#ifdef HAVE_LATENCY_BOUND_TRACKING
 -  int (*get_latency_limited) (surf_action_t action);     /**< Return 1 if action is limited by latency, 0 otherwise */
 -#endif
++  /* The size of other states than memory pages, which is out-of-scope of dirty
++   * page tracking. */
++  long devsize;
++  int skip_stage1;
++  int skip_stage2;
++  double max_downtime;
 -  void (*gap_remove) (surf_action_lmm_t action);
++  double dp_rate;
++  double dp_cap; /* bytes per 1 flop execution */
 -  surf_model_private_t model_private;
++  double xfer_cpu_overhead;
++  double dpt_cpu_overhead;
 -  union extension {
 -    s_surf_model_extension_cpu_t cpu;
 -    s_surf_model_extension_network_t network;
 -    s_surf_model_extension_storage_t storage;
 -    s_surf_model_extension_workstation_t workstation;
 -    // TODO Implement the corresponding model
 -    s_surf_model_extension_vm_workstation_t vm_workstation;
 -    /*******************************************/
 -    /* TUTORIAL: New model                     */
 -    s_surf_model_extension_new_model_t new_model;
 -    /*******************************************/
 -  } extension;
 -} s_surf_model_t;
++  /* set migration speed */
++  double mig_speed;
++} s_ws_params_t, *ws_params_t;
 -surf_model_t surf_model_init(void);
 -void surf_model_exit(surf_model_t model);
 +/***************************/
 +/* Generic model object */
 +/***************************/
 +//FIXME:REMOVE typedef struct s_routing_platf s_routing_platf_t, *routing_platf_t;
 +XBT_PUBLIC_DATA(routing_platf_t) routing_platf;
  
- /*******************************************
-  *  TUTORIAL: New model
-  *  New model extension public
-  *  Public functions specific to a New model.
-  */
- typedef struct surf_new_model_extension_public {
-   surf_action_t(*fct) ();
-   void* (*create_resource) ();
- } s_surf_model_extension_new_model_t;
- /*******************************************/
- /** \ingroup SURF_models
-  *  \brief Private data available on all models
-  */
- typedef struct surf_model_private *surf_model_private_t;
-      /* Cpu model */
-      /** \ingroup SURF_models
-       *  \brief CPU model extension public
-       *
-       *  Public functions specific to the CPU model.
-       */
- typedef struct surf_cpu_model_extension_public {
-   surf_action_t(*execute) (void *cpu, double size);
-   surf_action_t(*sleep) (void *cpu, double duration);
-   e_surf_resource_state_t(*get_state) (void *cpu);
-   int (*get_core) (void *cpu);
-   double (*get_speed) (void *cpu, double load);
-   double (*get_available_speed) (void *cpu);
-   double (*get_current_power_peak) (void *cpu);
-   double (*get_power_peak_at) (void *cpu, int pstate_index);
-   int (*get_nb_pstates) (void *cpu);
-   void (*set_power_peak_at) (void *cpu, int pstate_index);
-   double (*get_consumed_energy) (void *cpu);
-   void (*add_traces) (void);
- } s_surf_model_extension_cpu_t;
-      /* Network model */
-      /** \ingroup SURF_models
-       *  \brief Network model extension public
-       *
-       *  Public functions specific to the network model
-       */
- typedef struct surf_network_model_extension_public {
-   surf_action_t (*communicate) (sg_routing_edge_t src,
-                                 sg_routing_edge_t dst,
-                                 double size, double rate);
-   xbt_dynar_t(*get_route) (void *src, void *dst); //FIXME: kill field? That is done by the routing nowadays
-   double (*get_link_bandwidth) (const void *link);
-   double (*get_link_latency) (const void *link);
-   int (*link_shared) (const void *link);
-   void (*add_traces) (void);
- } s_surf_model_extension_network_t;
- /* Storage model */
- /** \ingroup SURF_models
-  *  \brief Storage model extension public
-  *
-  *  Public functions specific to the Storage model.
-  */
- 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, 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.
-       */
- typedef struct surf_workstation_model_extension_public {
-   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 */
-   e_surf_resource_state_t(*get_state) (void *workstation);                                      /**< Return the CPU state of a workstation */
-   int (*get_core) (void *workstation); 
-   double (*get_speed) (void *workstation, double load);                                    /**< Return the speed of a workstation */
-   double (*get_available_speed) (void *workstation);                                       /**< Return tha available speed of a workstation */
-   double (*get_current_power_peak) (void *workstation);                                         /**< Return the current CPU speed of a workstation */
-   double (*get_power_peak_at) (void *workstation, int pstate_index);                    /**< Return the speed of a workstation for a specific pstate,
-                                                                                                (where higher pstate values represent lower processor speeds) */
-   int (*get_nb_pstates) (void *workstation);                                            /**< Return the number of pstates defined for a workstation (default is 1) */
-   void (*set_power_peak_at) (void *workstation, int pstate_index);                      /**< Set the processor speed of a workstation to the speed associated with the pstate_index pstate */
-   double (*get_consumed_energy) (void *workstation);                                    /**< Return the total energy consumed by a workstation */
-    surf_action_t(*communicate) (void *workstation_src,                                     /**< Execute a communication amount between two workstations */
-                                 void *workstation_dst, double size,
-                                 double max_rate);
-    // FIXME: kill next field, which duplicates the routing
-    xbt_dynar_t(*get_route) (void *workstation_src, void *workstation_dst);                 /**< Get the list of links between two ws */
-    surf_action_t(*execute_parallel_task) (int workstation_nb,                              /**< Execute a parallel task on several workstations */
-                                           void **workstation_list,
-                                           double *computation_amount,
-                                           double *communication_amount,
-                                           double rate);
-   double (*get_link_bandwidth) (const void *link);                                         /**< Return the current bandwidth of a network link */
-   double (*get_link_latency) (const void *link);                                           /**< Return the current latency of a network link */
-   surf_action_t(*open) (void *workstation, const char* storage,
-                         const char* path);
-   surf_action_t(*close) (void *workstation, surf_file_t fd);
-   surf_action_t(*read) (void *workstation, surf_file_t fd, sg_storage_size_t size);
-   surf_action_t(*write) (void *workstation, surf_file_t fd, sg_storage_size_t size);
-   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);
-   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);
-   void (*add_traces) (void);
-   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;
  static inline void *surf_cpu_resource_priv(const void *host) {
 -  return xbt_lib_get_level((void *)host, SURF_CPU_LEVEL);
 +  return xbt_lib_get_level((xbt_dictelm_t)host, SURF_CPU_LEVEL);
  }
  static inline void *surf_workstation_resource_priv(const void *host){
 -  return xbt_lib_get_level((void *)host, SURF_WKS_LEVEL);
 +  return (void*)xbt_lib_get_level((xbt_dictelm_t)host, SURF_WKS_LEVEL);
  }
  static inline void *surf_storage_resource_priv(const void *storage){
 -  return xbt_lib_get_level((void *)storage, SURF_STORAGE_LEVEL);
 +  return (void*)xbt_lib_get_level((xbt_dictelm_t)storage, SURF_STORAGE_LEVEL);
  }
  
  static inline void *surf_cpu_resource_by_name(const char *name) {
@@@ -322,76 -447,36 +231,92 @@@ static inline void *surf_storage_resour
    return xbt_lib_get_elm_or_null(storage_lib, name);
  }
  
 -typedef struct surf_resource {
 -  surf_model_t model;
 -  char *name;
 -  xbt_dict_t properties;
 -  void_f_pvoid_t free_f;
 -} s_surf_resource_t, *surf_resource_t;
 -
 -static inline surf_model_t surf_resource_model(const void *host, int level) {
 -  /* If level is SURF_WKS_LEVEL, ws is a workstation_CLM03 object. It has
 -   * surf_resource at the generic_resource field. */
 -  surf_resource_t ws = xbt_lib_get_level((void *) host, level);
 -  return ws->model;
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +char *surf_routing_edge_name(sg_routing_edge_t edge);
 +void *surf_as_cluster_get_backbone(AS_t as);
 +void surf_as_cluster_set_backbone(AS_t as, void* backbone);
 +const char *surf_model_name(surf_model_t model);
 +xbt_swag_t surf_model_done_action_set(surf_model_t model);
 +xbt_swag_t surf_model_failed_action_set(surf_model_t model);
 +xbt_swag_t surf_model_ready_action_set(surf_model_t model);
 +xbt_swag_t surf_model_running_action_set(surf_model_t model);
 +surf_action_t surf_workstation_model_execute_parallel_task(surf_workstation_model_t model,
 +                                                  int workstation_nb,
 +                                            void **workstation_list,
 +                                            double *computation_amount,
 +                                            double *communication_amount,
 +                                            double rate);
 +surf_action_t surf_workstation_model_communicate(surf_workstation_model_t model, surf_resource_t src, surf_resource_t dst, double size, double rate);
 +xbt_dynar_t surf_workstation_model_get_route(surf_workstation_model_t model, surf_resource_t src, surf_resource_t dst);
++void surf_vm_workstation_model_create(const char *name, surf_resource_t ind_phys_host);
 +surf_action_t surf_network_model_communicate(surf_network_model_t model, sg_routing_edge_t src, sg_routing_edge_t dst, double size, double rate);
 +const char *surf_resource_name(surf_cpp_resource_t resource);
 +xbt_dict_t surf_resource_get_properties(surf_cpp_resource_t resource);
 +e_surf_resource_state_t surf_resource_get_state(surf_cpp_resource_t resource);
++void surf_resource_set_state(surf_cpp_resource_t resource, e_surf_resource_state_t state);
 +double surf_workstation_get_speed(surf_resource_t resource, double load);
 +double surf_workstation_get_available_speed(surf_resource_t resource);
 +int surf_workstation_get_core(surf_resource_t resource);
 +surf_action_t surf_workstation_execute(surf_resource_t resource, double size);
 +surf_action_t surf_workstation_sleep(surf_resource_t resource, double duration);
 +surf_action_t surf_workstation_open(surf_resource_t workstation, const char* mount, const char* path);
 +surf_action_t surf_workstation_close(surf_resource_t workstation, surf_file_t fd);
 +surf_action_t surf_workstation_read(surf_resource_t resource, surf_file_t fd, sg_storage_size_t size);
 +surf_action_t surf_workstation_write(surf_resource_t resource, surf_file_t fd, sg_storage_size_t size);
 +xbt_dynar_t surf_workstation_get_info(surf_resource_t resource, surf_file_t fd);
 +sg_storage_size_t surf_workstation_get_free_size(surf_resource_t resource, const char* name);
 +sg_storage_size_t surf_workstation_get_used_size(surf_resource_t resource, const char* name);
++xbt_dynar_t surf_workstation_get_vms(surf_resource_t resource);
++void surf_workstation_get_params(surf_resource_t resource, ws_params_t params);
++void surf_workstation_set_params(surf_resource_t resource, ws_params_t params);
++void surf_vm_workstation_destroy(surf_resource_t resource);
++void surf_vm_workstation_suspend(surf_resource_t resource);
++void surf_vm_workstation_resume(surf_resource_t resource);
++void surf_vm_workstation_save(surf_resource_t resource);
++void surf_vm_workstation_restore(surf_resource_t resource);
++void surf_vm_workstation_migrate(surf_resource_t resource, surf_resource_t ind_vm_ws_dest);
++surf_resource_t surf_vm_workstation_get_pm(surf_resource_t resource);
++void surf_vm_workstation_set_bound(surf_resource_t resource, double bound);
++void surf_vm_workstation_set_affinity(surf_resource_t resource, surf_resource_t cpu, unsigned long mask);
 +surf_action_t surf_cpu_execute(surf_resource_t cpu, double size);
 +surf_action_t surf_cpu_sleep(surf_resource_t cpu, double duration);
 +double surf_workstation_get_current_power_peak(surf_resource_t host);
 +double surf_workstation_get_power_peak_at(surf_resource_t host, int pstate_index);
 +int surf_workstation_get_nb_pstates(surf_resource_t host);
 +void surf_workstation_set_power_peak_at(surf_resource_t host, int pstate_index);
 +double surf_workstation_get_consumed_energy(surf_resource_t host);
 +xbt_dict_t surf_workstation_get_storage_list(surf_resource_t workstation);
 +int surf_workstation_unlink(surf_resource_t workstation, surf_file_t fd);
 +surf_action_t surf_workstation_ls(surf_resource_t workstation, const char* mount, const char *path);
 +size_t surf_workstation_get_size(surf_resource_t workstation, surf_file_t fd);
 +int surf_network_link_is_shared(surf_cpp_resource_t link);
 +double surf_network_link_get_bandwidth(surf_cpp_resource_t link);
 +double surf_network_link_get_latency(surf_cpp_resource_t link);
 +xbt_dict_t surf_storage_get_content(surf_resource_t resource);
 +sg_storage_size_t surf_storage_get_size(surf_resource_t resource);
 +void *surf_action_get_data(surf_action_t action);
 +void surf_action_set_data(surf_action_t action, void *data);
 +void surf_action_unref(surf_action_t action);
 +double surf_action_get_start_time(surf_action_t action);
 +double surf_action_get_finish_time(surf_action_t action);
 +double surf_action_get_remains(surf_action_t action);
 +void surf_action_suspend(surf_action_t action);
 +void surf_action_resume(surf_action_t action);
 +void surf_action_cancel(surf_action_t action);
 +void surf_action_set_priority(surf_action_t action, double priority);
 +void surf_action_set_category(surf_action_t action, const char *category);
 +e_surf_action_state_t surf_action_get_state(surf_action_t action);
 +int surf_action_get_cost(surf_action_t action);
++void surf_cpu_action_set_affinity(surf_action_t action, surf_resource_t cpu, unsigned long mask);
++void surf_cpu_action_set_bound(surf_action_t action, double bound);
 +surf_file_t surf_storage_action_get_file(surf_action_t action);
 +xbt_dict_t surf_storage_action_get_ls_dict(surf_action_t action);
++surf_model_t surf_resource_model(const void *host, int level);
 +#ifdef __cplusplus
  }
 -
 -/**
 - * Resource which have a metric handled by a maxmin system
 - */
 -typedef struct {
 -  double scale;
 -  double peak;
 -  tmgr_trace_event_t event;
 -} s_surf_metric_t;
 -
 -typedef struct surf_resource_lmm {
 -  s_surf_resource_t generic_resource;
 -  lmm_constraint_t constraint;
 -  e_surf_resource_state_t state_current;
 -  tmgr_trace_event_t state_event;
 -  s_surf_metric_t power;
 -} s_surf_resource_lmm_t, *surf_resource_lmm_t;
 +#endif
  
  /**************************************/
  /* Implementations of model object */
  
  
  /** \ingroup SURF_models
-  *  \brief The CPU model
+  *  \brief The CPU model object for the physical machine layer
   */
- XBT_PUBLIC_DATA(surf_cpu_model_t) surf_cpu_model;
 -XBT_PUBLIC_DATA(surf_model_t) surf_cpu_model_pm;
++XBT_PUBLIC_DATA(surf_cpu_model_t) surf_cpu_model_pm;
+ /** \ingroup SURF_models
+  *  \brief The CPU model object for the virtual machine layer
+  */
 -XBT_PUBLIC_DATA(surf_model_t) surf_cpu_model_vm;
++XBT_PUBLIC_DATA(surf_cpu_model_t) surf_cpu_model_vm;
++
  
  /** \ingroup SURF_models
   *  \brief Initializes the CPU model with the model Cas01
@@@ -420,7 -510,7 +351,7 @@@ XBT_PUBLIC(void) surf_cpu_model_init_Ca
   *
   *  You shouldn't have to call it by yourself.
   */
 -XBT_PUBLIC(surf_model_t) surf_cpu_model_init_ti(void);
 +XBT_PUBLIC(void) surf_cpu_model_init_ti(void);
  
  /** \ingroup SURF_models
   *  \brief The list of all available optimization modes (both for cpu and networks).
@@@ -446,7 -536,7 +377,7 @@@ XBT_PUBLIC_DATA(s_surf_model_descriptio
   *  model should be accessed because depending on the platform model,
   *  the network model can be NULL.
   */
 -XBT_PUBLIC_DATA(surf_model_t) surf_network_model;
 +XBT_PUBLIC_DATA(surf_network_model_t) surf_network_model;
  
  /** \ingroup SURF_models
   *  \brief Same as network model 'LagrangeVelho', only with different correction factors.
@@@ -582,7 -672,7 +513,7 @@@ XBT_PUBLIC(void) surf_storage_model_ini
   */
  XBT_PUBLIC_DATA(s_surf_model_description_t) surf_storage_model_description[];
  
 -XBT_PUBLIC_DATA(surf_model_t) surf_storage_model;
 +XBT_PUBLIC_DATA(surf_storage_model_t) surf_storage_model;
  
  /** \ingroup SURF_models
   *  \brief The workstation model
   *  because depending on the platform model, the network model and the CPU model
   *  may not exist.
   */
 -XBT_PUBLIC_DATA(surf_model_t) surf_workstation_model;
 +XBT_PUBLIC_DATA(surf_workstation_model_t) surf_workstation_model;
  
 -XBT_PUBLIC_DATA(surf_model_t) surf_vm_workstation_model;
+ /** \ingroup SURF_models
+  *  \brief The vm_workstation model
+  *
+  *  Note that when you create an API on top of SURF,
+  *  the vm_workstation model should be the only one you use
+  *  because depending on the platform model, the network model and the CPU model
+  *  may not exist.
+  */
++XBT_PUBLIC_DATA(surf_vm_workstation_model_t) surf_vm_workstation_model;
  /** \ingroup SURF_models
   *  \brief Initializes the platform with a compound workstation model
   *
@@@ -631,12 -731,18 +572,31 @@@ XBT_PUBLIC(void) surf_workstation_model
  XBT_PUBLIC_DATA(s_surf_model_description_t)
      surf_workstation_model_description[];
  
 -/*******************************************
 - *  TUTORIAL: New model
++/** \ingroup SURF_models
++ *  \brief Initializes the platform with the current best network and cpu models at hand
++ *
++ *  This platform model seperates the workstation model and the network model.
++ *  The workstation model will be initialized with the model compound, the network
++ *  model with the model LV08 (with cross traffic support) and the CPU model with
++ *  the model Cas01.
++ *  Such model is subject to modification with warning in the ChangeLog so monitor it!
++ *
++ */
++XBT_PUBLIC(void) surf_vm_workstation_model_init_current_default(void);
++
++/** \ingroup SURF_models
++ *  \brief The list of all available vm workstation model models
+  */
 -XBT_PUBLIC(void) surf_new_model_init_default(void);
 -XBT_PUBLIC_DATA(s_surf_model_description_t) surf_new_model_description[];
++XBT_PUBLIC_DATA(s_surf_model_description_t)
++    surf_vm_workstation_model_description[];
++
  /*******************************************/
  
  /** \ingroup SURF_models
   *  \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.
@@@ -651,20 -757,13 +611,20 @@@ XBT_PUBLIC(xbt_dict_t) watched_hosts_li
  /*******************************************/
  /*** SURF Platform *************************/
  /*******************************************/
 -typedef struct s_as *AS_t;
 -
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
  XBT_PUBLIC_DATA(AS_t) surf_AS_get_routing_root(void); 
  XBT_PUBLIC_DATA(const char *) surf_AS_get_name(AS_t as);
  XBT_PUBLIC_DATA(xbt_dict_t) surf_AS_get_routing_sons(AS_t as);
  XBT_PUBLIC_DATA(const char *) surf_AS_get_model(AS_t as);
  XBT_PUBLIC_DATA(xbt_dynar_t) surf_AS_get_hosts(AS_t as);
 +XBT_PUBLIC_DATA(void) surf_AS_get_graph(AS_t as, xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges);
 +XBT_PUBLIC_DATA(AS_t) surf_platf_get_root(routing_platf_t platf);
 +XBT_PUBLIC_DATA(e_surf_network_element_type_t) surf_routing_edge_get_rc_type(sg_routing_edge_t edge);
 +#ifdef __cplusplus
 +}
 +#endif
  
  /*******************************************/
  /*** SURF Globals **************************/
@@@ -761,7 -860,7 +721,7 @@@ void instr_routing_define_callbacks (vo
  void instr_new_variable_type (const char *new_typename, const char *color);
  void instr_new_user_variable_type  (const char *father_type, const char *new_typename, const char *color);
  void instr_new_user_state_type (const char *father_type, const char *new_typename);
 -void instr_new_value_for_user_state_type (const char *typename, const char *value, const char *color);
 +void instr_new_value_for_user_state_type (const char *_typename, const char *value, const char *color);
  int instr_platform_traced (void);
  xbt_graph_t instr_routing_platform_graph (void);
  void instr_routing_platform_graph_export_graphviz (xbt_graph_t g, const char *filename);
diff --combined src/simdag/sd_global.c
@@@ -310,12 -310,14 +310,13 @@@ xbt_swag_t SD_simulate_swag(double how_
      if (elapsed_time > 0.0)
        total_time += elapsed_time;
  
+     /* FIXME: shoud look at model_list or model_list_invoke? */
      /* let's see which tasks are done */
      xbt_dynar_foreach(model_list, iter, model) {
 -      while ((action = xbt_swag_extract(model->states.done_action_set))) {
 -        task = action->data;
 -        task->start_time =
 -            surf_workstation_model->
 -            action_get_start_time(task->surf_action);
 +      while ((action = xbt_swag_extract(surf_model_done_action_set(model)))) {
 +        task = surf_action_get_data(action);
 +        task->start_time = surf_action_get_start_time(task->surf_action);
 +
          task->finish_time = surf_get_clock();
          XBT_VERB("Task '%s' done", SD_task_get_name(task));
          XBT_DEBUG("Calling __SD_task_just_done");
        }
  
        /* let's see which tasks have just failed */
 -      while ((action = xbt_swag_extract(model->states.failed_action_set))) {
 -        task = action->data;
 -        task->start_time =
 -            surf_workstation_model->
 -            action_get_start_time(task->surf_action);
 +      while ((action = xbt_swag_extract(surf_model_failed_action_set(model)))) {
 +        task = surf_action_get_data(action);
 +        task->start_time = surf_action_get_start_time(task->surf_action);
          task->finish_time = surf_get_clock();
          XBT_VERB("Task '%s' failed", SD_task_get_name(task));
          __SD_task_set_state(task, SD_FAILED);
 -        surf_workstation_model->action_unref(action);
 +        surf_action_unref(action);
          task->surf_action = NULL;
  
          xbt_swag_insert(task,sd_global->return_set);
diff --combined src/simgrid/sg_config.c
@@@ -21,6 -21,7 +21,6 @@@
  #include "smpi/smpi_interface.h"
  #include "mc/mc.h"
  #include "instr/instr.h"
 -#include "surf/vm_workstation_private.h"
  
  XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_config, surf,
                                  "About the configuration of simgrid");
@@@ -125,6 -126,6 +125,25 @@@ static void _sg_cfg_cb__workstation_mod
    find_model_description(surf_workstation_model_description, val);
  }
  
++/* callback of the vm_workstation/model variable */
++static void _sg_cfg_cb__vm_workstation_model(const char *name, int pos)
++{
++  char *val;
++
++  xbt_assert(_sg_cfg_init_status < 2,
++              "Cannot change the model after the initialization");
++
++  val = xbt_cfg_get_string(_sg_cfg_set, name);
++
++  if (!strcmp(val, "help")) {
++    model_help("vm_workstation", surf_vm_workstation_model_description);
++    sg_cfg_exit_early();
++  }
++
++  /* Make sure that the model exists */
++  find_model_description(surf_vm_workstation_model_description, val);
++}
++
  /* callback of the cpu/model variable */
  static void _sg_cfg_cb__cpu_model(const char *name, int pos)
  {
@@@ -447,6 -448,22 +466,6 @@@ void sg_config_init(int *argc, char **a
                       xbt_cfgelm_string, 1, 1, &_sg_cfg_cb__storage_mode, NULL);
      xbt_cfg_setdefault_string(_sg_cfg_set, "storage/model", "default");
  
 -    /* ********************************************************************* */
 -    /* TUTORIAL: New model                                                   */
 -    sprintf(description,
 -            "The model to use for the New model. Possible values: ");
 -    p = description;
 -    while (*(++p) != '\0');
 -    for (i = 0; surf_new_model_description[i].name; i++)
 -      p += sprintf(p, "%s%s", (i == 0 ? "" : ", "),
 -                   surf_new_model_description[i].name);
 -    sprintf(p,
 -            ".\n       (use 'help' as a value to see the long description of each model)");
 -    xbt_cfg_register(&_sg_cfg_set, "new_model/model", description,
 -                     xbt_cfgelm_string, 1, 1, &_sg_cfg_cb__storage_mode, NULL);
 -    xbt_cfg_setdefault_string(_sg_cfg_set, "new_model/model", "default");
 -    /* ********************************************************************* */
 -
      sprintf(description,
              "The model to use for the network. Possible values: ");
      p = description;
                       xbt_cfgelm_string, 1, 1, &_sg_cfg_cb__workstation_model, NULL);
      xbt_cfg_setdefault_string(_sg_cfg_set, "workstation/model", "default");
  
++    xbt_cfg_register(&_sg_cfg_set, "vm_workstation/model", description,
++                     xbt_cfgelm_string, 1, 1, &_sg_cfg_cb__vm_workstation_model, NULL);
++    xbt_cfg_setdefault_string(_sg_cfg_set, "vm_workstation/model", "default");
++
      xbt_cfg_register(&_sg_cfg_set, "network/TCP_gamma",
                       "Size of the biggest TCP window (cat /proc/sys/net/ipv4/tcp_[rw]mem for recv/send window; Use the last given value, which is the max window size)",
                       xbt_cfgelm_double, 1, 1, _sg_cfg_cb__tcp_gamma, NULL);
@@@ -818,7 -835,7 +841,9 @@@ void sg_config_finalize(void
  void surf_config_models_setup()
  {
    const char *workstation_model_name;
++  const char *vm_workstation_model_name;
    int workstation_id = -1;
++  int vm_workstation_id = -1;
    char *network_model_name = NULL;
    char *cpu_model_name = NULL;
    int storage_id = -1;
  
    workstation_model_name =
        xbt_cfg_get_string(_sg_cfg_set, "workstation/model");
++  vm_workstation_model_name =
++      xbt_cfg_get_string(_sg_cfg_set, "vm_workstation/model");
    network_model_name = xbt_cfg_get_string(_sg_cfg_set, "network/model");
    cpu_model_name = xbt_cfg_get_string(_sg_cfg_set, "cpu/model");
    storage_model_name = xbt_cfg_get_string(_sg_cfg_set, "storage/model");
    XBT_DEBUG("Call workstation_model_init");
    surf_workstation_model_description[workstation_id].model_init_preparse();
  
 -  surf_vm_workstation_model_init();
+   XBT_DEBUG("Call vm_workstation_model_init");
++  vm_workstation_id = find_model_description(surf_vm_workstation_model_description,
++                                          vm_workstation_model_name);
++  surf_vm_workstation_model_description[vm_workstation_id].model_init_preparse();
    XBT_DEBUG("Call storage_model_init");
    storage_id = find_model_description(surf_storage_model_description, storage_model_name);
    surf_storage_model_description[storage_id].model_init_preparse();
  
 -  /* ********************************************************************* */
 -  /* TUTORIAL: New model                                                   */
 -  int new_model_id = -1;
 -  char *new_model_name = NULL;
 -  new_model_name = xbt_cfg_get_string(_sg_cfg_set, "new_model/model");
 -  XBT_DEBUG("Call new model_init");
 -  new_model_id = find_model_description(surf_new_model_description, new_model_name);
 -  surf_new_model_description[new_model_id].model_init_preparse();
 -  /* ********************************************************************* */
  }
  
  int sg_cfg_get_int(const char* name)
diff --combined src/simix/smx_global.c
@@@ -324,15 -324,19 +324,20 @@@ void SIMIX_run(void
           ((void (*)(void*))timer->func)(timer->args);
         xbt_free(timer);
      }
 +
      /* Wake up all processes waiting for a Surf action to finish */
      xbt_dynar_foreach(model_list, iter, model) {
 -      set = model->states.failed_action_set;
 +      set = surf_model_failed_action_set(model);
        while ((action = xbt_swag_extract(set)))
-         SIMIX_simcall_post((smx_action_t) surf_action_get_data(action));
 -        SIMIX_simcall_post((smx_action_t) action->data);
 -      set = model->states.done_action_set;
 -      while ((action = xbt_swag_extract(set))) {
 -        if (action->data == NULL)
++      SIMIX_simcall_post((smx_action_t) surf_action_get_data(action));
 +      set = surf_model_done_action_set(model);
-       while ((action = xbt_swag_extract(set)))
-         SIMIX_simcall_post((smx_action_t) surf_action_get_data(action));
++
++      while ((action = xbt_swag_extract(set))) 
++        if (surf_action_get_data(action) == NULL)
+           XBT_DEBUG("probably vcpu's action %p, skip", action);
+         else
 -          SIMIX_simcall_post((smx_action_t) action->data);
 -      }
++          SIMIX_simcall_post((smx_action_t) surf_action_get_data(action));
      }
  
      /* Autorestart all process */
      /* Clean processes to destroy */
      SIMIX_process_empty_trash();
  
+     XBT_DEBUG("### time %f, empty %d", time, xbt_dynar_is_empty(simix_global->process_to_run));
+     // !(time == -1.0 && xbt_dynar_is_empty()) 
    } while (time != -1.0 || !xbt_dynar_is_empty(simix_global->process_to_run));
  
    if (xbt_swag_size(simix_global->process_list) != 0) {
diff --combined src/simix/smx_host.c
@@@ -38,6 -38,88 +38,86 @@@ smx_host_t SIMIX_host_create(const cha
    return xbt_lib_get_or_null(host_lib, name, SIMIX_HOST_LEVEL);
  }
  
 -  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);
+ 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_ON) {
 -    ws_model->extension.workstation.set_state(h, SURF_RESOURCE_OFF);
++  if (surf_resource_get_state(surf_workstation_resource_priv(h))==SURF_RESOURCE_OFF) {
++      surf_resource_set_state(surf_workstation_resource_priv(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");
+   
++  if (surf_resource_get_state(surf_workstation_resource_priv(h))==SURF_RESOURCE_OFF) {
++      surf_resource_set_state(surf_workstation_resource_priv(h), SURF_RESOURCE_ON);
+     /* 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.
   *
@@@ -64,6 -146,7 +144,7 @@@ void SIMIX_host_destroy(void *h
      THROWF(arg_error, 0, "%s", msg);
    }
    xbt_dynar_free(&host->auto_restart_processes);
+   xbt_dynar_free(&host->boot_processes);
    xbt_swag_free(host->process_list);
  
    /* Clean host structure */
@@@ -135,7 -218,8 +216,7 @@@ xbt_dict_t SIMIX_pre_host_get_propertie
  xbt_dict_t SIMIX_host_get_properties(smx_host_t host){
    xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
  
 -  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 -  return ws_model->extension.workstation.get_properties(host);
 +  return surf_resource_get_properties(surf_workstation_resource_priv(host));
  }
  
  double SIMIX_pre_host_get_speed(smx_simcall_t simcall, smx_host_t host){
  }
  double SIMIX_host_get_speed(smx_host_t host){
    xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
 -
 -  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 -  return ws_model->extension.workstation.get_speed(host, 1.0);
 +  return surf_workstation_get_speed(host, 1.0);
  }
  
  int SIMIX_pre_host_get_core(smx_simcall_t simcall, smx_host_t host){
  int SIMIX_host_get_core(smx_host_t host){
    xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
  
 -  return surf_workstation_model->extension.workstation.
 -      get_core(host);
 +  return surf_workstation_get_core(host);
  }
  
  xbt_swag_t SIMIX_pre_host_get_process_list(smx_simcall_t simcall, smx_host_t host){
@@@ -173,7 -260,8 +254,7 @@@ double SIMIX_pre_host_get_available_spe
  double SIMIX_host_get_available_speed(smx_host_t host){
    xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
  
 -  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 -  return ws_model->extension.workstation.get_available_speed(host);
 +  return surf_workstation_get_available_speed(host);
  }
  
  double SIMIX_pre_host_get_current_power_peak(smx_simcall_t simcall, smx_host_t 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);
 +        return surf_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){
  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);
 +        return surf_workstation_get_power_peak_at(host, pstate_index);
  }
  
  int SIMIX_pre_host_get_nb_pstates(smx_simcall_t simcall, smx_host_t 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);
 +        return surf_workstation_get_nb_pstates(host);
  }
  
  
@@@ -209,7 -300,8 +290,7 @@@ void SIMIX_pre_host_set_power_peak_at(s
  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);
 +        surf_workstation_set_power_peak_at(host, pstate_index);
  }
  
  double SIMIX_pre_host_get_consumed_energy(smx_simcall_t simcall, smx_host_t 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);
 +        return surf_workstation_get_consumed_energy(host);
  }
  
  int SIMIX_pre_host_get_state(smx_simcall_t simcall, smx_host_t host){
  int SIMIX_host_get_state(smx_host_t host){
    xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
  
 -  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 -  return ws_model->extension.workstation.get_state(host);
 +  return surf_resource_get_state(surf_workstation_resource_priv(host));
  }
  
  void* SIMIX_pre_host_self_get_data(smx_simcall_t simcall){
@@@ -253,7 -347,7 +334,7 @@@ void* SIMIX_host_get_data(smx_host_t ho
    return SIMIX_host_priv(host)->data;
  }
  
static void _SIMIX_host_free_process_arg(void *data)
+ void _SIMIX_host_free_process_arg(void *data)
  {
    smx_process_arg_t arg = *(void**)data;
    int i;
@@@ -377,11 -471,11 +458,11 @@@ void SIMIX_host_set_data(smx_host_t hos
  }
  
  smx_action_t SIMIX_pre_host_execute(smx_simcall_t simcall,const char *name,
-     smx_host_t host, double computation_amount, double priority){
-   return SIMIX_host_execute(name, host, computation_amount, priority);
+     smx_host_t host, double computation_amount, double priority, double bound, unsigned long affinity_mask){
+   return SIMIX_host_execute(name, host, computation_amount, priority, bound, affinity_mask);
  }
  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){
  
    /* alloc structures and initialize */
    smx_action_t action = xbt_mallocator_get(simix_global->action_mallocator);
    action->category = NULL;
  #endif
  
 -  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
    /* set surf's action */
    if (!MC_is_active()) {
-     action->execution.surf_exec =
-       surf_workstation_execute(host, computation_amount);
 -    action->execution.surf_exec = ws_model->extension.workstation.execute(host, computation_amount);
 -    ws_model->action_data_set(action->execution.surf_exec, action);
 -    ws_model->set_priority(action->execution.surf_exec, priority);
++
++    action->execution.surf_exec = surf_workstation_execute(host, computation_amount);
 +    surf_action_set_data(action->execution.surf_exec, action);
 +    surf_action_set_priority(action->execution.surf_exec, priority);
+     /* Note (hypervisor): for multicore, the bound value being passed to the
+      * surf layer should not be zero (i.e., unlimited). It should be the
+      * capacity of a CPU core. */
+     if (bound == 0)
 -      ws_model->set_bound(action->execution.surf_exec, SIMIX_host_get_speed(host));
++      surf_cpu_action_set_bound(action->execution.surf_exec, SIMIX_host_get_speed(host));
+     else
 -      ws_model->set_bound(action->execution.surf_exec, bound);
++      surf_cpu_action_set_bound(action->execution.surf_exec, bound);
+     if (affinity_mask != 0) {
+       /* just a double check to confirm that this host is the host where this task is running. */
+       xbt_assert(action->execution.host == host);
 -      ws_model->set_affinity(action->execution.surf_exec, host, affinity_mask);
++      surf_cpu_action_set_affinity(action->execution.surf_exec, host, affinity_mask);
+     }
    }
  
    XBT_DEBUG("Create execute action %p", action);
@@@ -436,29 -544,56 +531,51 @@@ smx_action_t SIMIX_host_parallel_execut
    /* set surf's action */
    workstation_list = xbt_new0(void *, host_nb);
    for (i = 0; i < host_nb; i++)
 -    workstation_list[i] = host_list[i];
 +    workstation_list[i] = surf_workstation_resource_priv(host_list[i]);
  
+   /* FIXME: what happens if host_list contains VMs and PMs. If
+    * execute_parallel_task() does not change the state of the model, we can mix
+    * them. */
+   surf_model_t ws_model = surf_resource_model(host_list[0], SURF_WKS_LEVEL);
+   for (i = 1; i < host_nb; i++) {
+     surf_model_t ws_model_tmp = surf_resource_model(host_list[i], SURF_WKS_LEVEL);
+     if (ws_model_tmp != ws_model) {
+       XBT_CRITICAL("mixing VMs and PMs is not supported");
+       DIE_IMPOSSIBLE;
+     }
+   }
    /* set surf's action */
    if (!MC_is_active()) {
      action->execution.surf_exec =
 -      ws_model->extension.workstation.
 -      execute_parallel_task(host_nb, workstation_list, computation_amount,
 -                      communication_amount, rate);
 +      surf_workstation_model_execute_parallel_task((surf_workstation_model_t)surf_workstation_model,
 +                host_nb, workstation_list, computation_amount, communication_amount, rate);
  
 -    ws_model->action_data_set(action->execution.surf_exec, action);
 +    surf_action_set_data(action->execution.surf_exec, action);
    }
    XBT_DEBUG("Create parallel execute action %p", action);
  
    return action;
  }
  
 -
 -  xbt_assert((model == surf_workstation_model) || (model == surf_vm_workstation_model));
 -
++//FIXME: REMOVE not used
+ static surf_model_t get_ws_model_from_action(smx_action_t action)
+ {
+   xbt_assert(action->type == SIMIX_ACTION_EXECUTE);
+   smx_host_t host = action->execution.host;
+   surf_model_t model = surf_resource_model(host, SURF_WKS_LEVEL);
+   return model;
+ }
  void SIMIX_pre_host_execution_destroy(smx_simcall_t simcall, smx_action_t action){
    SIMIX_host_execution_destroy(action);
  }
  void SIMIX_host_execution_destroy(smx_action_t action){
    XBT_DEBUG("Destroy action %p", action);
  
 -  surf_model_t ws_model = get_ws_model_from_action(action);
 -
    if (action->execution.surf_exec) {
 -    ws_model->action_unref(action->execution.surf_exec);
 +    surf_action_unref(action->execution.surf_exec);
      action->execution.surf_exec = NULL;
    }
    xbt_free(action->name);
@@@ -471,8 -606,10 +588,8 @@@ void SIMIX_pre_host_execution_cancel(sm
  void SIMIX_host_execution_cancel(smx_action_t action){
    XBT_DEBUG("Cancel action %p", action);
  
 -  surf_model_t ws_model = get_ws_model_from_action(action);
 -
    if (action->execution.surf_exec)
 -    ws_model->action_cancel(action->execution.surf_exec);
 +    surf_action_cancel(action->execution.surf_exec);
  }
  
  double SIMIX_pre_host_execution_get_remains(smx_simcall_t simcall, smx_action_t action){
  }
  double SIMIX_host_execution_get_remains(smx_action_t action){
    double result = 0.0;
 -  surf_model_t ws_model = get_ws_model_from_action(action);
  
    if (action->state == SIMIX_RUNNING)
 -    result = ws_model->get_remains(action->execution.surf_exec);
 +    result = surf_action_get_remains(action->execution.surf_exec);
  
    return result;
  }
@@@ -496,13 -634,42 +613,38 @@@ e_smx_state_t SIMIX_host_execution_get_
  
  void SIMIX_pre_host_execution_set_priority(smx_simcall_t simcall, smx_action_t action,
                                        double priority){
-   return SIMIX_host_execution_set_priority(action, priority);
+   SIMIX_host_execution_set_priority(action, priority);
  }
  void SIMIX_host_execution_set_priority(smx_action_t action, double priority){
 -  surf_model_t ws_model = get_ws_model_from_action(action);
    if(action->execution.surf_exec)
 -    ws_model->set_priority(action->execution.surf_exec, priority);
 +      surf_action_set_priority(action->execution.surf_exec, priority);
  }
  
 -  surf_model_t ws_model = get_ws_model_from_action(action);
+ void SIMIX_pre_host_execution_set_bound(smx_simcall_t simcall, smx_action_t action,
+                                       double bound){
+   SIMIX_host_execution_set_bound(action, bound);
+ }
+ void SIMIX_host_execution_set_bound(smx_action_t action, double bound){
 -    ws_model->set_bound(action->execution.surf_exec, bound);
+   if(action->execution.surf_exec)
 -  surf_model_t ws_model = get_ws_model_from_action(action);
 -
++      surf_cpu_action_set_bound(action->execution.surf_exec, bound);
+ }
+ void SIMIX_pre_host_execution_set_affinity(smx_simcall_t simcall,
+     smx_action_t action, smx_host_t host, unsigned long mask){
+   SIMIX_host_execution_set_affinity(action, host, mask);
+ }
+ void SIMIX_host_execution_set_affinity(smx_action_t action, smx_host_t host, unsigned long mask){
 -    ws_model->set_affinity(action->execution.surf_exec, host, mask);
+   xbt_assert(action->type == SIMIX_ACTION_EXECUTE);
+   if (action->execution.surf_exec) {
+     /* just a double check to confirm that this host is the host where this task is running. */
+     xbt_assert(action->execution.host == host);
++    surf_cpu_action_set_affinity(action->execution.surf_exec, host, mask);
+   }
+ }
  void SIMIX_pre_host_execution_wait(smx_simcall_t simcall, smx_action_t action){
  
    XBT_DEBUG("Wait for execution of action %p, state %d", action, (int)action->state);
  
  void SIMIX_host_execution_suspend(smx_action_t action)
  {
 -  surf_model_t ws_model = get_ws_model_from_action(action);
 -
    if(action->execution.surf_exec)
 -    ws_model->suspend(action->execution.surf_exec);
 +    surf_action_suspend(action->execution.surf_exec);
  }
  
  void SIMIX_host_execution_resume(smx_action_t action)
  {
 -  surf_model_t ws_model = get_ws_model_from_action(action);
 -
    if(action->execution.surf_exec)
 -    ws_model->resume(action->execution.surf_exec);
 +    surf_action_resume(action->execution.surf_exec);
  }
  
  void SIMIX_execution_finish(smx_action_t action)
  {
    xbt_fifo_item_t item;
    smx_simcall_t simcall;
 -  surf_model_t ws_model = get_ws_model_from_action(action);
  
    xbt_fifo_foreach(action->simcalls, item, simcall, smx_simcall_t) {
  
              (int)action->state);
      }
      /* check if the host is down */
 -    if (ws_model->extension.workstation.get_state(simcall->issuer->smx_host) != SURF_RESOURCE_ON) {
 +    if (surf_resource_get_state(surf_workstation_resource_priv(simcall->issuer->smx_host)) != SURF_RESOURCE_ON) {
        simcall->issuer->context->iwannadie = 1;
      }
  
    SIMIX_host_execution_destroy(action);
  }
  
  void SIMIX_post_host_execute(smx_action_t action)
  {
 -  surf_model_t ws_model = get_ws_model_from_action(action);
 -
    if (action->type == SIMIX_ACTION_EXECUTE && /* FIMXE: handle resource failure
                                                 * for parallel tasks too */
 -      ws_model->extension.workstation.get_state(action->execution.host) == SURF_RESOURCE_OFF) {
 +      surf_resource_get_state(surf_workstation_resource_priv(action->execution.host)) == SURF_RESOURCE_OFF) {
      /* If the host running the action failed, notice it so that the asking
       * process can be killed if it runs on that host itself */
      action->state = SIMIX_FAILED;
 -  } else if (ws_model->action_state_get(action->execution.surf_exec) == SURF_ACTION_FAILED) {
 +  } else if (surf_action_get_state(action->execution.surf_exec) == SURF_ACTION_FAILED) {
      /* If the host running the action didn't fail, then the action was
       * canceled */
      action->state = SIMIX_CANCELED;
    }
  
    if (action->execution.surf_exec) {
 -    ws_model->action_unref(action->execution.surf_exec);
 +    surf_action_unref(action->execution.surf_exec);
      action->execution.surf_exec = NULL;
    }
  
@@@ -614,20 -788,51 +756,49 @@@ void SIMIX_pre_set_category(smx_simcall
  }
  void SIMIX_set_category(smx_action_t action, const char *category)
  {
 -  surf_model_t ws_model = get_ws_model_from_action(action);
 -
    if (action->state != SIMIX_RUNNING) return;
    if (action->type == SIMIX_ACTION_EXECUTE){
 -    ws_model->set_category(action->execution.surf_exec, category);
 +    surf_action_set_category(action->execution.surf_exec, category);
    }else if (action->type == SIMIX_ACTION_COMMUNICATE){
 -    ws_model->set_category(action->comm.surf_comm, category);
 +    surf_action_set_category(action->comm.surf_comm, category);
    }
  }
  #endif
  
 -  surf_workstation_model->extension.workstation.get_params(ind_vm, params);
+ /**
+  * \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.set_params(ind_vm, params);
++  surf_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_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);
 +  return surf_workstation_get_storage_list(host);
  }
  typedef struct s_smx_host_priv {
    xbt_swag_t process_list;
    xbt_dynar_t auto_restart_processes;
+   xbt_dynar_t boot_processes; 
    void *data;              /**< @brief user data */
  } s_smx_host_priv_t;
  
  static inline smx_host_priv_t SIMIX_host_priv(smx_host_t host){
 -  return xbt_lib_get_level(host, SIMIX_HOST_LEVEL);
 +  return (smx_host_priv_t) xbt_lib_get_level(host, SIMIX_HOST_LEVEL);
  }
  
 -void _SIMIX_host_free_process_arg(void *);
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
++void _SIMIX_host_free_process_arg(void *);
  smx_host_t SIMIX_host_create(const char *name, void *workstation, void *data);
  void SIMIX_host_destroy(void *host);
  
@@@ -45,13 -45,15 +48,15 @@@ xbt_swag_t SIMIX_host_get_process_list(
  double SIMIX_host_get_speed(smx_host_t host);
  double SIMIX_host_get_available_speed(smx_host_t host);
  int SIMIX_host_get_state(smx_host_t host);
+ void SIMIX_host_on(smx_host_t host);
+ void SIMIX_host_off(smx_host_t host, smx_process_t issuer);
  double SIMIX_host_get_current_power_peak(smx_host_t host);
  double SIMIX_host_get_power_peak_at(smx_host_t host, int pstate_index);
  int SIMIX_host_get_nb_pstates(smx_host_t host);
  double SIMIX_host_get_consumed_energy(smx_host_t host);
  void SIMIX_host_set_power_peak_at(smx_host_t host, int pstate_index);
  smx_action_t SIMIX_host_execute(const char *name,
-     smx_host_t host, double computation_amount, double priority);
+     smx_host_t host, double computation_amount, double priority, double bound, unsigned long affinity_mask);
  smx_action_t SIMIX_host_parallel_execute(const char *name,
      int host_nb, smx_host_t *host_list,
      double *computation_amount, double *communication_amount,
@@@ -61,6 -63,8 +66,8 @@@ void SIMIX_host_execution_cancel(smx_ac
  double SIMIX_host_execution_get_remains(smx_action_t action);
  e_smx_state_t SIMIX_host_execution_get_state(smx_action_t action);
  void SIMIX_host_execution_set_priority(smx_action_t action, double priority);
+ void SIMIX_host_execution_set_bound(smx_action_t action, double bound);
+ void SIMIX_host_execution_set_affinity(smx_action_t action, smx_host_t host, unsigned long mask);
  void SIMIX_pre_host_execution_wait(smx_simcall_t simcall, smx_action_t action);
  xbt_dict_t SIMIX_host_get_storage_list(smx_host_t host);
  
@@@ -68,6 -72,8 +75,8 @@@
  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);
@@@ -82,7 -88,7 +91,7 @@@ double SIMIX_pre_host_get_consumed_ener
  void* SIMIX_pre_host_self_get_data(smx_simcall_t);
  void* SIMIX_pre_host_get_data(smx_simcall_t, smx_host_t);
  void SIMIX_pre_host_set_data(smx_simcall_t, smx_host_t, void*);
- smx_action_t SIMIX_pre_host_execute(smx_simcall_t, const char*, smx_host_t, double, double);
+ smx_action_t SIMIX_pre_host_execute(smx_simcall_t, const char*, smx_host_t, double, double, double, unsigned long);
  smx_action_t SIMIX_pre_host_parallel_execute(smx_simcall_t, const char*, int, smx_host_t*,
                                               double*, double*, double, double);
  void SIMIX_pre_host_execution_destroy(smx_simcall_t, smx_action_t);
@@@ -90,6 -96,8 +99,8 @@@ void SIMIX_pre_host_execution_cancel(sm
  double SIMIX_pre_host_execution_get_remains(smx_simcall_t, smx_action_t);
  e_smx_state_t SIMIX_pre_host_execution_get_state(smx_simcall_t, smx_action_t);
  void SIMIX_pre_host_execution_set_priority(smx_simcall_t, smx_action_t, double);
+ void SIMIX_pre_host_execution_set_bound(smx_simcall_t simcall, smx_action_t action, double bound);
+ void SIMIX_pre_host_execution_set_affinity(smx_simcall_t simcall, smx_action_t action, smx_host_t host, unsigned long mask);
  
  void SIMIX_host_execution_suspend(smx_action_t action);
  void SIMIX_host_execution_resume(smx_action_t action);
@@@ -101,10 -109,57 +112,57 @@@ void SIMIX_pre_set_category(smx_simcall
                            const char *category);
  void SIMIX_set_category(smx_action_t action, const char *category);
  #endif
 -
 -
 -
+ /* vm related stuff */
+ smx_host_t SIMIX_vm_create(const char *name, smx_host_t ind_phys_host);
+ smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host);
+ void SIMIX_vm_destroy(smx_host_t ind_vm);
+ void SIMIX_pre_vm_destroy(smx_simcall_t simcall, smx_host_t ind_vm);
+ // --
+ void SIMIX_vm_resume(smx_host_t ind_vm, smx_process_t issuer);
+ void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm);
+ void SIMIX_vm_suspend(smx_host_t ind_vm, smx_process_t issuer);
+ void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm);
+ // --
+ void SIMIX_vm_save(smx_host_t ind_vm, smx_process_t issuer);
+ void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm);
+ void SIMIX_vm_restore(smx_host_t ind_vm, smx_process_t issuer);
+ void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm);
+ // --
+ void SIMIX_vm_start(smx_host_t ind_vm);
+ void SIMIX_pre_vm_start(smx_simcall_t simcall, smx_host_t ind_vm);
+ void SIMIX_vm_shutdown(smx_host_t ind_vm, smx_process_t issuer);
+ void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm);
+ // --
+ void SIMIX_vm_set_state(smx_host_t ind_vm, int state);
+ void SIMIX_pre_vm_set_state(smx_simcall_t simcall, smx_host_t ind_vm, int state);
+ int SIMIX_vm_get_state(smx_host_t ind_vm);
+ int SIMIX_pre_vm_get_state(smx_simcall_t simcall, smx_host_t ind_vm);
+ // --
+ void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm);
+ void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm);
+ void *SIMIX_vm_get_pm(smx_host_t ind_vm);
+ void *SIMIX_pre_vm_get_pm(smx_simcall_t simcall, smx_host_t ind_vm);
+ void SIMIX_vm_set_bound(smx_host_t ind_vm, double bound);
+ void SIMIX_pre_vm_set_bound(smx_simcall_t simcall, smx_host_t ind_vm, double bound);
+ void SIMIX_vm_set_affinity(smx_host_t ind_vm, smx_host_t ind_pm, unsigned long mask);
+ void SIMIX_pre_vm_set_affinity(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_pm, unsigned long mask);
+ void SIMIX_host_get_params(smx_host_t ind_vm, ws_params_t params);
+ void SIMIX_pre_host_get_params(smx_simcall_t simcall, smx_host_t ind_vm, ws_params_t params);
  
+ void SIMIX_host_set_params(smx_host_t ind_vm, ws_params_t params);
+ void SIMIX_pre_host_set_params(smx_simcall_t simcall, smx_host_t ind_vm, ws_params_t params);
 +#ifdef __cplusplus
 +}
 +#endif
  
  #endif
  
diff --combined src/simix/smx_process.c
@@@ -491,7 -491,8 +491,8 @@@ smx_action_t SIMIX_process_suspend(smx_
        return NULL;
      }
    } else {
-     return SIMIX_host_execute("suspend", process->smx_host, 0.0, 1.0);
+     /* FIXME: computation size is zero. Is it okay that bound is zero ? */
+     return SIMIX_host_execute("suspend", process->smx_host, 0.0, 1.0, 0.0, 0);
    }
  }
  
@@@ -693,9 -694,11 +694,9 @@@ smx_action_t SIMIX_process_sleep(smx_pr
  {
    smx_action_t action;
    smx_host_t host = process->smx_host;
 -  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
  
    /* check if the host is active */
 -  if (ws_model->extension.
 -      workstation.get_state(host) != SURF_RESOURCE_ON) {
 +  if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) {
      THROWF(host_error, 0, "Host %s failed, you cannot call this function",
             sg_host_name(host));
    }
  
    action->sleep.host = host;
    action->sleep.surf_sleep =
 -      ws_model->extension.workstation.sleep(host, duration);
 +      surf_workstation_sleep(host, duration);
  
 -  ws_model->action_data_set(action->sleep.surf_sleep, action);
 +  surf_action_set_data(action->sleep.surf_sleep, action);
    XBT_DEBUG("Create sleep action %p", action);
  
    return action;
@@@ -722,9 -725,13 +723,11 @@@ void SIMIX_post_process_sleep(smx_actio
    smx_simcall_t simcall;
    e_smx_state_t state;
  
 -  smx_host_t host = action->sleep.host;
 -  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
+   xbt_assert(action->type == SIMIX_ACTION_SLEEP);
    while ((simcall = xbt_fifo_shift(action->simcalls))) {
  
 -    switch(ws_model->action_state_get(action->sleep.surf_sleep)){
 +    switch(surf_action_get_state(action->sleep.surf_sleep)){
        case SURF_ACTION_FAILED:
          simcall->issuer->context->iwannadie = 1;
          //SMX_EXCEPTION(simcall->issuer, host_error, 0, "Host failed");
          THROW_IMPOSSIBLE;
          break;
      }
 -    if (ws_model->extension.
 -        workstation.get_state(simcall->issuer->smx_host) != SURF_RESOURCE_ON) {
 +    if (surf_resource_get_state(surf_workstation_resource_priv(simcall->issuer->smx_host)) != SURF_RESOURCE_ON) {
        simcall->issuer->context->iwannadie = 1;
      }
      simcall_process_sleep__set__result(simcall, state);
  void SIMIX_process_sleep_destroy(smx_action_t action)
  {
    XBT_DEBUG("Destroy action %p", action);
+   xbt_assert(action->type == SIMIX_ACTION_SLEEP);
    if (action->sleep.surf_sleep)
 -    action->sleep.surf_sleep->model_obj->action_unref(action->sleep.surf_sleep);
 +    surf_action_unref(action->sleep.surf_sleep);
    xbt_mallocator_release(simix_global->action_mallocator, action);
  }
  
  void SIMIX_process_sleep_suspend(smx_action_t action)
  {
 -  smx_host_t host = action->sleep.host;
 -  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 -
 -  ws_model->suspend(action->sleep.surf_sleep);
+   xbt_assert(action->type == SIMIX_ACTION_SLEEP);
 +  surf_action_suspend(action->sleep.surf_sleep);
  }
  
  void SIMIX_process_sleep_resume(smx_action_t action)
  {
 -  smx_host_t host = action->sleep.host;
 -  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 -  XBT_DEBUG("%p ws_model", ws_model);
 -
 -  ws_model->resume(action->sleep.surf_sleep);
+   xbt_assert(action->type == SIMIX_ACTION_SLEEP);
 +  surf_action_resume(action->sleep.surf_sleep);
  }
  
  /** 
@@@ -1,4 -1,4 +1,4 @@@
- /* 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 TULONG(n) (n, unsigned long, ul)
  #define TFLOAT(n) (n, float, f)
  #define TDOUBLE(n) (n, double, d)
 -#define TPTR(n) (n, void*, p)
 +#define TDPTR(n) (n, void*, dp, void*)
 +#define TFPTR(n) (n, FPtr, fp, FPtr)
  #define TCPTR(n) (n, const void*, cp)
  #define TSIZE(n) (n, size_t, si)
  #define TVOID(n) (n, void)
 -#define TSPEC(n,t) (n, t, p)
 +#define TDSPEC(n,t) (n, t, dp, void*)
 +#define TFSPEC(n,t) (n, t, fp, FPtr)
  
  /* use comma or nothing to separate elements*/
  #define SIMCALL_SEP_COMMA ,
  #define SIMCALL_SEP_NOTHING
  
  /* get the name of the parameter */
 -#define SIMCALL_NAME_(name, type, field) name
 +#define SIMCALL_NAME_(name, type, field, ...) name
  #define SIMCALL_NAME(i, v) SIMCALL_NAME_ v
  
 +/* get the cast of the parameter */
 +#define SIMCALL_CASTTYPE_(name, type, field, cast) (cast)
 +#define SIMCALL_NOCASTTYPE_(name, type, field) 
 +#define SIMCALL_CASTTYPE(...) MAYBE5(,##__VA_ARGS__, SIMCALL_CASTTYPE_, SIMCALL_NOCASTTYPE_) (__VA_ARGS__)
 +
 +/* get the uncast of the parameter */
 +#define SIMCALL_UNCASTTYPE_(name, type, field, cast) (type)
 +#define SIMCALL_NOUNCASTTYPE_(name, type, field) 
 +#define SIMCALL_UNCASTTYPE(...) MAYBE5(,##__VA_ARGS__, SIMCALL_UNCASTTYPE_, SIMCALL_NOUNCASTTYPE_) (__VA_ARGS__)
 +
  /* get the %s format code of the parameter */
 -#define SIMCALL_FORMAT_(name, type, field) %field
 +#define SIMCALL_FORMAT_(name, type, field, ...) %field
  #define SIMCALL_FORMAT(i, v) SIMCALL_FORMAT_ v
  
  /* get the field of the parameter */
 -#define SIMCALL_FIELD_(name, type, field) field
 +#define SIMCALL_FIELD_(name, type, field, ...) field
  #define SIMCALL_FIELD(i, v) SIMCALL_FIELD_ v
  
  /* get the parameter declaration */
 -#define SIMCALL_ARG_(name, type, field) type name
 +#define SIMCALL_ARG_(name, type, field, ...) type name
  #define SIMCALL_ARG(i, v) SIMCALL_ARG_ v
  
  /* get the parameter initialisation field */
 -#define SIMCALL_INIT_FIELD_(name, type, field) .field = name
 +#define SIMCALL_INIT_FIELD_(name, type, field, ...) .field = SIMCALL_CASTTYPE(name, type, field,##__VA_ARGS__) name
  #define SIMCALL_INIT_FIELD(i, d, v) self->simcall.args[i]SIMCALL_INIT_FIELD_ v;
  
  /* get the case of the parameter */
 -#define SIMCALL_CASE_PARAM_(name, type, field) field
 -#define SIMCALL_CASE_PARAM(i, v) simcall->args[i].SIMCALL_CASE_PARAM_ v
 +#define SIMCALL_CASE_PARAM_(name, type, field, ...) field
 +#define SIMCALL_CASE_PARAM(i, v) SIMCALL_UNCASTTYPE v simcall->args[i].SIMCALL_CASE_PARAM_ v
  
  /* generate some code for SIMCALL_CASE if the simcall has an answer */
 +#define MAYBE5(_0, _1, _2, _3, _4, func, ...) func
 +#define MAYBE3(_0, _1, _2, func, ...) func
  #define MAYBE2(_0, _1, func, ...) func
  
 -#define SIMCALL_WITH_RESULT_BEGIN(name, type, field) simcall->result.field =
 +#define SIMCALL_WITH_RESULT_BEGIN(name, type, field, ...) simcall->result.field =
  #define SIMCALL_WITHOUT_RESULT_BEGIN(name, type, field)
  #define SIMCALL_RESULT_BEGIN_(name, type, ...)\
 -        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_RESULT_BEGIN, SIMCALL_WITHOUT_RESULT_BEGIN)\
 +        MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_RESULT_BEGIN, SIMCALL_WITH_RESULT_BEGIN, SIMCALL_WITHOUT_RESULT_BEGIN)\
        (name, type, __VA_ARGS__)
  #define SIMCALL_RESULT_BEGIN(answer, res) answer(SIMCALL_RESULT_BEGIN_ res)
  
  #define SIMCALL_WITH_FUNC_SIMCALL(name, type, field) smx_simcall_t simcall = 
  #define SIMCALL_WITHOUT_FUNC_SIMCALL(name, type, field)
  #define SIMCALL_FUNC_SIMCALL_(name, type, ...)\
 -        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_FUNC_SIMCALL, SIMCALL_WITHOUT_FUNC_SIMCALL)\
 +        MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_FUNC_SIMCALL, SIMCALL_WITH_FUNC_SIMCALL, SIMCALL_WITHOUT_FUNC_SIMCALL)\
        (name, type, __VA_ARGS__)
  #define SIMCALL_FUNC_SIMCALL(res) SIMCALL_FUNC_SIMCALL_ res
  
 -#define SIMCALL_WITH_FUNC_RETURN(name, type, field) return self->simcall.result.field;
 +#define SIMCALL_WITH_FUNC_RETURN(name, type, field, ...) return self->simcall.result.field;
  #define SIMCALL_WITHOUT_FUNC_RETURN(name, type, field)
  #define SIMCALL_FUNC_RETURN_(name, type, ...)\
 -        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_FUNC_RETURN, SIMCALL_WITHOUT_FUNC_RETURN)\
 +        MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_FUNC_RETURN, SIMCALL_WITH_FUNC_RETURN, SIMCALL_WITHOUT_FUNC_RETURN)\
        (name, type, __VA_ARGS__)
  #define SIMCALL_FUNC_RETURN(res) SIMCALL_FUNC_RETURN_ res
  
  /* generate the simcalls args getter/setter */
  #define SIMCALL_ARG_GETSET_(i, name, v) \
    static inline SIMCALL_FUNC_RETURN_TYPE(v) SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME(name), get, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall){\
 -    return simcall->args[i].SIMCALL_FIELD_ v ;\
 +    return (SIMCALL_FUNC_RETURN_TYPE(v)) simcall->args[i].SIMCALL_FIELD_ v ;\
    }\
    static inline void SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME(name), set, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall, SIMCALL_ARG_ v){\
 -    simcall->args[i].SIMCALL_FIELD_ v = SIMCALL_NAME_ v ;\
 +    simcall->args[i].SIMCALL_FIELD_ v = SIMCALL_CASTTYPE v SIMCALL_NAME_ v ;\
    }
  
  #define SIMCALL_ARG_GETSET(type, name, answer, res, ...)\
  /* generate the simcalls result getter/setter */
  #define SIMCALL_WITH_RES_GETSET(name, v) \
    static inline SIMCALL_FUNC_RETURN_TYPE(v) SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME((name)), get, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall){\
 -    return simcall->result.SIMCALL_FIELD_ v ;\
 +    return (SIMCALL_FUNC_RETURN_TYPE(v)) simcall->result.SIMCALL_FIELD_ v ;\
    }\
    static inline void SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME((name)), set, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall, SIMCALL_ARG_ v){\
      simcall->result.SIMCALL_FIELD_ v = SIMCALL_NAME_ v ;\
    }
  #define SIMCALL_WITHOUT_RES_GETSET(name, v)
  #define SIMCALL_RES_GETSET__(name, type, ...)\
 -        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_RES_GETSET, SIMCALL_WITHOUT_RES_GETSET)
 +        MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_RES_GETSET, SIMCALL_WITH_RES_GETSET, SIMCALL_WITHOUT_RES_GETSET)
  #define SIMCALL_RES_GETSET_(scname, v)\
          SIMCALL_RES_GETSET__ v (scname, v)
  #define SIMCALL_RES_GETSET(type, name, answer, res, ...)\
    inline void SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME((name)), set, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall, SIMCALL_ARG_ v);
  #define SIMCALL_WITHOUT_RES_GETSET_PROTO(name, v)
  #define SIMCALL_RES_GETSET_PROTO__(name, type, ...)\
 -        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_RES_GETSET_PROTO, SIMCALL_WITHOUT_RES_GETSET_PROTO)
 +        MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_RES_GETSET_PROTO, SIMCALL_WITHOUT_RES_GETSET_PROTO, SIMCALL_WITHOUT_RES_GETSET_PROTO)
  #define SIMCALL_RES_GETSET_PROTO_(scname, v)\
          SIMCALL_RES_GETSET_PROTO__ v (scname, v)
  #define SIMCALL_RES_GETSET_PROTO(type, name, answer, res, ...)\
  
  /* the list of simcalls definitions */
  #define SIMCALL_LIST1(ACTION, sep) \
 -ACTION(SIMCALL_HOST_GET_BY_NAME, host_get_by_name, WITH_ANSWER, TSPEC(result, smx_host_t), TSTRING(name)) sep \
 -ACTION(SIMCALL_HOST_GET_NAME, host_get_name, WITH_ANSWER, TSTRING(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_ON, host_on, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_OFF, host_off, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_GET_PROPERTIES, host_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_GET_CORE, host_get_core, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_GET_PROCESS_LIST, host_get_process_list, WITH_ANSWER, TSPEC(result, xbt_swag_t), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_GET_SPEED, host_get_speed, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_GET_AVAILABLE_SPEED, host_get_available_speed, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_GET_STATE, host_get_state, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_GET_DATA, host_get_data, WITH_ANSWER, TPTR(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_SET_DATA, host_set_data, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t), TPTR(data)) sep \
 -ACTION(SIMCALL_HOST_EXECUTE, host_execute, WITH_ANSWER, TSPEC(result, smx_action_t), TSTRING(name), TSPEC(host, smx_host_t), TDOUBLE(computation_amount), TDOUBLE(priority), TDOUBLE(bound), TULONG(affinity_mask)) sep \
 -ACTION(SIMCALL_HOST_GET_CURRENT_POWER_PEAK, host_get_current_power_peak, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_GET_POWER_PEAK_AT, host_get_power_peak_at, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t), TINT(pstate_index)) sep \
 -ACTION(SIMCALL_HOST_GET_NB_PSTATES, host_get_nb_pstates, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_SET_POWER_PEAK_AT, host_set_power_peak_at, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t), TINT(pstate_index)) sep \
 -ACTION(SIMCALL_HOST_GET_CONSUMED_ENERGY, host_get_consumed_energy, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_HOST_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_HOST_GET_BY_NAME, host_get_by_name, WITH_ANSWER, TDSPEC(result, smx_host_t), TSTRING(name)) sep \
 +ACTION(SIMCALL_HOST_GET_NAME, host_get_name, WITH_ANSWER, TSTRING(result), TDSPEC(host, smx_host_t)) sep \
++ACTION(SIMCALL_HOST_ON, host_on, WITH_ANSWER, TVOID(result), TDSPEC(host, smx_host_t)) sep \
++ACTION(SIMCALL_HOST_OFF, host_off, WITH_ANSWER, TVOID(result), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_GET_PROPERTIES, host_get_properties, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_GET_CORE, host_get_core, WITH_ANSWER, TINT(result), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_GET_PROCESS_LIST, host_get_process_list, WITH_ANSWER, TDSPEC(result, xbt_swag_t), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_GET_SPEED, host_get_speed, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_GET_AVAILABLE_SPEED, host_get_available_speed, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_GET_STATE, host_get_state, WITH_ANSWER, TINT(result), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_GET_DATA, host_get_data, WITH_ANSWER, TDPTR(result), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_SET_DATA, host_set_data, WITH_ANSWER, TVOID(result), TDSPEC(host, smx_host_t), TDPTR(data)) sep \
 +ACTION(SIMCALL_HOST_GET_CURRENT_POWER_PEAK, host_get_current_power_peak, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_GET_POWER_PEAK_AT, host_get_power_peak_at, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t), TINT(pstate_index)) sep \
 +ACTION(SIMCALL_HOST_GET_NB_PSTATES, host_get_nb_pstates, WITH_ANSWER, TINT(result), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_SET_POWER_PEAK_AT, host_set_power_peak_at, WITH_ANSWER, TVOID(result), TDSPEC(host, smx_host_t), TINT(pstate_index)) sep \
 +ACTION(SIMCALL_HOST_GET_CONSUMED_ENERGY, host_get_consumed_energy, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t)) sep \
- ACTION(SIMCALL_HOST_EXECUTE, host_execute, WITH_ANSWER, TDSPEC(result, smx_action_t), TSTRING(name), TDSPEC(host, smx_host_t), TDOUBLE(computation_amount), TDOUBLE(priority)) sep \
++ACTION(SIMCALL_HOST_EXECUTE, host_execute, WITH_ANSWER, TDSPEC(result, smx_action_t), TSTRING(name), TDSPEC(host, smx_host_t), TDOUBLE(computation_amount), TDOUBLE(priority), TDOUBLE(bound), TULONG(affinity_mask)) sep \
 +ACTION(SIMCALL_HOST_PARALLEL_EXECUTE, host_parallel_execute, WITH_ANSWER, TDSPEC(result, smx_action_t), TSTRING(name), TINT(host_nb), TDSPEC(host_list, smx_host_t*), TDSPEC(computation_amount, double*), TDSPEC(communication_amount, double*), TDOUBLE(amount), TDOUBLE(rate)) sep \
 +ACTION(SIMCALL_HOST_EXECUTION_DESTROY, host_execution_destroy, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t)) sep \
 +ACTION(SIMCALL_HOST_EXECUTION_CANCEL, host_execution_cancel, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t)) sep \
 +ACTION(SIMCALL_HOST_EXECUTION_GET_REMAINS, host_execution_get_remains, WITH_ANSWER, TDOUBLE(result), TDSPEC(execution, smx_action_t)) sep \
 +ACTION(SIMCALL_HOST_EXECUTION_GET_STATE, host_execution_get_state, WITH_ANSWER, TINT(result), TDSPEC(execution, smx_action_t)) sep \
 +ACTION(SIMCALL_HOST_EXECUTION_SET_PRIORITY, host_execution_set_priority, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t), TDOUBLE(priority)) sep \
++ACTION(SIMCALL_HOST_EXECUTION_SET_BOUND, host_execution_set_bound, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t), TDOUBLE(bound)) sep \
++ACTION(SIMCALL_HOST_EXECUTION_SET_AFFINITY, host_execution_set_affinity, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t), TDSPEC(ws, smx_host_t), TULONG(mask)) sep \
 +ACTION(SIMCALL_HOST_EXECUTION_WAIT, host_execution_wait, WITHOUT_ANSWER, TINT(result), TDSPEC(execution, smx_action_t)) sep \
++ACTION(SIMCALL_HOST_GET_PARAMS, host_get_params, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDSPEC(params, ws_params_t)) sep \
++ACTION(SIMCALL_HOST_SET_PARAMS, host_set_params, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDSPEC(params, ws_params_t)) sep \
++ACTION(SIMCALL_VM_CREATE, vm_create, WITH_ANSWER, TDPTR(result), TSTRING(name), TDSPEC(ind_pm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_START, vm_start, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_SET_STATE, vm_set_state, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TINT(state)) sep \
++ACTION(SIMCALL_VM_GET_STATE, vm_get_state, WITH_ANSWER, TINT(result), TDSPEC(ind_vm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_MIGRATE, vm_migrate, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDSPEC(ind_dst_pm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_GET_PM, vm_get_pm, WITH_ANSWER,    TDPTR(result),  TDSPEC(ind_vm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_SET_BOUND,    vm_set_bound,    WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDOUBLE(bound)) sep \
++ACTION(SIMCALL_VM_SET_AFFINITY, vm_set_affinity, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDSPEC(ind_pm, smx_host_t), TULONG(mask)) sep \
++ACTION(SIMCALL_VM_DESTROY,   vm_destroy,   WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_SUSPEND,   vm_suspend,   WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_RESUME,    vm_resume,    WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_SHUTDOWN,  vm_shutdown,  WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_SAVE,      vm_save,      WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
++ACTION(SIMCALL_VM_RESTORE,   vm_restore,   WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
 +ACTION(SIMCALL_HOST_GET_STORAGE_LIST, host_get_storage_list, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_PROCESS_CREATE, process_create, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t*), TSTRING(name), TFSPEC(code, xbt_main_func_t), TDPTR(data), TSTRING(hostname), TDOUBLE(kill_time), TINT(argc), TDSPEC(argv, char**), TDSPEC(properties, xbt_dict_t), TINT(auto_restart)) sep \
 +ACTION(SIMCALL_PROCESS_KILL, process_kill, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t)) sep \
  ACTION(SIMCALL_PROCESS_KILLALL, process_killall, WITH_ANSWER, TVOID(result), TINT(reset_pid)) sep \
 -ACTION(SIMCALL_PROCESS_CLEANUP, process_cleanup, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
 -ACTION(SIMCALL_PROCESS_CHANGE_HOST, process_change_host, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TSPEC(dest, smx_host_t)) sep \
 -ACTION(SIMCALL_PROCESS_SUSPEND, process_suspend, WITHOUT_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
 -ACTION(SIMCALL_PROCESS_RESUME, process_resume, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
 +ACTION(SIMCALL_PROCESS_CLEANUP, process_cleanup, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t)) sep \
 +ACTION(SIMCALL_PROCESS_CHANGE_HOST, process_change_host, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t), TDSPEC(dest, smx_host_t)) sep \
 +ACTION(SIMCALL_PROCESS_SUSPEND, process_suspend, WITHOUT_ANSWER, TVOID(result), TDSPEC(process, smx_process_t)) sep \
 +ACTION(SIMCALL_PROCESS_RESUME, process_resume, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t)) sep \
  ACTION(SIMCALL_PROCESS_COUNT, process_count, WITH_ANSWER, TINT(result)) sep \
 -ACTION(SIMCALL_PROCESS_GET_PID, process_get_PID, WITH_ANSWER, TINT(result), TSPEC(process, smx_process_t)) sep  \
 -ACTION(SIMCALL_PROCESS_GET_PPID, process_get_PPID, WITH_ANSWER, TINT(result), TSPEC(process, smx_process_t)) sep  \
 -ACTION(SIMCALL_PROCESS_GET_DATA, process_get_data, WITH_ANSWER, TPTR(result), TSPEC(process, smx_process_t)) sep \
 -ACTION(SIMCALL_PROCESS_SET_DATA, process_set_data, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TPTR(data)) sep \
 -ACTION(SIMCALL_PROCESS_GET_HOST, process_get_host, WITH_ANSWER, TSPEC(result, smx_host_t), TSPEC(process, smx_process_t)) sep \
 -ACTION(SIMCALL_PROCESS_GET_NAME, process_get_name, WITH_ANSWER, TSTRING(result), TSPEC(process, smx_process_t)) sep \
 -ACTION(SIMCALL_PROCESS_IS_SUSPENDED, process_is_suspended, WITH_ANSWER, TINT(result), TSPEC(process, smx_process_t)) sep \
 -ACTION(SIMCALL_PROCESS_GET_PROPERTIES, process_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(process, smx_process_t)) sep \
 +ACTION(SIMCALL_PROCESS_GET_PID, process_get_PID, WITH_ANSWER, TINT(result), TDSPEC(process, smx_process_t)) sep  \
 +ACTION(SIMCALL_PROCESS_GET_PPID, process_get_PPID, WITH_ANSWER, TINT(result), TDSPEC(process, smx_process_t)) sep  \
 +ACTION(SIMCALL_PROCESS_GET_DATA, process_get_data, WITH_ANSWER, TDPTR(result), TDSPEC(process, smx_process_t)) sep \
 +ACTION(SIMCALL_PROCESS_SET_DATA, process_set_data, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t), TDPTR(data)) sep \
 +ACTION(SIMCALL_PROCESS_GET_HOST, process_get_host, WITH_ANSWER, TDSPEC(result, smx_host_t), TDSPEC(process, smx_process_t)) sep \
 +ACTION(SIMCALL_PROCESS_GET_NAME, process_get_name, WITH_ANSWER, TSTRING(result), TDSPEC(process, smx_process_t)) sep \
 +ACTION(SIMCALL_PROCESS_IS_SUSPENDED, process_is_suspended, WITH_ANSWER, TINT(result), TDSPEC(process, smx_process_t)) sep \
 +ACTION(SIMCALL_PROCESS_GET_PROPERTIES, process_get_properties, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(process, smx_process_t)) sep \
  ACTION(SIMCALL_PROCESS_SLEEP, process_sleep, WITHOUT_ANSWER, TINT(result), TDOUBLE(duration)) sep \
 -ACTION(SIMCALL_PROCESS_ON_EXIT, process_on_exit, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TSPEC(fun, int_f_pvoid_t), TPTR(data)) sep \
 -ACTION(SIMCALL_PROCESS_AUTO_RESTART_SET, process_auto_restart_set, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TINT(auto_restart)) sep \
 -ACTION(SIMCALL_PROCESS_RESTART, process_restart, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(process, smx_process_t)) sep \
 -ACTION(SIMCALL_RDV_CREATE, rdv_create, WITH_ANSWER, TSPEC(result, smx_rdv_t), TSTRING(name)) sep \
 -ACTION(SIMCALL_RDV_DESTROY, rdv_destroy, WITH_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t)) sep \
 -ACTION(SIMCALL_RDV_GET_BY_NAME, rdv_get_by_name, WITH_ANSWER, TSPEC(result, smx_host_t), TSTRING(name)) sep \
 -ACTION(SIMCALL_RDV_COMM_COUNT_BY_HOST, rdv_comm_count_by_host, WITH_ANSWER, TUINT(result), TSPEC(rdv, smx_rdv_t), TSPEC(host, smx_host_t)) sep \
 -ACTION(SIMCALL_RDV_GET_HEAD, rdv_get_head, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t)) sep \
 -ACTION(SIMCALL_RDV_SET_RECV, rdv_set_receiver, WITH_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TSPEC(receiver, smx_process_t)) sep \
 -ACTION(SIMCALL_RDV_GET_RECV, rdv_get_receiver, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(rdv, smx_rdv_t)) sep \
 -ACTION(SIMCALL_COMM_IPROBE, comm_iprobe, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TINT(src), TINT(tag), TSPEC(match_fun, simix_match_func_t), TPTR(data)) sep \
 -ACTION(SIMCALL_COMM_SEND, comm_send, WITHOUT_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TPTR(src_buff), TSIZE(src_buff_size), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(timeout)) sep \
 -ACTION(SIMCALL_COMM_ISEND, comm_isend, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TPTR(src_buff), TSIZE(src_buff_size), TSPEC(match_fun, simix_match_func_t), TSPEC(clean_fun, simix_clean_func_t), TPTR(data), TINT(detached)) sep \
 -ACTION(SIMCALL_COMM_RECV, comm_recv, WITHOUT_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(timeout)) sep \
 -ACTION(SIMCALL_COMM_IRECV, comm_irecv, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data)) sep \
 -ACTION(SIMCALL_COMM_RECV_BOUNDED, comm_recv_bounded, WITHOUT_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(timeout), TDOUBLE(rate)) sep \
 -ACTION(SIMCALL_COMM_IRECV_BOUNDED, comm_irecv_bounded, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(rate)) sep \
 -ACTION(SIMCALL_COMM_DESTROY, comm_destroy, WITH_ANSWER, TVOID(result), TSPEC(comm, smx_action_t)) sep \
 -ACTION(SIMCALL_COMM_CANCEL, comm_cancel, WITH_ANSWER, TVOID(result), TSPEC(comm, smx_action_t)) sep \
 -ACTION(SIMCALL_COMM_WAITANY, comm_waitany, WITHOUT_ANSWER, TINT(result), TSPEC(comms, xbt_dynar_t)) sep \
 -ACTION(SIMCALL_COMM_WAIT, comm_wait, WITHOUT_ANSWER, TVOID(result), TSPEC(comm, smx_action_t), TDOUBLE(timeout)) sep \
 -ACTION(SIMCALL_COMM_TEST, comm_test, WITHOUT_ANSWER, TINT(result), TSPEC(comm, smx_action_t)) sep \
 -ACTION(SIMCALL_COMM_TESTANY, comm_testany, WITHOUT_ANSWER, TINT(result), TSPEC(comms, xbt_dynar_t)) sep \
 -ACTION(SIMCALL_COMM_GET_REMAINS, comm_get_remains, WITH_ANSWER, TDOUBLE(result), TSPEC(comm, smx_action_t)) sep \
 -ACTION(SIMCALL_COMM_GET_STATE, comm_get_state, WITH_ANSWER, TINT(result), TSPEC(comm, smx_action_t)) sep \
 -ACTION(SIMCALL_COMM_GET_SRC_DATA, comm_get_src_data, WITH_ANSWER, TPTR(result), TSPEC(comm, smx_action_t)) sep \
 -ACTION(SIMCALL_COMM_GET_DST_DATA, comm_get_dst_data, WITH_ANSWER, TPTR(result), TSPEC(comm, smx_action_t)) sep \
 -ACTION(SIMCALL_COMM_GET_SRC_PROC, comm_get_src_proc, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(comm, smx_action_t)) sep \
 -ACTION(SIMCALL_COMM_GET_DST_PROC, comm_get_dst_proc, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(comm, smx_action_t)) sep \
 -ACTION(SIMCALL_MUTEX_INIT, mutex_init, WITH_ANSWER, TSPEC(result, smx_mutex_t)) sep \
 -ACTION(SIMCALL_MUTEX_DESTROY, mutex_destroy, WITH_ANSWER, TVOID(result), TSPEC(mutex, smx_mutex_t)) sep \
 -ACTION(SIMCALL_MUTEX_LOCK, mutex_lock, WITHOUT_ANSWER, TVOID(result), TSPEC(mutex, smx_mutex_t)) sep \
 -ACTION(SIMCALL_MUTEX_TRYLOCK, mutex_trylock, WITH_ANSWER, TINT(result), TSPEC(mutex, smx_mutex_t)) sep \
 -ACTION(SIMCALL_MUTEX_UNLOCK, mutex_unlock, WITH_ANSWER, TVOID(result), TSPEC(mutex, smx_mutex_t)) sep \
 -ACTION(SIMCALL_COND_INIT, cond_init, WITH_ANSWER, TSPEC(result, smx_cond_t)) sep \
 -ACTION(SIMCALL_COND_DESTROY, cond_destroy, WITH_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t)) sep \
 -ACTION(SIMCALL_COND_SIGNAL, cond_signal, WITH_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t)) sep \
 -ACTION(SIMCALL_COND_WAIT, cond_wait, WITHOUT_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t), TSPEC(mutex, smx_mutex_t)) sep \
 -ACTION(SIMCALL_COND_WAIT_TIMEOUT, cond_wait_timeout, WITHOUT_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t), TSPEC(mutex, smx_mutex_t), TDOUBLE(timeout)) sep \
 -ACTION(SIMCALL_COND_BROADCAST, cond_broadcast, WITH_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t)) sep \
 -ACTION(SIMCALL_SEM_INIT, sem_init, WITH_ANSWER, TSPEC(result, smx_sem_t), TINT(capacity)) sep \
 -ACTION(SIMCALL_SEM_DESTROY, sem_destroy, WITH_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t)) sep \
 -ACTION(SIMCALL_SEM_RELEASE, sem_release, WITH_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t)) sep \
 -ACTION(SIMCALL_SEM_WOULD_BLOCK, sem_would_block, WITH_ANSWER, TINT(result), TSPEC(sem, smx_sem_t)) sep \
 -ACTION(SIMCALL_SEM_ACQUIRE, sem_acquire, WITHOUT_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t)) sep \
 -ACTION(SIMCALL_SEM_ACQUIRE_TIMEOUT, sem_acquire_timeout, WITHOUT_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t), TDOUBLE(timeout)) sep \
 -ACTION(SIMCALL_SEM_GET_CAPACITY, sem_get_capacity, WITH_ANSWER, TINT(result), TSPEC(sem, smx_sem_t)) sep \
 -ACTION(SIMCALL_FILE_GET_DATA, file_get_data, WITH_ANSWER, TPTR(result), TSPEC(fd, smx_file_t)) sep \
 -ACTION(SIMCALL_FILE_SET_DATA, file_set_data, WITH_ANSWER, TVOID(result), TSPEC(fd, smx_file_t), TPTR(data)) sep \
 -ACTION(SIMCALL_FILE_READ, file_read, WITHOUT_ANSWER, TSIZE(result), TSPEC(fd, smx_file_t), TSIZE(size)) sep \
 -ACTION(SIMCALL_FILE_WRITE, file_write, WITHOUT_ANSWER, TSIZE(result), TSPEC(fd, smx_file_t), TSIZE(size)) sep \
 -ACTION(SIMCALL_FILE_OPEN, file_open, WITHOUT_ANSWER, TSPEC(result, smx_file_t), TSTRING(mount), TSTRING(path)) sep \
 -ACTION(SIMCALL_FILE_CLOSE, file_close, WITHOUT_ANSWER, TINT(result), TSPEC(fd, smx_file_t)) sep \
 -ACTION(SIMCALL_FILE_UNLINK, file_unlink, WITH_ANSWER, TINT(result), TSPEC(fd, smx_file_t)) sep \
 -ACTION(SIMCALL_FILE_LS, file_ls, WITHOUT_ANSWER, TSPEC(result, xbt_dict_t), TSTRING(mount), TSTRING(path)) sep \
 -ACTION(SIMCALL_FILE_GET_SIZE, file_get_size, WITH_ANSWER, TSIZE(result), TSPEC(fd, smx_file_t)) sep \
 -ACTION(SIMCALL_FILE_GET_INFO, file_get_info, WITH_ANSWER, TSPEC(result, xbt_dynar_t), TSPEC(fd, smx_file_t)) sep \
 +ACTION(SIMCALL_PROCESS_ON_EXIT, process_on_exit, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t), TFSPEC(fun, int_f_pvoid_t), TDPTR(data)) sep \
 +ACTION(SIMCALL_PROCESS_AUTO_RESTART_SET, process_auto_restart_set, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t), TINT(auto_restart)) sep \
 +ACTION(SIMCALL_PROCESS_RESTART, process_restart, WITH_ANSWER, TDSPEC(result, smx_process_t), TDSPEC(process, smx_process_t)) sep \
 +ACTION(SIMCALL_RDV_CREATE, rdv_create, WITH_ANSWER, TDSPEC(result, smx_rdv_t), TSTRING(name)) sep \
 +ACTION(SIMCALL_RDV_DESTROY, rdv_destroy, WITH_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t)) sep \
 +ACTION(SIMCALL_RDV_GET_BY_NAME, rdv_get_by_name, WITH_ANSWER, TDSPEC(result, smx_host_t), TSTRING(name)) sep \
 +ACTION(SIMCALL_RDV_COMM_COUNT_BY_HOST, rdv_comm_count_by_host, WITH_ANSWER, TUINT(result), TDSPEC(rdv, smx_rdv_t), TDSPEC(host, smx_host_t)) sep \
 +ACTION(SIMCALL_RDV_GET_HEAD, rdv_get_head, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t)) sep \
 +ACTION(SIMCALL_RDV_SET_RECV, rdv_set_receiver, WITH_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t), TDSPEC(receiver, smx_process_t)) sep \
 +ACTION(SIMCALL_RDV_GET_RECV, rdv_get_receiver, WITH_ANSWER, TDSPEC(result, smx_process_t), TDSPEC(rdv, smx_rdv_t)) sep \
 +ACTION(SIMCALL_COMM_IPROBE, comm_iprobe, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t), TINT(src), TINT(tag), TFSPEC(match_fun, simix_match_func_t), TDPTR(data)) sep \
 +ACTION(SIMCALL_COMM_SEND, comm_send, WITHOUT_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TDPTR(src_buff), TSIZE(src_buff_size), TFSPEC(match_fun, simix_match_func_t), TDPTR(data), TDOUBLE(timeout)) sep \
 +ACTION(SIMCALL_COMM_ISEND, comm_isend, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TDPTR(src_buff), TSIZE(src_buff_size), TFSPEC(match_fun, simix_match_func_t), TFSPEC(clean_fun, simix_clean_func_t), TDPTR(data), TINT(detached)) sep \
 +ACTION(SIMCALL_COMM_RECV, comm_recv, WITHOUT_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t), TDPTR(dst_buff), TDSPEC(dst_buff_size, size_t*), TFSPEC(match_fun, simix_match_func_t), TDPTR(data), TDOUBLE(timeout)) sep \
 +ACTION(SIMCALL_COMM_IRECV, comm_irecv, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t), TDPTR(dst_buff), TDSPEC(dst_buff_size, size_t*), TFSPEC(match_fun, simix_match_func_t), TDPTR(data)) sep \
 +ACTION(SIMCALL_COMM_RECV_BOUNDED, comm_recv_bounded, WITHOUT_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t), TDPTR(dst_buff), TDSPEC(dst_buff_size, size_t*), TFSPEC(match_fun, simix_match_func_t), TDPTR(data), TDOUBLE(timeout), TDOUBLE(rate)) sep \
 +ACTION(SIMCALL_COMM_IRECV_BOUNDED, comm_irecv_bounded, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t), TDPTR(dst_buff), TDSPEC(dst_buff_size, size_t*), TFSPEC(match_fun, simix_match_func_t), TDPTR(data), TDOUBLE(rate)) sep \
 +ACTION(SIMCALL_COMM_DESTROY, comm_destroy, WITH_ANSWER, TVOID(result), TDSPEC(comm, smx_action_t)) sep \
 +ACTION(SIMCALL_COMM_CANCEL, comm_cancel, WITH_ANSWER, TVOID(result), TDSPEC(comm, smx_action_t)) sep \
 +ACTION(SIMCALL_COMM_WAITANY, comm_waitany, WITHOUT_ANSWER, TINT(result), TDSPEC(comms, xbt_dynar_t)) sep \
 +ACTION(SIMCALL_COMM_WAIT, comm_wait, WITHOUT_ANSWER, TVOID(result), TDSPEC(comm, smx_action_t), TDOUBLE(timeout)) sep \
 +ACTION(SIMCALL_COMM_TEST, comm_test, WITHOUT_ANSWER, TINT(result), TDSPEC(comm, smx_action_t)) sep \
 +ACTION(SIMCALL_COMM_TESTANY, comm_testany, WITHOUT_ANSWER, TINT(result), TDSPEC(comms, xbt_dynar_t)) sep \
 +ACTION(SIMCALL_COMM_GET_REMAINS, comm_get_remains, WITH_ANSWER, TDOUBLE(result), TDSPEC(comm, smx_action_t)) sep \
 +ACTION(SIMCALL_COMM_GET_STATE, comm_get_state, WITH_ANSWER, TINT(result), TDSPEC(comm, smx_action_t)) sep \
 +ACTION(SIMCALL_COMM_GET_SRC_DATA, comm_get_src_data, WITH_ANSWER, TDPTR(result), TDSPEC(comm, smx_action_t)) sep \
 +ACTION(SIMCALL_COMM_GET_DST_DATA, comm_get_dst_data, WITH_ANSWER, TDPTR(result), TDSPEC(comm, smx_action_t)) sep \
 +ACTION(SIMCALL_COMM_GET_SRC_PROC, comm_get_src_proc, WITH_ANSWER, TDSPEC(result, smx_process_t), TDSPEC(comm, smx_action_t)) sep \
 +ACTION(SIMCALL_COMM_GET_DST_PROC, comm_get_dst_proc, WITH_ANSWER, TDSPEC(result, smx_process_t), TDSPEC(comm, smx_action_t)) sep \
 +ACTION(SIMCALL_MUTEX_INIT, mutex_init, WITH_ANSWER, TDSPEC(result, smx_mutex_t)) sep \
 +ACTION(SIMCALL_MUTEX_DESTROY, mutex_destroy, WITH_ANSWER, TVOID(result), TDSPEC(mutex, smx_mutex_t)) sep \
 +ACTION(SIMCALL_MUTEX_LOCK, mutex_lock, WITHOUT_ANSWER, TVOID(result), TDSPEC(mutex, smx_mutex_t)) sep \
 +ACTION(SIMCALL_MUTEX_TRYLOCK, mutex_trylock, WITH_ANSWER, TINT(result), TDSPEC(mutex, smx_mutex_t)) sep \
 +ACTION(SIMCALL_MUTEX_UNLOCK, mutex_unlock, WITH_ANSWER, TVOID(result), TDSPEC(mutex, smx_mutex_t)) sep \
 +ACTION(SIMCALL_COND_INIT, cond_init, WITH_ANSWER, TDSPEC(result, smx_cond_t)) sep \
 +ACTION(SIMCALL_COND_DESTROY, cond_destroy, WITH_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t)) sep \
 +ACTION(SIMCALL_COND_SIGNAL, cond_signal, WITH_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t)) sep \
 +ACTION(SIMCALL_COND_WAIT, cond_wait, WITHOUT_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t), TDSPEC(mutex, smx_mutex_t)) sep \
 +ACTION(SIMCALL_COND_WAIT_TIMEOUT, cond_wait_timeout, WITHOUT_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t), TDSPEC(mutex, smx_mutex_t), TDOUBLE(timeout)) sep \
 +ACTION(SIMCALL_COND_BROADCAST, cond_broadcast, WITH_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t)) sep \
 +ACTION(SIMCALL_SEM_INIT, sem_init, WITH_ANSWER, TDSPEC(result, smx_sem_t), TINT(capacity)) sep \
 +ACTION(SIMCALL_SEM_DESTROY, sem_destroy, WITH_ANSWER, TVOID(result), TDSPEC(sem, smx_sem_t)) sep \
 +ACTION(SIMCALL_SEM_RELEASE, sem_release, WITH_ANSWER, TVOID(result), TDSPEC(sem, smx_sem_t)) sep \
 +ACTION(SIMCALL_SEM_WOULD_BLOCK, sem_would_block, WITH_ANSWER, TINT(result), TDSPEC(sem, smx_sem_t)) sep \
 +ACTION(SIMCALL_SEM_ACQUIRE, sem_acquire, WITHOUT_ANSWER, TVOID(result), TDSPEC(sem, smx_sem_t)) sep \
 +ACTION(SIMCALL_SEM_ACQUIRE_TIMEOUT, sem_acquire_timeout, WITHOUT_ANSWER, TVOID(result), TDSPEC(sem, smx_sem_t), TDOUBLE(timeout)) sep \
 +ACTION(SIMCALL_SEM_GET_CAPACITY, sem_get_capacity, WITH_ANSWER, TINT(result), TDSPEC(sem, smx_sem_t)) sep \
 +ACTION(SIMCALL_FILE_GET_DATA, file_get_data, WITH_ANSWER, TDPTR(result), TDSPEC(fd, smx_file_t)) sep \
 +ACTION(SIMCALL_FILE_SET_DATA, file_set_data, WITH_ANSWER, TVOID(result), TDSPEC(fd, smx_file_t), TDPTR(data)) sep \
 +ACTION(SIMCALL_FILE_READ, file_read, WITHOUT_ANSWER, TSIZE(result), TDSPEC(fd, smx_file_t),  TSIZE(size)) sep \
 +ACTION(SIMCALL_FILE_WRITE, file_write, WITHOUT_ANSWER, TSIZE(result), TDSPEC(fd, smx_file_t), TSIZE(size)) sep \
 +ACTION(SIMCALL_FILE_OPEN, file_open, WITHOUT_ANSWER, TDSPEC(result, smx_file_t), TSTRING(mount), TSTRING(path)) sep \
 +ACTION(SIMCALL_FILE_CLOSE, file_close, WITHOUT_ANSWER, TINT(result), TDSPEC(fd, smx_file_t)) sep \
 +ACTION(SIMCALL_FILE_UNLINK, file_unlink, WITH_ANSWER, TINT(result), TDSPEC(fd, smx_file_t)) sep \
 +ACTION(SIMCALL_FILE_LS, file_ls, WITHOUT_ANSWER, TDSPEC(result, xbt_dict_t), TSTRING(mount), TSTRING(path)) sep \
 +ACTION(SIMCALL_FILE_GET_SIZE, file_get_size, WITH_ANSWER, TSIZE(result), TDSPEC(fd, smx_file_t)) sep \
 +ACTION(SIMCALL_FILE_GET_INFO, file_get_info, WITH_ANSWER, TDSPEC(result, xbt_dynar_t), TDSPEC(fd, smx_file_t)) sep \
  ACTION(SIMCALL_STORAGE_GET_FREE_SIZE, storage_get_free_size, WITH_ANSWER, TSIZE(result), TSTRING(name)) sep \
  ACTION(SIMCALL_STORAGE_GET_USED_SIZE, storage_get_used_size, WITH_ANSWER, TSIZE(result), TSTRING(name)) sep \
 -ACTION(SIMCALL_STORAGE_GET_PROPERTIES, storage_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(storage, smx_storage_t)) sep \
 -ACTION(SIMCALL_STORAGE_GET_CONTENT, storage_get_content, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(storage, smx_storage_t)) sep \
 -ACTION(SIMCALL_ASR_GET_PROPERTIES, asr_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSTRING(name)) sep 
 +ACTION(SIMCALL_STORAGE_GET_PROPERTIES, storage_get_properties, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(storage, smx_storage_t)) sep \
 +ACTION(SIMCALL_STORAGE_GET_CONTENT, storage_get_content, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(storage, smx_storage_t)) sep \
 +ACTION(SIMCALL_ASR_GET_PROPERTIES, asr_get_properties, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TSTRING(name)) sep
  
  /* SIMCALL_COMM_IS_LATENCY_BOUNDED and SIMCALL_SET_CATEGORY make things complicated
   * because they are not always present */
  #ifdef HAVE_LATENCY_BOUND_TRACKING
  #define SIMCALL_LIST2(ACTION, sep) \
 -ACTION(SIMCALL_COMM_IS_LATENCY_BOUNDED, comm_is_latency_bounded, WITH_ANSWER, TINT(result), TSPEC(comm, smx_action_t)) sep
 +ACTION(SIMCALL_COMM_IS_LATENCY_BOUNDED, comm_is_latency_bounded, WITH_ANSWER, TINT(result), TDSPEC(comm, smx_action_t)) sep
  #else
  #define SIMCALL_LIST2(ACTION, sep)
  #endif
  
  #ifdef HAVE_TRACING
  #define SIMCALL_LIST3(ACTION, sep) \
 -ACTION(SIMCALL_SET_CATEGORY, set_category, WITH_ANSWER, TVOID(result), TSPEC(action, smx_action_t), TSTRING(category)) sep
 +ACTION(SIMCALL_SET_CATEGORY, set_category, WITH_ANSWER, TVOID(result), TDSPEC(action, smx_action_t), TSTRING(category)) sep
  #else
  #define SIMCALL_LIST3(ACTION, sep)
  #endif
  
  #ifdef HAVE_MC
  #define SIMCALL_LIST4(ACTION, sep) \
 -ACTION(SIMCALL_MC_SNAPSHOT, mc_snapshot, WITH_ANSWER, TPTR(result)) sep \
 -ACTION(SIMCALL_MC_COMPARE_SNAPSHOTS, mc_compare_snapshots, WITH_ANSWER, TINT(result), TPTR(s1), TPTR(s2)) sep \
 +ACTION(SIMCALL_MC_SNAPSHOT, mc_snapshot, WITH_ANSWER, TDPTR(result)) sep \
 +ACTION(SIMCALL_MC_COMPARE_SNAPSHOTS, mc_compare_snapshots, WITH_ANSWER, TINT(result), TDPTR(s1), TDPTR(s2)) sep \
  ACTION(SIMCALL_MC_RANDOM, mc_random, WITH_ANSWER, TINT(result), TINT(min), TINT(max)) sep
  #else
  #define SIMCALL_LIST4(ACTION, sep)
@@@ -426,7 -432,6 +446,7 @@@ NUM_SIMCALL
  
  typedef int (*simix_match_func_t)(void *, void *, smx_action_t);
  typedef void (*simix_clean_func_t)(void *);
 +typedef void (*FPtr)(void); // Hide the ugliness
  
  /* Pack all possible scalar types in an union */
  union u_smx_scalar {
    float           f;
    double          d;
    size_t          si;
 -  void*           p;
 +  void*           dp;
 +  FPtr            fp;
    const void*     cp;
  };
  
@@@ -467,14 -471,8 +487,14 @@@ typedef struct s_smx_simcall 
    };
  } s_smx_simcall_t, *smx_simcall_t;
  
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
  SIMCALL_LIST(SIMCALL_RES_GETSET, SIMCALL_SEP_NOTHING)
  SIMCALL_LIST(SIMCALL_ARG_GETSET, SIMCALL_SEP_NOTHING)
 +#ifdef __cplusplus
 +}
 +#endif
  
  /******************************** General *************************************/
  
diff --combined src/simix/smx_synchro.c
@@@ -23,14 -23,16 +23,15 @@@ static void _SIMIX_sem_wait(smx_sem_t s
  static smx_action_t SIMIX_synchro_wait(smx_host_t smx_host, double timeout)
  {
    XBT_IN("(%p, %f)",smx_host,timeout);
 -  surf_model_t ws_model = surf_resource_model(smx_host, SURF_WKS_LEVEL);
    smx_action_t action;
    action = xbt_mallocator_get(simix_global->action_mallocator);
    action->type = SIMIX_ACTION_SYNCHRO;
    action->name = xbt_strdup("synchro");
    action->synchro.sleep = 
 -    ws_model->extension.workstation.sleep(smx_host, timeout);
 +    surf_workstation_sleep(smx_host, timeout);
  
 -  ws_model->action_data_set(action->synchro.sleep, action);
 +  surf_action_set_data(action->synchro.sleep, action);
    XBT_OUT();
    return action;
  }
@@@ -70,7 -72,9 +71,8 @@@ void SIMIX_synchro_destroy(smx_action_
  {
    XBT_IN("(%p)",action);
    XBT_DEBUG("Destroying synchro %p", action);
 -
 -  action->synchro.sleep->model_obj->action_unref(action->synchro.sleep);
+   xbt_assert(action->type == SIMIX_ACTION_SYNCHRO);
 +  surf_action_unref(action->synchro.sleep);
    xbt_free(action->name);
    xbt_mallocator_release(simix_global->action_mallocator, action);
    XBT_OUT();
  void SIMIX_post_synchro(smx_action_t action)
  {
    XBT_IN("(%p)",action);
 -  surf_model_t ws_model = action->synchro.sleep->model_obj;
 -
 -  if (ws_model->action_state_get(action->synchro.sleep) == SURF_ACTION_FAILED)
+   xbt_assert(action->type == SIMIX_ACTION_SYNCHRO);
 +  if (surf_action_get_state(action->synchro.sleep) == SURF_ACTION_FAILED)
      action->state = SIMIX_FAILED;
 -  else if(ws_model->action_state_get(action->synchro.sleep) == SURF_ACTION_DONE)
 +  else if(surf_action_get_state(action->synchro.sleep) == SURF_ACTION_DONE)
      action->state = SIMIX_SRC_TIMEOUT;
  
    SIMIX_synchro_finish(action);  
diff --combined src/simix/smx_vm.c
index 0000000,05a9b45..e56c555
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,402 +1,402 @@@
 -  surf_vm_workstation_model->extension.vm_workstation.create(name, ind_phys_host);
+ /* Copyright (c) 2007-2012. 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 "smx_private.h"
+ #include "xbt/sysdep.h"
+ #include "xbt/log.h"
+ #include "xbt/dict.h"
+ #include "mc/mc.h"
+ //If you need to log some stuffs, just uncomment these two lines and uses XBT_DEBUG for instance
+ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_vm, simix, "Logging specific to SIMIX (vms)");
+ /* **** create a VM **** */
+ /**
+  * \brief Internal function to create a SIMIX host.
+  * \param name name of the host to create
+  * \param data some user data (may be NULL)
+  */
+ smx_host_t SIMIX_vm_create(const char *name, smx_host_t ind_phys_host)
+ {
+   /* Create surf associated resource */
 -  surf_workstation_model->extension.workstation.get_params(vm, &params);
++  surf_vm_workstation_model_create(name, ind_phys_host);
+   smx_host_t smx_host = SIMIX_host_create(name, ind_phys_host, NULL);
+   /* We will be able to register the VM to its physical host, so that we can promptly
+    * retrieve the list VMs on the physical host. */
+   return smx_host;
+ }
+ smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host)
+ {
+   return SIMIX_vm_create(name, ind_phys_host);
+ }
+ /* works for VMs and PMs */
+ static long host_get_ramsize(smx_host_t vm, int *overcommit)
+ {
+   s_ws_params_t params;
 -  smx_host_t pm = surf_vm_workstation_model->extension.vm_workstation.get_pm(vm);
++  surf_workstation_get_params(vm, &params);
+   if (overcommit)
+     *overcommit = params.overcommit;
+   return params.ramsize;
+ }
+ /* **** start a VM **** */
+ static int __can_be_started(smx_host_t vm)
+ {
 -  xbt_dynar_t dyn_vms = surf_workstation_model->extension.workstation.get_vms(pm);
++  smx_host_t pm = surf_vm_workstation_get_pm(vm);
+   int pm_overcommit = 0;
+   long pm_ramsize = host_get_ramsize(pm, &pm_overcommit);
+   long vm_ramsize = host_get_ramsize(vm, NULL);
+   if (!pm_ramsize) {
+     /* We assume users do not want to care about ramsize. */
+     return 1;
+   }
+   if (pm_overcommit) {
+     XBT_INFO("%s allows memory overcommit.", pm->key);
+     return 1;
+   }
+   long total_ramsize_of_vms = 0;
 -  surf_vm_workstation_model->extension.vm_workstation.set_state(ind_vm, state);
++  xbt_dynar_t dyn_vms = surf_workstation_get_vms(pm);
+   {
+     unsigned int cursor = 0;
+     smx_host_t another_vm;
+     xbt_dynar_foreach(dyn_vms, cursor, another_vm) {
+       long another_vm_ramsize = host_get_ramsize(vm, NULL);
+       total_ramsize_of_vms += another_vm_ramsize;
+     }
+   }
+   if (vm_ramsize > pm_ramsize - total_ramsize_of_vms) {
+     XBT_WARN("cannnot start %s@%s due to memory shortage: vm_ramsize %ld, free %ld, pm_ramsize %ld (bytes).",
+         vm->key, pm->key, vm_ramsize, pm_ramsize - total_ramsize_of_vms, pm_ramsize);
+     xbt_dynar_free(&dyn_vms);
+     return 0;
+   }
+   xbt_dynar_free(&dyn_vms);
+       return 1;
+ }
+ void SIMIX_vm_start(smx_host_t ind_vm)
+ {
+   if (__can_be_started(ind_vm))
+     SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_RUNNING);
+   else
+     THROWF(vm_error, 0, "The VM %s cannot be started", SIMIX_host_get_name(ind_vm));
+ }
+ void SIMIX_pre_vm_start(smx_simcall_t simcall, smx_host_t ind_vm)
+ {
+   SIMIX_vm_start(ind_vm);
+ }
+ /* ***** set/get state of a VM ***** */
+ void SIMIX_vm_set_state(smx_host_t ind_vm, int state)
+ {
+   /* jump to vm_ws_set_state */
 -  return surf_vm_workstation_model->extension.vm_workstation.get_state(ind_vm);
++ surf_resource_set_state(surf_workstation_resource_priv(ind_vm), state);
+ }
+ void SIMIX_pre_vm_set_state(smx_simcall_t simcall, smx_host_t ind_vm, int state)
+ {
+   SIMIX_vm_set_state(ind_vm, state);
+ }
+ int SIMIX_vm_get_state(smx_host_t ind_vm)
+ {
 -  surf_vm_workstation_model->extension.vm_workstation.migrate(ind_vm, ind_dst_pm);
++  return surf_resource_get_state(surf_workstation_resource_priv(ind_vm));
+ }
+ int SIMIX_pre_vm_get_state(smx_simcall_t simcall, smx_host_t ind_vm)
+ {
+   return SIMIX_vm_get_state(ind_vm);
+ }
+ /**
+  * \brief Function to migrate a SIMIX VM host. 
+  *
+  * \param host the vm host to migrate (a smx_host_t)
+  */
+ void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm)
+ {
+   /* precopy migration makes the VM temporally paused */
+   e_surf_vm_state_t state = SIMIX_vm_get_state(ind_vm);
+   xbt_assert(state == SURF_VM_STATE_SUSPENDED);
+   /* jump to vm_ws_migrate(). this will update the vm location. */
 -  return surf_vm_workstation_model->extension.vm_workstation.get_pm(ind_vm);
++  surf_vm_workstation_migrate(ind_vm, ind_dst_pm);
+ }
+ void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm)
+ {
+   SIMIX_vm_migrate(ind_vm, ind_dst_pm);
+ }
+ /**
+  * \brief Function to get the physical host of the given SIMIX VM host.
+  *
+  * \param host the vm host to get_phys_host (a smx_host_t)
+  */
+ void *SIMIX_vm_get_pm(smx_host_t ind_vm)
+ {
+   /* jump to vm_ws_get_pm(). this will return the vm name. */
 -  surf_vm_workstation_model->extension.vm_workstation.set_vm_bound(ind_vm, bound);
++  return surf_vm_workstation_get_pm(ind_vm);
+ }
+ void *SIMIX_pre_vm_get_pm(smx_simcall_t simcall, smx_host_t ind_vm)
+ {
+   return SIMIX_vm_get_pm(ind_vm);
+ }
+ /**
+  * \brief Function to set the CPU bound of the given SIMIX VM host.
+  *
+  * \param host the vm host (a smx_host_t)
+  * \param bound bound (a double)
+  */
+ void SIMIX_vm_set_bound(smx_host_t ind_vm, double bound)
+ {
+   /* jump to vm_ws_set_vm_bound(). */
 -  surf_vm_workstation_model->extension.vm_workstation.set_vm_affinity(ind_vm, ind_pm, mask);
++  surf_vm_workstation_set_bound(ind_vm, bound);
+ }
+ void SIMIX_pre_vm_set_bound(smx_simcall_t simcall, smx_host_t ind_vm, double bound)
+ {
+   SIMIX_vm_set_bound(ind_vm, bound);
+ }
+ /**
+  * \brief Function to set the CPU affinity of the given SIMIX VM host.
+  *
+  * \param host the vm host (a smx_host_t)
+  * \param host the pm host (a smx_host_t)
+  * \param mask affinity mask (a unsigned long)
+  */
+ void SIMIX_vm_set_affinity(smx_host_t ind_vm, smx_host_t ind_pm, unsigned long mask)
+ {
+   /* make sure this at the MSG layer. */
+   xbt_assert(SIMIX_vm_get_pm(ind_vm) == ind_pm);
+   /* jump to vm_ws_set_vm_affinity(). */
 -  surf_vm_workstation_model->extension.vm_workstation.suspend(ind_vm);
++  surf_vm_workstation_set_affinity(ind_vm, ind_pm, mask);
+ }
+ void SIMIX_pre_vm_set_affinity(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_pm, unsigned long mask)
+ {
+   SIMIX_vm_set_affinity(ind_vm, ind_pm, mask);
+ }
+ /**
+  * \brief Function to suspend a SIMIX VM host. This function stops the exection of the
+  * VM. All the processes on this VM will pause. The state of the VM is
+  * preserved on memory. We can later resume it again.
+  *
+  * \param host the vm host to suspend (a smx_host_t)
+  */
+ void SIMIX_vm_suspend(smx_host_t ind_vm, smx_process_t issuer)
+ {
+   const char *name = SIMIX_host_get_name(ind_vm);
+   if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+     THROWF(vm_error, 0, "VM(%s) is not running", name);
+   XBT_DEBUG("suspend VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+   /* jump to vm_ws_suspend. The state will be set. */
 -  surf_vm_workstation_model->extension.vm_workstation.resume(ind_vm);
++  surf_vm_workstation_suspend(ind_vm);
+   smx_process_t smx_process, smx_process_safe;
+   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+     XBT_DEBUG("suspend %s", smx_process->name);
+     SIMIX_process_suspend(smx_process, issuer);
+   }
+   XBT_DEBUG("suspend all processes on the VM done done");
+ }
+ void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm)
+ {
+   if (simcall->issuer->smx_host == ind_vm) {
+     XBT_ERROR("cannot suspend the VM where I run");
+     DIE_IMPOSSIBLE;
+   }
+   SIMIX_vm_suspend(ind_vm, simcall->issuer);
+   XBT_DEBUG("SIMIX_pre_vm_suspend done");
+ }
+ /**
+  * \brief Function to resume a SIMIX VM host. This function restart the execution of the
+  * VM. All the processes on this VM will run again. 
+  *
+  * \param host the vm host to resume (a smx_host_t)
+  */
+ void SIMIX_vm_resume(smx_host_t ind_vm, smx_process_t issuer)
+ {
+   const char *name = SIMIX_host_get_name(ind_vm);
+   if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_SUSPENDED)
+     THROWF(vm_error, 0, "VM(%s) was not suspended", name);
+   XBT_DEBUG("resume VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+   /* jump to vm_ws_resume() */
 -  surf_vm_workstation_model->extension.vm_workstation.save(ind_vm);
++  surf_vm_workstation_resume(ind_vm);
+   smx_process_t smx_process, smx_process_safe;
+   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+     XBT_DEBUG("resume %s", smx_process->name);
+     SIMIX_process_resume(smx_process, issuer);
+   }
+ }
+ void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm)
+ {
+   SIMIX_vm_resume(ind_vm, simcall->issuer);
+ }
+ /**
+  * \brief Function to save a SIMIX VM host.
+  * This function is the same as vm_suspend, but the state of the VM is saved to the disk, and not preserved on memory.
+  * We can later restore it again.
+  *
+  * \param host the vm host to save (a smx_host_t)
+  */
+ void SIMIX_vm_save(smx_host_t ind_vm, smx_process_t issuer)
+ {
+   const char *name = SIMIX_host_get_name(ind_vm);
+   if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+     THROWF(vm_error, 0, "VM(%s) is not running", name);
+   XBT_DEBUG("save VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+   /* jump to vm_ws_save() */
 -  surf_vm_workstation_model->extension.vm_workstation.resume(ind_vm);
++  surf_vm_workstation_save(ind_vm);
+   smx_process_t smx_process, smx_process_safe;
+   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+     XBT_DEBUG("suspend %s", smx_process->name);
+     SIMIX_process_suspend(smx_process, issuer);
+   }
+ }
+ void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm)
+ {
+   SIMIX_vm_save(ind_vm, simcall->issuer);
+ }
+ /**
+  * \brief Function to restore a SIMIX VM host. This function restart the execution of the
+  * VM. All the processes on this VM will run again. 
+  *
+  * \param host the vm host to restore (a smx_host_t)
+  */
+ void SIMIX_vm_restore(smx_host_t ind_vm, smx_process_t issuer)
+ {
+   const char *name = SIMIX_host_get_name(ind_vm);
+   if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_SAVED)
+     THROWF(vm_error, 0, "VM(%s) was not saved", name);
+   XBT_DEBUG("restore VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+   /* jump to vm_ws_restore() */
 -  surf_vm_workstation_model->extension.vm_workstation.destroy(ind_vm);
++  surf_vm_workstation_resume(ind_vm);
+   smx_process_t smx_process, smx_process_safe;
+   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+     XBT_DEBUG("resume %s", smx_process->name);
+     SIMIX_process_resume(smx_process, issuer);
+   }
+ }
+ void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm)
+ {
+   SIMIX_vm_restore(ind_vm, simcall->issuer);
+ }
+ /**
+  * \brief Function to shutdown a SIMIX VM host. This function powers off the
+  * VM. All the processes on this VM will be killed. But, the state of the VM is
+  * preserved on memory. We can later start it again.
+  *
+  * \param host the vm host to shutdown (a smx_host_t)
+  */
+ void SIMIX_vm_shutdown(smx_host_t ind_vm, smx_process_t issuer)
+ {
+   const char *name = SIMIX_host_get_name(ind_vm);
+   if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+     THROWF(vm_error, 0, "VM(%s) is not running", name);
+   XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+   smx_process_t smx_process, smx_process_safe;
+   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+     XBT_DEBUG("shutdown %s", name);
+     SIMIX_process_kill(smx_process, issuer);
+   }
+   /* FIXME: we may have to do something at the surf layer, e.g., vcpu action */
+   SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_CREATED);
+ }
+ void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm)
+ {
+   SIMIX_vm_shutdown(ind_vm, simcall->issuer);
+ }
+ /**
+  * \brief Function to destroy a SIMIX VM host.
+  *
+  * \param host the vm host to destroy (a smx_host_t)
+  */
+ void SIMIX_vm_destroy(smx_host_t ind_vm)
+ {
+   /* this code basically performs a similar thing like SIMIX_host_destroy() */
+   xbt_assert((ind_vm != NULL), "Invalid parameters");
+   const char *hostname = SIMIX_host_get_name(ind_vm);
+   /* this will call the registered callback function, i.e., SIMIX_host_destroy().  */
+   xbt_lib_unset(host_lib, hostname, SIMIX_HOST_LEVEL, 1);
+   /* jump to vm_ws_destroy(). The surf level resource will be freed. */
++  surf_vm_workstation_destroy(ind_vm);
+ }
+ void SIMIX_pre_vm_destroy(smx_simcall_t simcall, smx_host_t ind_vm)
+ {
+   SIMIX_vm_destroy(ind_vm);
+ }
diff --combined src/surf/cpu.cpp
index d550b0a,0000000..2a9acf9
mode 100644,000000..100644
--- /dev/null
@@@ -1,164 -1,0 +1,250 @@@
- CpuModelPtr surf_cpu_model;
 +#include "cpu.hpp"
 +
 +extern "C" {
 +XBT_LOG_EXTERNAL_CATEGORY(surf_kernel);
 +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu, surf,
 +                                "Logging specific to the SURF cpu module");
 +}
 +
++CpuModelPtr surf_cpu_model_pm;
++CpuModelPtr surf_cpu_model_vm;
 +
 +/*********
 + * Model *
 + *********/
 +
 +void CpuModel::updateActionsStateLazy(double now, double delta)
 +{
 +  void *_action;
 +  CpuActionLmmPtr action;
 +  while ((xbt_heap_size(p_actionHeap) > 0)
 +         && (double_equals(xbt_heap_maxkey(p_actionHeap), now))) {
 +    action = dynamic_cast<CpuActionLmmPtr>(static_cast<ActionLmmPtr>(xbt_heap_pop(p_actionHeap)));
 +    XBT_CDEBUG(surf_kernel, "Something happened to action %p", action);
 +#ifdef HAVE_TRACING
 +    if (TRACE_is_enabled()) {
 +      CpuPtr cpu = (CpuPtr) lmm_constraint_id(lmm_get_cnst_from_var(p_maxminSystem, action->p_variable, 0));
 +      TRACE_surf_host_set_utilization(cpu->m_name, action->p_category,
 +                                      lmm_variable_getvalue(action->p_variable),
 +                                      action->m_lastUpdate,
 +                                      now - action->m_lastUpdate);
 +    }
 +#endif
 +
 +    action->m_finish = surf_get_clock();
 +    XBT_CDEBUG(surf_kernel, "Action %p finished", action);
 +
 +    action->updateEnergy();
 +
 +    /* set the remains to 0 due to precision problems when updating the remaining amount */
 +    action->m_remains = 0;
 +    action->setState(SURF_ACTION_DONE);
 +    action->heapRemove(p_actionHeap); //FIXME: strange call since action was already popped
 +  }
 +#ifdef HAVE_TRACING
 +  if (TRACE_is_enabled()) {
 +    //defining the last timestamp that we can safely dump to trace file
 +    //without losing the event ascending order (considering all CPU's)
 +    double smaller = -1;
 +    xbt_swag_foreach(_action, p_runningActionSet) {
 +      action = dynamic_cast<CpuActionLmmPtr>(static_cast<ActionPtr>(_action));
 +        if (smaller < 0) {
 +          smaller = action->m_lastUpdate;
 +          continue;
 +        }
 +        if (action->m_lastUpdate < smaller) {
 +          smaller = action->m_lastUpdate;
 +        }
 +    }
 +    if (smaller > 0) {
 +      TRACE_last_timestamp_to_dump = smaller;
 +    }
 +  }
 +#endif
 +  return;
 +}
 +
 +void CpuModel::updateActionsStateFull(double now, double delta)
 +{
 +  void *_action, *_next_action;
 +  CpuActionLmmPtr action = NULL;
 +  xbt_swag_t running_actions = p_runningActionSet;
 +
 +  xbt_swag_foreach_safe(_action, _next_action, running_actions) {
 +    action = dynamic_cast<CpuActionLmmPtr>(static_cast<ActionPtr>(_action));
 +#ifdef HAVE_TRACING
 +    if (TRACE_is_enabled()) {
 +      CpuPtr x = (CpuPtr) lmm_constraint_id(lmm_get_cnst_from_var
 +                              (p_maxminSystem, action->p_variable, 0));
 +
 +      TRACE_surf_host_set_utilization(x->m_name,
 +                                      action->p_category,
 +                                      lmm_variable_getvalue(action->p_variable),
 +                                      now - delta,
 +                                      delta);
 +      TRACE_last_timestamp_to_dump = now - delta;
 +    }
 +#endif
 +
 +    double_update(&(action->m_remains),
 +                  lmm_variable_getvalue(action->p_variable) * delta);
 +
 +
 +    if (action->m_maxDuration != NO_MAX_DURATION)
 +      double_update(&(action->m_maxDuration), delta);
 +
 +
 +    if ((action->m_remains <= 0) &&
 +        (lmm_get_variable_weight(action->p_variable) > 0)) {
 +      action->m_finish = surf_get_clock();
 +      action->setState(SURF_ACTION_DONE);
 +
 +    } else if ((action->m_maxDuration != NO_MAX_DURATION) &&
 +               (action->m_maxDuration <= 0)) {
 +      action->m_finish = surf_get_clock();
 +      action->setState(SURF_ACTION_DONE);
 +    }
 +    action->updateEnergy();
 +  }
 +
 +  return;
 +}
 +
 +/************
 + * Resource *
 + ************/
 +
 +double Cpu::getSpeed(double load)
 +{
 +  return load * m_powerPeak;
 +}
 +
 +double Cpu::getAvailableSpeed()
 +{
 +/* number between 0 and 1 */
 +  return m_powerScale;
 +}
 +
 +int Cpu::getCore()
 +{
 +  return m_core;
 +}
 +
 +/**********
 + * Action *
 + **********/
 +
 +void CpuActionLmm::updateRemainingLazy(double now)
 +{
 +  double delta = 0.0;
 +
 +  xbt_assert(p_stateSet == p_model->p_runningActionSet,
 +      "You're updating an action that is not running.");
 +
 +  /* bogus priority, skip it */
 +  xbt_assert(m_priority > 0,
 +      "You're updating an action that seems suspended.");
 +
 +  delta = now - m_lastUpdate;
 +
 +  if (m_remains > 0) {
 +    XBT_CDEBUG(surf_kernel, "Updating action(%p): remains was %lf, last_update was: %lf", this, m_remains, m_lastUpdate);
 +    double_update(&(m_remains), m_lastValue * delta);
 +
 +#ifdef HAVE_TRACING
 +    if (TRACE_is_enabled()) {
 +      CpuPtr cpu = (CpuPtr) lmm_constraint_id(lmm_get_cnst_from_var(p_model->p_maxminSystem, p_variable, 0));
 +      TRACE_surf_host_set_utilization(cpu->m_name, p_category, m_lastValue, m_lastUpdate, now - m_lastUpdate);
 +    }
 +#endif
 +    XBT_CDEBUG(surf_kernel, "Updating action(%p): remains is now %lf", this, m_remains);
 +  }
 +
 +  m_lastUpdate = now;
 +  m_lastValue = lmm_variable_getvalue(p_variable);
 +}
++
++void CpuActionLmm::setBound(double bound)
++{
++  XBT_IN("(%p,%g)", this, bound);
++  m_bound = bound;
++  lmm_update_variable_bound(p_model->p_maxminSystem, p_variable, bound);
++
++  if (p_model->p_updateMechanism == UM_LAZY)
++      heapRemove(p_model->p_actionHeap);
++  XBT_OUT();
++}
++
++/*
++ *
++ * This function formulates a constraint problem that pins a given task to
++ * particular cores. Currently, it is possible to pin a task to an exactly one
++ * specific core. The system links the variable object of the task to the
++ * per-core constraint object.
++ *
++ * But, the taskset command on Linux takes a mask value specifying a CPU
++ * affinity setting of a given task. If the mask value is 0x03, the given task
++ * will be executed on the first core (CPU0) or the second core (CPU1) on the
++ * given PM. The schedular will determine appropriate placements of tasks,
++ * considering given CPU affinities and task activities.
++ *
++ * How should the system formulate constraint problems for an affinity to
++ * multiple cores?
++ *
++ * The cpu argument must be the host where the task is being executed. The
++ * action object does not have the information about the location where the
++ * action is being executed.
++ */
++void CpuActionLmm::setAffinity(CpuLmmPtr cpu, unsigned long mask)
++{
++  lmm_variable_t var_obj = p_variable;
++
++  XBT_IN("(%p,%lx)", this, mask);
++
++  {
++    unsigned long nbits = 0;
++
++    /* FIXME: There is much faster algorithms doing this. */
++    unsigned long i;
++    for (i = 0; i < cpu->m_core; i++) {
++      unsigned long has_affinity = (1UL << i) & mask;
++      if (has_affinity)
++        nbits += 1;
++    }
++
++    if (nbits > 1) {
++      XBT_CRITICAL("Do not specify multiple cores for an affinity mask.");
++      XBT_CRITICAL("See the comment in cpu_action_set_affinity().");
++      DIE_IMPOSSIBLE;
++    }
++  }
++
++
++
++  unsigned long i;
++  for (i = 0; i < cpu->m_core; i++) {
++    XBT_DEBUG("clear affinity %p to cpu-%lu@%s", this, i,  cpu->m_name);
++    lmm_shrink(cpu->p_model->p_maxminSystem, cpu->p_constraintCore[i], var_obj);
++
++    unsigned long has_affinity = (1UL << i) & mask;
++    if (has_affinity) {
++      /* This function only accepts an affinity setting on the host where the
++       * task is now running. In future, a task might move to another host.
++       * But, at this moment, this function cannot take an affinity setting on
++       * that future host.
++       *
++       * It might be possible to extend the code to allow this function to
++       * accept affinity settings on a future host. We might be able to assign
++       * zero to elem->value to maintain such inactive affinity settings in the
++       * system. But, this will make the system complex. */
++      XBT_DEBUG("set affinity %p to cpu-%lu@%s", this, i, cpu->m_name);
++      lmm_expand(cpu->p_model->p_maxminSystem, cpu->p_constraintCore[i], var_obj, 1.0);
++    }
++  }
++
++  if (cpu->p_model->p_updateMechanism == UM_LAZY) {
++    /* FIXME (hypervisor): Do we need to do something for the LAZY mode? */
++  }
++
++  XBT_OUT();
++}
diff --combined src/surf/cpu.hpp
index b7c5e78,0000000..669578a
mode 100644,000000..100644
--- /dev/null
@@@ -1,93 -1,0 +1,97 @@@
- protected:
 +#include "surf.hpp"
 +
 +#ifndef SURF_MODEL_CPU_H_
 +#define SURF_MODEL_CPU_H_
 +
 +/***********
 + * Classes *
 + ***********/
 +class CpuModel;
 +typedef CpuModel *CpuModelPtr;
 +
 +class Cpu;
 +typedef Cpu *CpuPtr;
 +
 +class CpuLmm;
 +typedef CpuLmm *CpuLmmPtr;
 +
 +class CpuAction;
 +typedef CpuAction *CpuActionPtr;
 +
 +class CpuActionLmm;
 +typedef CpuActionLmm *CpuActionLmmPtr;
 +
 +/*********
 + * Model *
 + *********/
 +class CpuModel : public Model {
 +public:
 +  CpuModel(string name) : Model(name) {};
 +  CpuPtr createResource(string name);
 +  void updateActionsStateLazy(double now, double delta);
 +  void updateActionsStateFull(double now, double delta);
 +
 +  virtual void addTraces() =0;
 +};
 +
 +/************
 + * Resource *
 + ************/
 +class Cpu : virtual public Resource {
 +public:
 +  Cpu(){};
 +  Cpu(CpuModelPtr model, const char* name, xbt_dict_t properties) : Resource(model, name, properties) {};
 +  virtual ActionPtr execute(double size)=0;
 +  virtual ActionPtr sleep(double duration)=0;
 +  virtual int getCore();
 +  virtual double getSpeed(double load);
 +  virtual double getAvailableSpeed();
 +
 +  virtual double getCurrentPowerPeak()=0;
 +  virtual double getPowerPeakAt(int pstate_index)=0;
 +  virtual int getNbPstates()=0;
 +  virtual void setPowerPeakAt(int pstate_index)=0;
 +  virtual double getConsumedEnergy()=0;
 +
 +  void addTraces(void);
 +  double m_powerPeak;            /*< CPU power peak */
 +  double m_powerScale;           /*< Percentage of CPU disponible */
 +  int m_core;
++protected:
 +
 +  //virtual boost::shared_ptr<Action> execute(double size) = 0;
 +  //virtual boost::shared_ptr<Action> sleep(double duration) = 0;
 +};
 +
 +class CpuLmm : public ResourceLmm, public Cpu {
 +public:
 +  CpuLmm(){};
 +  CpuLmm(CpuModelPtr model, const char* name, xbt_dict_t properties) : ResourceLmm(), Cpu(model, name, properties) {};
++  /* Note (hypervisor): */
++  lmm_constraint_t *p_constraintCore;
 +};
 +
 +/**********
 + * Action *
 + **********/
 +class CpuAction : virtual public Action {
 +public:
 +  CpuAction(){};
 +  CpuAction(ModelPtr model, double cost, bool failed)
 +  : Action(model, cost, failed) {};
 +};
 +
 +class CpuActionLmm : public ActionLmm, public CpuAction {
 +public:
 +  CpuActionLmm(){};
 +  CpuActionLmm(ModelPtr model, double cost, bool failed)
 +  : Action(model, cost, failed), ActionLmm(model, cost, failed), CpuAction(model, cost, failed) {};
 +  void updateRemainingLazy(double now);
 +  virtual void updateEnergy()=0;
++  void setAffinity(CpuLmmPtr cpu, unsigned long mask);
++  void setBound(double bound);
++  double m_bound;
 +};
 +
 +
 +#endif /* SURF_MODEL_CPU_H_ */
diff --combined src/surf/cpu_cas01.cpp
index 61e1e9e,0000000..0ea0217
mode 100644,000000..100644
--- /dev/null
@@@ -1,505 -1,0 +1,505 @@@
-   ((CpuCas01ModelPtr)surf_cpu_model)->parseInit(host);
 +/* Copyright (c) 2009-2011. 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 "cpu_cas01.hpp"
 +#include "cpu_ti.hpp"
 +#include "surf.hpp"
 +#include "maxmin_private.h"
 +#include "simgrid/sg_config.h"
 +
 +extern "C" {
 +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu_cas, surf_cpu,
 +                                "Logging specific to the SURF CPU IMPROVED module");
 +}
 +
 +static xbt_swag_t
 +    cpu_running_action_set_that_does_not_need_being_checked = NULL;
 +
 +/*************
 + * CallBacks *
 + *************/
 +
 +static void parse_cpu_init(sg_platf_host_cbarg_t host){
-   surf_cpu_model->addTraces();
++  ((CpuCas01ModelPtr)surf_cpu_model_pm)->parseInit(host);
 +}
 +
 +static void cpu_add_traces_cpu(){
-   if (surf_cpu_model)
++  surf_cpu_model_pm->addTraces();
 +}
 +
 +static void cpu_define_callbacks()
 +{
 +  sg_platf_host_add_cb(parse_cpu_init);
 +  sg_platf_postparse_add_cb(cpu_add_traces_cpu);
 +}
 +
 +/*********
 + * Model *
 + *********/
 +void surf_cpu_model_init_Cas01()
 +{
 +  char *optim = xbt_cfg_get_string(_sg_cfg_set, "cpu/optim");
 +
-   surf_cpu_model = new CpuCas01Model();
++  if (surf_cpu_model_pm)
 +    return;
 +
 +  if (!strcmp(optim, "TI")) {
 +    surf_cpu_model_init_ti();
 +    return;
 +  }
 +
-   ModelPtr model = static_cast<ModelPtr>(surf_cpu_model);
++  surf_cpu_model_pm = new CpuCas01Model();
 +  cpu_define_callbacks();
-   surf_cpu_model = NULL;
++  ModelPtr model = static_cast<ModelPtr>(surf_cpu_model_pm);
 +  xbt_dynar_push(model_list, &model);
 +}
 +
 +CpuCas01Model::CpuCas01Model() : CpuModel("cpu")
 +{
 +  ActionPtr action;
 +  ActionLmmPtr actionlmm;
 +
 +  char *optim = xbt_cfg_get_string(_sg_cfg_set, "cpu/optim");
 +  int select = xbt_cfg_get_boolean(_sg_cfg_set, "cpu/maxmin_selective_update");
 +
 +  if (!strcmp(optim, "Full")) {
 +    p_updateMechanism = UM_FULL;
 +    m_selectiveUpdate = select;
 +  } else if (!strcmp(optim, "Lazy")) {
 +    p_updateMechanism = UM_LAZY;
 +    m_selectiveUpdate = 1;
 +    xbt_assert((select == 1)
 +               ||
 +               (xbt_cfg_is_default_value
 +                (_sg_cfg_set, "cpu/maxmin_selective_update")),
 +               "Disabling selective update while using the lazy update mechanism is dumb!");
 +  } else {
 +    xbt_die("Unsupported optimization (%s) for this model", optim);
 +  }
 +
 +  cpu_running_action_set_that_does_not_need_being_checked =
 +      xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
 +
 +  if (p_updateMechanism == UM_LAZY) {
 +      shareResources = &CpuCas01Model::shareResourcesLazy;
 +      updateActionsState = &CpuCas01Model::updateActionsStateLazy;
 +
 +  } else if (p_updateMechanism == UM_FULL) {
 +      shareResources = &CpuCas01Model::shareResourcesFull;
 +      updateActionsState = &CpuCas01Model::updateActionsStateFull;
 +  } else
 +    xbt_die("Invalid cpu update mechanism!");
 +
 +  if (!p_maxminSystem) {
 +    p_maxminSystem = lmm_system_new(m_selectiveUpdate);
 +  }
 +
 +  if (p_updateMechanism == UM_LAZY) {
 +    p_actionHeap = xbt_heap_new(8, NULL);
 +    xbt_heap_set_update_callback(p_actionHeap,  surf_action_lmm_update_index_heap);
 +    p_modifiedSet = xbt_swag_new(xbt_swag_offset(*actionlmm, p_actionListHookup));
 +    p_maxminSystem->keep_track = p_modifiedSet;
 +  }
 +}
 +
 +CpuCas01Model::~CpuCas01Model()
 +{
 +  lmm_system_free(p_maxminSystem);
 +  p_maxminSystem = NULL;
 +
 +  if (p_actionHeap)
 +    xbt_heap_free(p_actionHeap);
 +  xbt_swag_free(p_modifiedSet);
 +
-     lmm_update_constraint_bound(surf_cpu_model->p_maxminSystem, p_constraint,
++  surf_cpu_model_pm = 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;
 +}
 +
 +void CpuCas01Model::parseInit(sg_platf_host_cbarg_t host)
 +{
 +  createResource(host->id,
 +        host->power_peak,
 +        host->pstate,
 +        host->power_scale,
 +        host->power_trace,
 +        host->core_amount,
 +        host->initial_state,
 +        host->state_trace,
 +        host->properties);
 +}
 +
 +CpuCas01LmmPtr CpuCas01Model::createResource(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)
 +{
 +  CpuPtr cpu = NULL;
 +  xbt_assert(!surf_cpu_resource_priv(surf_cpu_resource_by_name(name)),
 +             "Host '%s' declared several times in the platform file",
 +             name);
 +  xbt_assert(power_peak > 0, "Power has to be >0");
 +  xbt_assert(core > 0, "Invalid number of cores %d", core);
 +
 +  cpu = new CpuCas01Lmm(this, name, power_peak, pstate, power_scale, power_trace, core, state_initial, state_trace, cpu_properties);
 +  xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, static_cast<ResourcePtr>(cpu));
 +
 +  return (CpuCas01LmmPtr) xbt_lib_get_elm_or_null(host_lib, name);
 +}
 +
 +double CpuCas01Model::shareResourcesFull(double now)
 +{
 +  return Model::shareResourcesMaxMin(p_runningActionSet,
 +                             p_maxminSystem, lmm_solve);
 +}
 +
 +void CpuCas01Model::addTraces()
 +{
 +  xbt_dict_cursor_t cursor = NULL;
 +  char *trace_name, *elm;
 +  static int called = 0;
 +  if (called)
 +    return;
 +  called = 1;
 +
 +  /* connect all traces relative to hosts */
 +  xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
 +    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 +    CpuCas01LmmPtr host = static_cast<CpuCas01LmmPtr>(surf_cpu_resource_priv(surf_cpu_resource_by_name(elm)));
 +
 +    xbt_assert(host, "Host %s undefined", elm);
 +    xbt_assert(trace, "Trace %s undefined", trace_name);
 +
 +    host->p_stateEvent =
 +        tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(host));
 +  }
 +
 +  xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
 +    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 +    CpuCas01LmmPtr host = dynamic_cast<CpuCas01LmmPtr>(static_cast<ResourcePtr>(surf_cpu_resource_priv(surf_cpu_resource_by_name(elm))));
 +
 +    xbt_assert(host, "Host %s undefined", elm);
 +    xbt_assert(trace, "Trace %s undefined", trace_name);
 +
 +    host->p_powerEvent =
 +        tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(host));
 +  }
 +}
 +
 +/************
 + * Resource *
 + ************/
 +CpuCas01Lmm::CpuCas01Lmm(CpuCas01ModelPtr model, const char *name, xbt_dynar_t powerPeak,
 +              int pstate, double powerScale, tmgr_trace_t powerTrace, int core,
 +        e_surf_resource_state_t stateInitial, tmgr_trace_t stateTrace,
 +      xbt_dict_t properties) :
 +      CpuLmm(model, name, properties), Resource(model, name, properties) {
 +  m_powerPeak = xbt_dynar_get_as(powerPeak, pstate, double);
 +  p_powerPeakList = powerPeak;
 +  m_pstate = pstate;
 +
 +  p_energy = xbt_new(s_energy_cpu_cas01_t, 1);
 +  p_energy->total_energy = 0;
 +  p_energy->power_range_watts_list = getWattsRangeList();
 +  p_energy->last_updated = surf_get_clock();
 +
 +  XBT_DEBUG("CPU create: peak=%f, pstate=%d", m_powerPeak, m_pstate);
 +
 +  m_powerScale = powerScale;
 +  m_core = core;
 +  p_stateCurrent = stateInitial;
 +  if (powerTrace)
 +    p_powerEvent = tmgr_history_add_trace(history, powerTrace, 0.0, 0, static_cast<ResourcePtr>(this));
 +
 +  if (stateTrace)
 +    p_stateEvent = tmgr_history_add_trace(history, stateTrace, 0.0, 0, static_cast<ResourcePtr>(this));
 +
 +  p_constraint = lmm_constraint_new(p_model->p_maxminSystem, this, m_core * m_powerScale * m_powerPeak);
 +}
 +
 +CpuCas01Lmm::~CpuCas01Lmm(){
 +  unsigned int iter;
 +  xbt_dynar_t power_tuple = NULL;
 +  xbt_dynar_foreach(p_energy->power_range_watts_list, iter, power_tuple)
 +    xbt_dynar_free(&power_tuple);
 +  xbt_dynar_free(&p_energy->power_range_watts_list);
 +  xbt_dynar_free(&p_powerPeakList);
 +  xbt_free(p_energy);
 +  return;
 +}
 +
 +bool CpuCas01Lmm::isUsed()
 +{
 +  return lmm_constraint_used(p_model->p_maxminSystem, p_constraint);
 +}
 +
 +void CpuCas01Lmm::updateState(tmgr_trace_event_t event_type, double value, double date)
 +{
 +  lmm_variable_t var = NULL;
 +  lmm_element_t elem = NULL;
 +
 +  if (event_type == p_powerEvent) {
 +    m_powerScale = value;
-             (surf_cpu_model->p_maxminSystem, p_constraint, &elem))) {
++    lmm_update_constraint_bound(surf_cpu_model_pm->p_maxminSystem, p_constraint,
 +                                m_core * m_powerScale *
 +                                m_powerPeak);
 +#ifdef HAVE_TRACING
 +    TRACE_surf_host_set_power(date, m_name,
 +                              m_core * m_powerScale *
 +                              m_powerPeak);
 +#endif
 +    while ((var = lmm_get_var_from_cnst
-       lmm_update_variable_bound(surf_cpu_model->p_maxminSystem,
++            (surf_cpu_model_pm->p_maxminSystem, p_constraint, &elem))) {
 +      CpuCas01ActionLmmPtr action = static_cast<CpuCas01ActionLmmPtr>(static_cast<ActionLmmPtr>(lmm_variable_id(var)));
 +
-       while ((var = lmm_get_var_from_cnst(surf_cpu_model->p_maxminSystem, cnst, &elem))) {
++      lmm_update_variable_bound(surf_cpu_model_pm->p_maxminSystem,
 +                                action->p_variable,
 +                                m_powerScale * m_powerPeak);
 +    }
 +    if (tmgr_trace_event_free(event_type))
 +      p_powerEvent = NULL;
 +  } else if (event_type == p_stateEvent) {
 +    if (value > 0) {
 +      if(p_stateCurrent == SURF_RESOURCE_OFF)
 +        xbt_dynar_push_as(host_that_restart, char*, (char *)m_name);
 +      p_stateCurrent = SURF_RESOURCE_ON;
 +    } else {
 +      lmm_constraint_t cnst = p_constraint;
 +
 +      p_stateCurrent = SURF_RESOURCE_OFF;
 +
-   CpuCas01ActionLmmPtr action = new CpuCas01ActionLmm(surf_cpu_model, size, p_stateCurrent != SURF_RESOURCE_ON);
++      while ((var = lmm_get_var_from_cnst(surf_cpu_model_pm->p_maxminSystem, cnst, &elem))) {
 +        ActionLmmPtr action = static_cast<ActionLmmPtr>(lmm_variable_id(var));
 +
 +        if (action->getState() == SURF_ACTION_RUNNING ||
 +            action->getState() == SURF_ACTION_READY ||
 +            action->getState() == SURF_ACTION_NOT_IN_THE_SYSTEM) {
 +          action->m_finish = date;
 +          action->setState(SURF_ACTION_FAILED);
 +        }
 +      }
 +    }
 +    if (tmgr_trace_event_free(event_type))
 +      p_stateEvent = NULL;
 +  } else {
 +    XBT_CRITICAL("Unknown event ! \n");
 +    xbt_abort();
 +  }
 +
 +  return;
 +}
 +
 +ActionPtr CpuCas01Lmm::execute(double size)
 +{
 +
 +  XBT_IN("(%s,%g)", m_name, size);
-       lmm_variable_new(surf_cpu_model->p_maxminSystem, static_cast<ActionLmmPtr>(action),
++  CpuCas01ActionLmmPtr action = new CpuCas01ActionLmm(surf_cpu_model_pm, size, p_stateCurrent != SURF_RESOURCE_ON);
 +
 +  action->m_suspended = 0;     /* Should be useless because of the
 +                                                   calloc but it seems to help valgrind... */
 +
 +  action->p_variable =
-   if (surf_cpu_model->p_updateMechanism == UM_LAZY) {
++      lmm_variable_new(surf_cpu_model_pm->p_maxminSystem, static_cast<ActionLmmPtr>(action),
 +                       action->m_priority,
 +                       m_powerScale * m_powerPeak, 1);
-   lmm_expand(surf_cpu_model->p_maxminSystem, p_constraint,
++  if (surf_cpu_model_pm->p_updateMechanism == UM_LAZY) {
 +    action->m_indexHeap = -1;
 +    action->m_lastUpdate = surf_get_clock();
 +    action->m_lastValue = 0.0;
 +  }
-   lmm_update_variable_weight(surf_cpu_model->p_maxminSystem,
++  lmm_expand(surf_cpu_model_pm->p_maxminSystem, p_constraint,
 +             action->p_variable, 1.0);
 +  XBT_OUT();
 +  return action;
 +}
 +
 +ActionPtr CpuCas01Lmm::sleep(double duration)
 +{
 +  if (duration > 0)
 +    duration = MAX(duration, MAXMIN_PRECISION);
 +
 +  XBT_IN("(%s,%g)", m_name, duration);
 +  CpuCas01ActionLmmPtr action = dynamic_cast<CpuCas01ActionLmmPtr>(execute(1.0));
 +
 +  // FIXME: sleep variables should not consume 1.0 in lmm_expand
 +  action->m_maxDuration = duration;
 +  action->m_suspended = 2;
 +  if (duration == NO_MAX_DURATION) {
 +    /* Move to the *end* of the corresponding action set. This convention
 +       is used to speed up update_resource_state  */
 +    xbt_swag_remove(static_cast<ActionPtr>(action), action->p_stateSet);
 +    action->p_stateSet = cpu_running_action_set_that_does_not_need_being_checked;
 +    xbt_swag_insert(static_cast<ActionPtr>(action), action->p_stateSet);
 +  }
 +
-   if (surf_cpu_model->p_updateMechanism == UM_LAZY) {     // remove action from the heap
-     action->heapRemove(surf_cpu_model->p_actionHeap);
++  lmm_update_variable_weight(surf_cpu_model_pm->p_maxminSystem,
 +                             action->p_variable, 0.0);
-     xbt_swag_insert_at_head(static_cast<ActionLmmPtr>(action), surf_cpu_model->p_modifiedSet);
++  if (surf_cpu_model_pm->p_updateMechanism == UM_LAZY) {     // remove action from the heap
++    action->heapRemove(surf_cpu_model_pm->p_actionHeap);
 +    // this is necessary for a variable with weight 0 since such
 +    // variables are ignored in lmm and we need to set its max_duration
 +    // correctly at the next call to share_resources
++    xbt_swag_insert_at_head(static_cast<ActionLmmPtr>(action), surf_cpu_model_pm->p_modifiedSet);
 +  }
 +
 +  XBT_OUT();
 +  return action;
 +}
 +
 +xbt_dynar_t CpuCas01Lmm::getWattsRangeList()
 +{
 +      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;
 +
 +      if (m_properties == NULL)
 +              return NULL;
 +
 +      char* all_power_values_str = (char*)xbt_dict_get_or_null(m_properties, "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",
 +                              m_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(&current_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
 + *
 + */
 +double CpuCas01Lmm::getCurrentWattsValue(double cpu_load)
 +{
 +      xbt_dynar_t power_range_list = p_energy->power_range_watts_list;
 +
 +      if (power_range_list == NULL)
 +      {
 +              XBT_DEBUG("No power range properties specified for host %s", m_name);
 +              return 0;
 +      }
 +      xbt_assert(xbt_dynar_length(power_range_list) == xbt_dynar_length(p_powerPeakList),
 +                                              "The number of power ranges in the properties does not match the number of pstates for host %s",
 +                                              m_name);
 +
 +    /* retrieve the power values associated with the current pstate */
 +    xbt_dynar_t current_power_values = xbt_dynar_get_as(power_range_list, m_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 CpuCas01Lmm::updateEnergy(double cpu_load)
 +{
 +  double start_time = p_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, m_powerPeak, m_pstate);
 +  double current_energy = p_energy->total_energy;
 +  double action_energy = getCurrentWattsValue(cpu_load)*(finish_time-start_time);
 +
 +  p_energy->total_energy = current_energy + action_energy;
 +  p_energy->last_updated = finish_time;
 +
 +  XBT_DEBUG("[cpu_update_energy] old_energy_value=%f, action_energy_value=%f", current_energy, action_energy);
 +}
 +
 +double CpuCas01Lmm::getCurrentPowerPeak()
 +{
 +  return m_powerPeak;
 +}
 +
 +double CpuCas01Lmm::getPowerPeakAt(int pstate_index)
 +{
 +  xbt_dynar_t plist = p_powerPeakList;
 +  xbt_assert((pstate_index <= xbt_dynar_length(plist)), "Invalid parameters (pstate index out of bounds)");
 +
 +  return xbt_dynar_get_as(plist, pstate_index, double);
 +}
 +
 +int CpuCas01Lmm::getNbPstates()
 +{
 +  return xbt_dynar_length(p_powerPeakList);
 +}
 +
 +void CpuCas01Lmm::setPowerPeakAt(int pstate_index)
 +{
 +  xbt_dynar_t plist = p_powerPeakList;
 +  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);
 +  m_pstate = pstate_index;
 +  m_powerPeak = new_power_peak;
 +}
 +
 +double CpuCas01Lmm::getConsumedEnergy()
 +{
 +  return p_energy->total_energy;
 +}
 +
 +/**********
 + * Action *
 + **********/
 +
 +/**
 + * Update the CPU total energy for a finished action
 + *
 + */
 +void CpuCas01ActionLmm::updateEnergy()
 +{
 +  CpuCas01LmmPtr cpu  = static_cast<CpuCas01LmmPtr>(lmm_constraint_id(lmm_get_cnst_from_var
 +                                                                                (p_model->p_maxminSystem,
 +                                                                                                p_variable, 0)));
 +
 +  if(cpu->p_energy->last_updated < surf_get_clock()) {
 +      double load = lmm_constraint_get_usage(cpu->p_constraint) / cpu->m_powerPeak;
 +    cpu->updateEnergy(load);
 +  }
 +}
diff --combined src/surf/cpu_ti.cpp
index 545f2ba,0000000..922c9c7
mode 100644,000000..100644
--- /dev/null
@@@ -1,1006 -1,0 +1,1006 @@@
-   ((CpuTiModelPtr)surf_cpu_model)->parseInit(host);
 +#include "cpu_ti.hpp"
 +#include "trace_mgr_private.h"
 +#include "xbt/heap.h"
 +
 +#ifndef SURF_MODEL_CPUTI_H_
 +#define SURF_MODEL_CPUTI_H_
 +
 +extern "C" {
 +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu_ti, surf_cpu,
 +                                "Logging specific to the SURF CPU TRACE INTEGRATION module");
 +}
 +
 +static xbt_swag_t cpu_ti_running_action_set_that_does_not_need_being_checked;
 +static xbt_swag_t cpu_ti_modified_cpu;
 +static xbt_heap_t cpu_ti_action_heap;
 +
 +static void cpu_ti_action_update_index_heap(void *action, int i);
 +
 +/*********
 + * Trace *
 + *********/
 +
 +CpuTiTrace::CpuTiTrace(tmgr_trace_t power_trace)
 +{
 +  s_tmgr_event_t val;
 +  unsigned int cpt;
 +  double integral = 0;
 +  double time = 0;
 +  int i = 0;
 +  p_timePoints = (double*) xbt_malloc0(sizeof(double) *
 +                  (xbt_dynar_length(power_trace->s_list.event_list) + 1));
 +  p_integral = (double*) xbt_malloc0(sizeof(double) *
 +                  (xbt_dynar_length(power_trace->s_list.event_list) + 1));
 +  m_nbPoints = xbt_dynar_length(power_trace->s_list.event_list);
 +  xbt_dynar_foreach(power_trace->s_list.event_list, cpt, val) {
 +    p_timePoints[i] = time;
 +    p_integral[i] = integral;
 +    integral += val.delta * val.value;
 +    time += val.delta;
 +    i++;
 +  }
 +  p_timePoints[i] = time;
 +  p_integral[i] = integral;
 +}
 +
 +CpuTiTrace::~CpuTiTrace()
 +{
 +  xbt_free(p_timePoints);
 +  xbt_free(p_integral);
 +}
 +
 +CpuTiTgmr::~CpuTiTgmr()
 +{
 +  if (p_trace)
 +    delete p_trace;
 +}
 +
 +/**
 +* \brief Integrate trace
 +*
 +* Wrapper around surf_cpu_integrate_trace_simple() to get
 +* the cyclic effect.
 +*
 +* \param trace Trace structure.
 +* \param a      Begin of interval
 +* \param b      End of interval
 +* \return the integrate value. -1 if an error occurs.
 +*/
 +double CpuTiTgmr::integrate(double a, double b)
 +{
 +  double first_chunk;
 +  double middle_chunk;
 +  double last_chunk;
 +  int a_index, b_index;
 +
 +  if ((a < 0.0) || (a > b)) {
 +    XBT_CRITICAL
 +        ("Error, invalid integration interval [%.2f,%.2f]. You probably have a task executing with negative computation amount. Check your code.",
 +         a, b);
 +    xbt_abort();
 +  }
 +  if (a == b)
 +    return 0.0;
 +
 +  if (m_type == TRACE_FIXED) {
 +    return ((b - a) * m_value);
 +  }
 +
 +  if (ceil(a / m_lastTime) == a / m_lastTime)
 +    a_index = 1 + (int) (ceil(a / m_lastTime));
 +  else
 +    a_index = (int) (ceil(a / m_lastTime));
 +
 +  b_index = (int) (floor(b / m_lastTime));
 +
 +  if (a_index > b_index) {      /* Same chunk */
 +    return p_trace->integrateSimple(a - (a_index -
 +                                              1) * m_lastTime,
 +                                         b -
 +                                         (b_index) *
 +                                         m_lastTime);
 +  }
 +
 +  first_chunk = p_trace->integrateSimple(a - (a_index -
 +                                                   1) *
 +                                              m_lastTime,
 +                                              m_lastTime);
 +  middle_chunk = (b_index - a_index) * m_total;
 +  last_chunk = p_trace->integrateSimple(0.0,
 +                                             b -
 +                                             (b_index) *
 +                                             m_lastTime);
 +
 +  XBT_DEBUG("first_chunk=%.2f  middle_chunk=%.2f  last_chunk=%.2f\n",
 +         first_chunk, middle_chunk, last_chunk);
 +
 +  return (first_chunk + middle_chunk + last_chunk);
 +}
 +
 +/**
 + * \brief Auxiliary function to calculate the integral between a and b.
 + *     It simply calculates the integral at point a and b and returns the difference 
 + *   between them.
 + * \param trace    Trace structure
 + * \param a        Initial point
 + * \param b  Final point
 + * \return  Integral
 +*/
 +double CpuTiTrace::integrateSimple(double a, double b)
 +{
 +  return integrateSimplePoint(b) - integrateSimplePoint(a);
 +}
 +
 +/**
 + * \brief Auxiliary function to calculate the integral at point a.
 + * \param trace    Trace structure
 + * \param a        point
 + * \return  Integral
 +*/
 +double CpuTiTrace::integrateSimplePoint(double a)
 +{
 +  double integral = 0;
 +  int ind;
 +  double a_aux = a;
 +  ind = binarySearch(p_timePoints, a, 0, m_nbPoints - 1);
 +  integral += p_integral[ind];
 +  XBT_DEBUG
 +      ("a %f ind %d integral %f ind + 1 %f ind %f time +1 %f time %f",
 +       a, ind, integral, p_integral[ind + 1], p_integral[ind],
 +       p_timePoints[ind + 1], p_timePoints[ind]);
 +  double_update(&a_aux, p_timePoints[ind]);
 +  if (a_aux > 0)
 +    integral +=
 +        ((p_integral[ind + 1] -
 +          p_integral[ind]) / (p_timePoints[ind + 1] -
 +                              p_timePoints[ind])) * (a - p_timePoints[ind]);
 +  XBT_DEBUG("Integral a %f = %f", a, integral);
 +
 +  return integral;
 +}
 +
 +/**
 +* \brief Calculate the time needed to execute "amount" on cpu.
 +*
 +* Here, amount can span multiple trace periods
 +*
 +* \param trace   CPU trace structure
 +* \param a        Initial time
 +* \param amount  Amount to be executed
 +* \return  End time
 +*/
 +double CpuTiTgmr::solve(double a, double amount)
 +{
 +  int quotient;
 +  double reduced_b;
 +  double reduced_amount;
 +  double reduced_a;
 +  double b;
 +
 +/* Fix very small negative numbers */
 +  if ((a < 0.0) && (a > -EPSILON)) {
 +    a = 0.0;
 +  }
 +  if ((amount < 0.0) && (amount > -EPSILON)) {
 +    amount = 0.0;
 +  }
 +
 +/* Sanity checks */
 +  if ((a < 0.0) || (amount < 0.0)) {
 +    XBT_CRITICAL
 +        ("Error, invalid parameters [a = %.2f, amount = %.2f]. You probably have a task executing with negative computation amount. Check your code.",
 +         a, amount);
 +    xbt_abort();
 +  }
 +
 +/* At this point, a and amount are positive */
 +
 +  if (amount < EPSILON)
 +    return a;
 +
 +/* Is the trace fixed ? */
 +  if (m_type == TRACE_FIXED) {
 +    return (a + (amount / m_value));
 +  }
 +
 +  XBT_DEBUG("amount %f total %f", amount, m_total);
 +/* Reduce the problem to one where amount <= trace_total */
 +  quotient = (int) (floor(amount / m_total));
 +  reduced_amount = (m_total) * ((amount / m_total) -
 +                                     floor(amount / m_total));
 +  reduced_a = a - (m_lastTime) * (int) (floor(a / m_lastTime));
 +
 +  XBT_DEBUG("Quotient: %d reduced_amount: %f reduced_a: %f", quotient,
 +         reduced_amount, reduced_a);
 +
 +/* Now solve for new_amount which is <= trace_total */
 +/*
 +   fprintf(stderr,"reduced_a = %.2f\n",reduced_a);
 +   fprintf(stderr,"reduced_amount = %.2f\n",reduced_amount);
 + */
 +  reduced_b = solveSomewhatSimple(reduced_a, reduced_amount);
 +
 +/* Re-map to the original b and amount */
 +  b = (m_lastTime) * (int) (floor(a / m_lastTime)) +
 +      (quotient * m_lastTime) + reduced_b;
 +  return b;
 +}
 +
 +/**
 +* \brief Auxiliary function to solve integral
 +*
 +* Here, amount is <= trace->total
 +* and a <=trace->last_time
 +*
 +*/
 +double CpuTiTgmr::solveSomewhatSimple(double a, double amount)
 +{
 +  double amount_till_end;
 +  double b;
 +
 +  XBT_DEBUG("Solve integral: [%.2f, amount=%.2f]", a, amount);
 +  amount_till_end = integrate(a, m_lastTime);
 +/*
 +   fprintf(stderr,"amount_till_end=%.2f\n",amount_till_end);
 + */
 +
 +  if (amount_till_end > amount) {
 +    b = p_trace->solveSimple(a, amount);
 +  } else {
 +    b = m_lastTime + p_trace->solveSimple(0.0, amount - amount_till_end);
 +  }
 +  return b;
 +}
 +
 +/**
 + * \brief Auxiliary function to solve integral.
 + *  It returns the date when the requested amount of flops is available
 + * \param trace    Trace structure
 + * \param a        Initial point
 + * \param amount  Amount of flops 
 + * \return The date when amount is available.
 +*/
 +double CpuTiTrace::solveSimple(double a, double amount)
 +{
 +  double integral_a;
 +  int ind;
 +  double time;
 +  integral_a = integrateSimplePoint(a);
 +  ind = binarySearch(p_integral, integral_a + amount, 0, m_nbPoints - 1);
 +  time = p_timePoints[ind];
 +  time +=
 +      (integral_a + amount -
 +       p_integral[ind]) / ((p_integral[ind + 1] -
 +                                 p_integral[ind]) /
 +                                (p_timePoints[ind + 1] -
 +                                 p_timePoints[ind]));
 +
 +  return time;
 +}
 +
 +/**
 +* \brief Auxiliary function to update the CPU power scale.
 +*
 +*  This function uses the trace structure to return the power scale at the determined time a.
 +* \param trace    Trace structure to search the updated power scale
 +* \param a        Time
 +* \return CPU power scale
 +*/
 +double CpuTiTgmr::getPowerScale(double a)
 +{
 +  double reduced_a;
 +  int point;
 +  s_tmgr_event_t val;
 +
 +  reduced_a = a - floor(a / m_lastTime) * m_lastTime;
 +  point = p_trace->binarySearch(p_trace->p_timePoints, reduced_a, 0,
 +                                p_trace->m_nbPoints - 1);
 +  xbt_dynar_get_cpy(p_powerTrace->s_list.event_list, point, &val);
 +  return val.value;
 +}
 +
 +/**
 +* \brief Creates a new integration trace from a tmgr_trace_t
 +*
 +* \param  power_trace    CPU availability trace
 +* \param  value          Percentage of CPU power available (useful to fixed tracing)
 +* \param  spacing        Initial spacing
 +* \return  Integration trace structure
 +*/
 +CpuTiTgmr::CpuTiTgmr(tmgr_trace_t power_trace, double value)
 +{
 +  double total_time = 0.0;
 +  s_tmgr_event_t val;
 +  unsigned int cpt;
 +  p_trace = 0;
 +
 +/* no availability file, fixed trace */
 +  if (!power_trace) {
 +    m_type = TRACE_FIXED;
 +    m_value = value;
 +    XBT_DEBUG("No availability trace. Constant value = %lf", value);
 +    return;
 +  }
 +
 +  /* only one point available, fixed trace */
 +  if (xbt_dynar_length(power_trace->s_list.event_list) == 1) {
 +    xbt_dynar_get_cpy(power_trace->s_list.event_list, 0, &val);
 +    m_type = TRACE_FIXED;
 +    m_value = val.value;
 +    return;
 +  }
 +
 +  m_type = TRACE_DYNAMIC;
 +  p_powerTrace = power_trace;
 +
 +  /* count the total time of trace file */
 +  xbt_dynar_foreach(power_trace->s_list.event_list, cpt, val) {
 +    total_time += val.delta;
 +  }
 +  p_trace = new CpuTiTrace(power_trace);
 +  m_lastTime = total_time;
 +  m_total = p_trace->integrateSimple(0, total_time);
 +
 +  XBT_DEBUG("Total integral %lf, last_time %lf ",
 +            m_total, m_lastTime);
 +}
 +
 +/**
 + * \brief Binary search in array.
 + *  It returns the first point of the interval in which "a" is. 
 + * \param array    Array
 + * \param a        Value to search
 + * \param low     Low bound to search in array
 + * \param high    Upper bound to search in array
 + * \return Index of point
 +*/
 +int CpuTiTrace::binarySearch(double *array, double a, int low, int high)
 +{
 +  xbt_assert(low < high, "Wrong parameters: low (%d) should be smaller than"
 +      " high (%d)", low, high);
 +
 +  int mid;
 +  do {
 +    mid = low + (high - low) / 2;
 +    XBT_DEBUG("a %f low %d high %d mid %d value %f", a, low, high, mid,
 +        array[mid]);
 +
 +    if (array[mid] > a)
 +      high = mid;
 +    else
 +      low = mid;
 +  }
 +  while (low < high - 1);
 +
 +  return low;
 +}
 +
 +/*************
 + * CallBacks *
 + *************/
 +
 +static void parse_cpu_ti_init(sg_platf_host_cbarg_t host){
-   surf_cpu_model->addTraces();
++  ((CpuTiModelPtr)surf_cpu_model_pm)->parseInit(host);
 +}
 +
 +static void add_traces_cpu_ti(){
-   xbt_assert(!surf_cpu_model,"CPU model already initialized. This should not happen.");
-   surf_cpu_model = new CpuTiModel();
++  surf_cpu_model_pm->addTraces();
 +}
 +
 +static void cpu_ti_define_callbacks()
 +{
 +  sg_platf_host_add_cb(parse_cpu_ti_init);
 +  sg_platf_postparse_add_cb(add_traces_cpu_ti);
 +}
 +
 +/*********
 + * Model *
 + *********/
 +
 +void surf_cpu_model_init_ti()
 +{
-   ModelPtr model = static_cast<ModelPtr>(surf_cpu_model);
++  xbt_assert(!surf_cpu_model_pm,"CPU model already initialized. This should not happen.");
++  surf_cpu_model_pm = new CpuTiModel();
 +  cpu_ti_define_callbacks();
-   xbt_assert(!surf_cpu_model,"CPU model already initialized. This should not happen.");
++  ModelPtr model = static_cast<ModelPtr>(surf_cpu_model_pm);
 +  xbt_dynar_push(model_list, &model);
 +}
 +
 +CpuTiModel::CpuTiModel() : CpuModel("cpu_ti")
 +{
-   surf_cpu_model = NULL;
++  xbt_assert(!surf_cpu_model_pm,"CPU model already initialized. This should not happen.");
 +  ActionPtr action;
 +  CpuTi cpu;
 +
 +  cpu_ti_running_action_set_that_does_not_need_being_checked =
 +      xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
 +
 +  cpu_ti_modified_cpu =
 +      xbt_swag_new(xbt_swag_offset(cpu, p_modifiedCpuHookup));
 +
 +  cpu_ti_action_heap = xbt_heap_new(8, NULL);
 +  xbt_heap_set_update_callback(cpu_ti_action_heap,
 +                               cpu_ti_action_update_index_heap);
 +}
 +
 +CpuTiModel::~CpuTiModel()
 +{
 +  void **cpu;
 +  xbt_lib_cursor_t cursor;
 +  char *key;
 +
 +  xbt_lib_foreach(host_lib, cursor, key, cpu){
 +    if(cpu[SURF_CPU_LEVEL])
 +    {
 +        CpuTiPtr CPU = dynamic_cast<CpuTiPtr>(static_cast<ResourcePtr>(cpu[SURF_CPU_LEVEL]));
 +        xbt_swag_free(CPU->p_actionSet);
 +        delete CPU->p_availTrace;
 +    }
 +  }
 +
-         surf_cpu_model->p_runningActionSet)
++  surf_cpu_model_pm = NULL;
 +
 +  xbt_swag_free
 +      (cpu_ti_running_action_set_that_does_not_need_being_checked);
 +  xbt_swag_free(cpu_ti_modified_cpu);
 +  cpu_ti_running_action_set_that_does_not_need_being_checked = NULL;
 +  xbt_heap_free(cpu_ti_action_heap);
 +}
 +
 +void CpuTiModel::parseInit(sg_platf_host_cbarg_t host)
 +{
 +  createResource(host->id,
 +        host->power_peak,
 +        host->pstate,
 +        host->power_scale,
 +        host->power_trace,
 +        host->core_amount,
 +        host->initial_state,
 +        host->state_trace,
 +        host->properties);
 +}
 +
 +CpuTiPtr CpuTiModel::createResource(const char *name,
 +                             xbt_dynar_t powerPeak,
 +                             int pstate,
 +                           double powerScale,
 +                           tmgr_trace_t powerTrace,
 +                           int core,
 +                           e_surf_resource_state_t stateInitial,
 +                           tmgr_trace_t stateTrace,
 +                           xbt_dict_t cpuProperties)
 +{
 +  tmgr_trace_t empty_trace;
 +  s_tmgr_event_t val;
 +  CpuTiActionPtr cpuAction;
 +  xbt_assert(core==1,"Multi-core not handled with this model yet");
 +  xbt_assert(!surf_cpu_resource_priv(surf_cpu_resource_by_name(name)),
 +              "Host '%s' declared several times in the platform file",
 +              name);
 +  CpuTiPtr cpu = new CpuTi(this, name, powerPeak, pstate, powerScale, powerTrace,
 +                         core, stateInitial, stateTrace, cpuProperties);
 +  xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, static_cast<ResourcePtr>(cpu));
 +  return (CpuTiPtr) xbt_lib_get_elm_or_null(host_lib, name);
 +}
 +
 +CpuTiActionPtr CpuTiModel::createAction(double cost, bool failed)
 +{
 +  return NULL;//new CpuTiAction(this, cost, failed);
 +}
 +
 +double CpuTiModel::shareResources(double now)
 +{
 +  void *_cpu, *_cpu_next;
 +  double min_action_duration = -1;
 +
 +/* iterates over modified cpus to update share resources */
 +  xbt_swag_foreach_safe(_cpu, _cpu_next, cpu_ti_modified_cpu) {
 +    static_cast<CpuTiPtr>(_cpu)->updateActionFinishDate(now);
 +  }
 +/* get the min next event if heap not empty */
 +  if (xbt_heap_size(cpu_ti_action_heap) > 0)
 +    min_action_duration = xbt_heap_maxkey(cpu_ti_action_heap) - now;
 +
 +  XBT_DEBUG("Share resources, min next event date: %f", min_action_duration);
 +
 +  return min_action_duration;
 +}
 +
 +void CpuTiModel::updateActionsState(double now, double delta)
 +{
 +  while ((xbt_heap_size(cpu_ti_action_heap) > 0)
 +         && (xbt_heap_maxkey(cpu_ti_action_heap) <= now)) {
 +    CpuTiActionPtr action = (CpuTiActionPtr) xbt_heap_pop(cpu_ti_action_heap);
 +    XBT_DEBUG("Action %p: finish", action);
 +    action->m_finish = surf_get_clock();
 +    /* set the remains to 0 due to precision problems when updating the remaining amount */
 +    action->m_remains = 0;
 +    action->setState(SURF_ACTION_DONE);
 +    /* update remaining amount of all actions */
 +    action->p_cpu->updateRemainingAmount(surf_get_clock());
 +  }
 +}
 +
 +void CpuTiModel::addTraces()
 +{
 +  xbt_dict_cursor_t cursor = NULL;
 +  char *trace_name, *elm;
 +
 +  static int called = 0;
 +
 +  if (called)
 +    return;
 +  called = 1;
 +
 +/* connect all traces relative to hosts */
 +  xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
 +    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 +    CpuTiPtr cpu = static_cast<CpuTiPtr>(surf_cpu_resource_priv(surf_cpu_resource_by_name(elm)));
 +
 +    xbt_assert(cpu, "Host %s undefined", elm);
 +    xbt_assert(trace, "Trace %s undefined", trace_name);
 +
 +    if (cpu->p_stateEvent) {
 +      XBT_DEBUG("Trace already configured for this CPU(%s), ignoring it",
 +             elm);
 +      continue;
 +    }
 +    XBT_DEBUG("Add state trace: %s to CPU(%s)", trace_name, elm);
 +    cpu->p_stateEvent = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(cpu));
 +  }
 +
 +  xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
 +    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 +    CpuTiPtr cpu = dynamic_cast<CpuTiPtr>(static_cast<ResourcePtr>(surf_cpu_resource_priv(surf_cpu_resource_by_name(elm))));
 +
 +    xbt_assert(cpu, "Host %s undefined", elm);
 +    xbt_assert(trace, "Trace %s undefined", trace_name);
 +
 +    XBT_DEBUG("Add power trace: %s to CPU(%s)", trace_name, elm);
 +    if (cpu->p_availTrace)
 +      delete cpu->p_availTrace;
 +
 +    cpu->p_availTrace = new CpuTiTgmr(trace, cpu->m_powerScale);
 +
 +    /* add a fake trace event if periodicity == 0 */
 +    if (trace && xbt_dynar_length(trace->s_list.event_list) > 1) {
 +      s_tmgr_event_t val;
 +      xbt_dynar_get_cpy(trace->s_list.event_list,
 +                        xbt_dynar_length(trace->s_list.event_list) - 1, &val);
 +      if (val.delta == 0) {
 +        tmgr_trace_t empty_trace;
 +        empty_trace = tmgr_empty_trace_new();
 +        cpu->p_powerEvent =
 +            tmgr_history_add_trace(history, empty_trace,
 +                                   cpu->p_availTrace->m_lastTime, 0, static_cast<ResourcePtr>(cpu));
 +      }
 +    }
 +  }
 +}
 +
 +/************
 + * Resource *
 + ************/
 +CpuTi::CpuTi(CpuTiModelPtr model, const char *name, xbt_dynar_t powerPeak,
 +        int pstate, double powerScale, tmgr_trace_t powerTrace, int core,
 +        e_surf_resource_state_t stateInitial, tmgr_trace_t stateTrace,
 +      xbt_dict_t properties) :
 +      Resource(model, name, properties), Cpu(model, name, properties) {
 +  p_stateCurrent = stateInitial;
 +  m_powerScale = powerScale;
 +  m_core = core;
 +  tmgr_trace_t empty_trace;           
 +  s_tmgr_event_t val;         
 +  xbt_assert(core==1,"Multi-core not handled with this model yet");
 +  XBT_DEBUG("power scale %lf", powerScale);
 +  p_availTrace = new CpuTiTgmr(powerTrace, powerScale);
 +
 +  CpuTiActionPtr action;
 +  p_actionSet = xbt_swag_new(xbt_swag_offset(*action, p_cpuListHookup));
 +
 +  xbt_dynar_get_cpy(powerPeak, 0, &m_powerPeak);
 +  xbt_dynar_free(&powerPeak);  /* kill memory leak */
 +  m_pstate = pstate;
 +  XBT_DEBUG("CPU create: peak=%f, pstate=%d", m_powerPeak, m_pstate);
 +
 +  p_modifiedCpuHookup.prev = 0;
 +  p_modifiedCpuHookup.next = 0;
 +
 +  if (stateTrace)
 +    p_stateEvent = tmgr_history_add_trace(history, stateTrace, 0.0, 0, static_cast<ResourcePtr>(this));
 +  if (powerTrace && xbt_dynar_length(powerTrace->s_list.event_list) > 1) {
 +    // add a fake trace event if periodicity == 0 
 +    xbt_dynar_get_cpy(powerTrace->s_list.event_list,
 +                      xbt_dynar_length(powerTrace->s_list.event_list) - 1, &val);
 +    if (val.delta == 0) {
 +      empty_trace = tmgr_empty_trace_new();
 +      p_powerEvent =
 +        tmgr_history_add_trace(history, empty_trace,
 +                               p_availTrace->m_lastTime, 0, static_cast<ResourcePtr>(this));
 +    }
 +  }
 +};
 +
 +void CpuTi::updateState(tmgr_trace_event_t event_type,
 +                        double value, double date)
 +{
 +  void *_action;
 +  CpuTiActionPtr action;
 +
 +  if (event_type == p_powerEvent) {
 +    tmgr_trace_t power_trace;
 +    CpuTiTgmrPtr trace;
 +    s_tmgr_event_t val;
 +
 +    XBT_DEBUG("Finish trace date: %f value %lf date %f", surf_get_clock(),
 +           value, date);
 +    /* update remaining of actions and put in modified cpu swag */
 +    updateRemainingAmount(date);
 +    xbt_swag_insert(this, cpu_ti_modified_cpu);
 +
 +    power_trace = p_availTrace->p_powerTrace;
 +    xbt_dynar_get_cpy(power_trace->s_list.event_list,
 +                      xbt_dynar_length(power_trace->s_list.event_list) - 1, &val);
 +    /* free old trace */
 +    delete p_availTrace;
 +    m_powerScale = val.value;
 +
 +    trace = new CpuTiTgmr(TRACE_FIXED, val.value);
 +    XBT_DEBUG("value %f", val.value);
 +
 +    p_availTrace = trace;
 +
 +    if (tmgr_trace_event_free(event_type))
 +      p_powerEvent = NULL;
 +
 +  } else if (event_type == p_stateEvent) {
 +    if (value > 0) {
 +      if(p_stateCurrent == SURF_RESOURCE_OFF)
 +        xbt_dynar_push_as(host_that_restart, char*, (char *)m_name);
 +      p_stateCurrent = SURF_RESOURCE_ON;
 +    } else {
 +      p_stateCurrent = SURF_RESOURCE_OFF;
 +
 +      /* put all action running on cpu to failed */
 +      xbt_swag_foreach(_action, p_actionSet) {
 +      action = static_cast<CpuTiActionPtr>(_action);
 +        if (action->getState() == SURF_ACTION_RUNNING
 +         || action->getState() == SURF_ACTION_READY
 +         || action->getState() == SURF_ACTION_NOT_IN_THE_SYSTEM) {
 +          action->m_finish = date;
 +          action->setState(SURF_ACTION_FAILED);
 +          if (action->m_indexHeap >= 0) {
 +            CpuTiActionPtr heap_act = (CpuTiActionPtr)
 +                xbt_heap_remove(cpu_ti_action_heap, action->m_indexHeap);
 +            if (heap_act != action)
 +              DIE_IMPOSSIBLE;
 +          }
 +        }
 +      }
 +    }
 +    if (tmgr_trace_event_free(event_type))
 +      p_stateEvent = NULL;
 +  } else {
 +    XBT_CRITICAL("Unknown event ! \n");
 +    xbt_abort();
 +  }
 +
 +  return;
 +}
 +
 +void CpuTi::updateActionFinishDate(double now)
 +{
 +  void *_action;
 +  CpuTiActionPtr action;
 +  double sum_priority = 0.0, total_area, min_finish = -1;
 +
 +/* update remaning amount of actions */
 +updateRemainingAmount(now);
 +
 +  xbt_swag_foreach(_action, p_actionSet) {
 +    action = static_cast<CpuTiActionPtr>(_action);
 +    /* action not running, skip it */
 +    if (action->p_stateSet !=
-         surf_cpu_model->p_runningActionSet)
++        surf_cpu_model_pm->p_runningActionSet)
 +      continue;
 +
 +    /* bogus priority, skip it */
 +    if (action->m_priority <= 0)
 +      continue;
 +
 +    /* action suspended, skip it */
 +    if (action->m_suspended != 0)
 +      continue;
 +
 +    sum_priority += 1.0 / action->m_priority;
 +  }
 +  m_sumPriority = sum_priority;
 +
 +  xbt_swag_foreach(_action, p_actionSet) {
 +    action = static_cast<CpuTiActionPtr>(_action);
 +    min_finish = -1;
 +    /* action not running, skip it */
 +    if (action->p_stateSet !=
++        surf_cpu_model_pm->p_runningActionSet)
 +      continue;
 +
 +    /* verify if the action is really running on cpu */
 +    if (action->m_suspended == 0 && action->m_priority > 0) {
 +      /* total area needed to finish the action. Used in trace integration */
 +      total_area =
 +          (action->m_remains) * sum_priority *
 +           action->m_priority;
 +
 +      total_area /= m_powerPeak;
 +
 +      action->m_finish = p_availTrace->solve(now, total_area);
 +      /* verify which event will happen before (max_duration or finish time) */
 +      if (action->m_maxDuration != NO_MAX_DURATION &&
 +          action->m_start + action->m_maxDuration < action->m_finish)
 +        min_finish = action->m_start + action->m_maxDuration;
 +      else
 +        min_finish = action->m_finish;
 +    } else {
 +      /* put the max duration time on heap */
 +      if (action->m_maxDuration != NO_MAX_DURATION)
 +        min_finish = action->m_start + action->m_maxDuration;
 +    }
 +    /* add in action heap */
 +    XBT_DEBUG("action(%p) index %d", action, action->m_indexHeap);
 +    if (action->m_indexHeap >= 0) {
 +      CpuTiActionPtr heap_act = (CpuTiActionPtr)
 +          xbt_heap_remove(cpu_ti_action_heap, action->m_indexHeap);
 +      if (heap_act != action)
 +        DIE_IMPOSSIBLE;
 +    }
 +    if (min_finish != NO_MAX_DURATION)
 +      xbt_heap_push(cpu_ti_action_heap, action, min_finish);
 +
 +    XBT_DEBUG
 +        ("Update finish time: Cpu(%s) Action: %p, Start Time: %f Finish Time: %f Max duration %f",
 +         m_name, action, action->m_start,
 +         action->m_finish,
 +         action->m_maxDuration);
 +  }
 +/* remove from modified cpu */
 +  xbt_swag_remove(this, cpu_ti_modified_cpu);
 +}
 +
 +bool CpuTi::isUsed()
 +{
 +  return xbt_swag_size(p_actionSet);
 +}
 +
 +
 +
 +double CpuTi::getAvailableSpeed()
 +{
 +  m_powerScale = p_availTrace->getPowerScale(surf_get_clock());
 +  return Cpu::getAvailableSpeed();
 +}
 +
 +/**
 +* \brief Update the remaining amount of actions
 +*
 +* \param  now    Current time
 +*/
 +void CpuTi::updateRemainingAmount(double now)
 +{
 +  double area_total;
 +  void* _action;
 +  CpuTiActionPtr action;
 +
 +  /* already updated */
 +  if (m_lastUpdate >= now)
 +    return;
 +
 +/* calcule the surface */
 +  area_total = p_availTrace->integrate(m_lastUpdate, now) * m_powerPeak;
 +  XBT_DEBUG("Flops total: %f, Last update %f", area_total,
 +         m_lastUpdate);
 +
 +  xbt_swag_foreach(_action, p_actionSet) {
 +    action = static_cast<CpuTiActionPtr>(_action);
 +    /* action not running, skip it */
 +    if (action->p_stateSet !=
 +        getModel()->p_runningActionSet)
 +      continue;
 +
 +    /* bogus priority, skip it */
 +    if (action->m_priority <= 0)
 +      continue;
 +
 +    /* action suspended, skip it */
 +    if (action->m_suspended != 0)
 +      continue;
 +
 +    /* action don't need update */
 +    if (action->m_start >= now)
 +      continue;
 +
 +    /* skip action that are finishing now */
 +    if (action->m_finish >= 0
 +        && action->m_finish <= now)
 +      continue;
 +
 +    /* update remaining */
 +    double_update(&(action->m_remains),
 +                  area_total / (m_sumPriority *
 +                                action->m_priority));
 +    XBT_DEBUG("Update remaining action(%p) remaining %f", action,
 +           action->m_remains);
 +  }
 +  m_lastUpdate = now;
 +}
 +
 +CpuActionPtr CpuTi::execute(double size)
 +{
 +  return _execute(size);
 +}
 +
 +CpuTiActionPtr CpuTi::_execute(double size)
 +{
 +  XBT_IN("(%s,%g)", m_name, size);
 +  CpuTiActionPtr action = new CpuTiAction(static_cast<CpuTiModelPtr>(p_model), size, p_stateCurrent != SURF_RESOURCE_ON);
 +
 +  action->p_cpu = this;
 +  action->m_indexHeap = -1;
 +
 +  xbt_swag_insert(this, cpu_ti_modified_cpu);
 +
 +  xbt_swag_insert(action, p_actionSet);
 +
 +  action->m_suspended = 0;        /* Should be useless because of the
 +              »                     calloc but it seems to help valgrind... */
 +
 +  XBT_OUT();
 +  return action;
 +}
 +
 +
 +CpuActionPtr CpuTi::sleep(double duration)
 +{
 +  if (duration > 0)
 +    duration = MAX(duration, MAXMIN_PRECISION);
 +
 +  XBT_IN("(%s,%g)", m_name, duration);
 +  CpuTiActionPtr action = _execute(1.0);
 +  action->m_maxDuration = duration;
 +  action->m_suspended = 2;
 +  if (duration == NO_MAX_DURATION) {
 +    /* Move to the *end* of the corresponding action set. This convention
 +       is used to speed up update_resource_state  */
 +    xbt_swag_remove(static_cast<ActionPtr>(action), action->p_stateSet);
 +    action->p_stateSet = cpu_ti_running_action_set_that_does_not_need_being_checked;
 +    xbt_swag_insert(static_cast<ActionPtr>(action), action->p_stateSet);
 +  }
 +  XBT_OUT();
 +  return action;
 +}
 +
 +void CpuTi::printCpuTiModel()
 +{
 +  std::cout << getModel()->getName() << "<<plop"<< std::endl;
 +};
 +
 +/**********
 + * Action *
 + **********/
 +static void cpu_ti_action_update_index_heap(void *action, int i)
 +{
 +  ((CpuTiActionPtr)action)->updateIndexHeap(i); 
 +}
 +void CpuTiAction::updateIndexHeap(int i)
 +{
 +  m_indexHeap = i;
 +}
 +
 +void CpuTiAction::setState(e_surf_action_state_t state)
 +{
 +  Action::setState(state);
 +  xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
 +}
 +
 +int CpuTiAction::unref()
 +{
 +  m_refcount--;
 +  if (!m_refcount) {
 +    xbt_swag_remove(static_cast<ActionPtr>(this), p_stateSet);
 +    /* remove from action_set */
 +    xbt_swag_remove(this, p_cpu->p_actionSet);
 +    /* remove from heap */
 +    xbt_heap_remove(cpu_ti_action_heap, this->m_indexHeap);
 +    xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
 +    delete this;
 +    return 1;
 +  }
 +  return 0;
 +}
 +
 +void CpuTiAction::cancel()
 +{
 +  this->setState(SURF_ACTION_FAILED);
 +  xbt_heap_remove(cpu_ti_action_heap, this->m_indexHeap);
 +  xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
 +  return;
 +}
 +
 +void CpuTiAction::recycle()
 +{
 +  DIE_IMPOSSIBLE;
 +}
 +
 +void CpuTiAction::suspend()
 +{
 +  XBT_IN("(%p)", this);
 +  if (m_suspended != 2) {
 +    m_suspended = 1;
 +    xbt_heap_remove(cpu_ti_action_heap, m_indexHeap);
 +    xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
 +  }
 +  XBT_OUT();
 +}
 +
 +void CpuTiAction::resume()
 +{
 +  XBT_IN("(%p)", this);
 +  if (m_suspended != 2) {
 +    m_suspended = 0;
 +    xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
 +  }
 +  XBT_OUT();
 +}
 +
 +bool CpuTiAction::isSuspended()
 +{
 +  return m_suspended == 1;
 +}
 +
 +void CpuTiAction::setMaxDuration(double duration)
 +{
 +  double min_finish;
 +
 +  XBT_IN("(%p,%g)", this, duration);
 +
 +  m_maxDuration = duration;
 +
 +  if (duration >= 0)
 +    min_finish = (m_start + m_maxDuration) < m_finish ?
 +                 (m_start + m_maxDuration) : m_finish;
 +  else
 +    min_finish = m_finish;
 +
 +/* add in action heap */
 +  if (m_indexHeap >= 0) {
 +    CpuTiActionPtr heap_act = (CpuTiActionPtr)
 +        xbt_heap_remove(cpu_ti_action_heap, m_indexHeap);
 +    if (heap_act != this)
 +      DIE_IMPOSSIBLE;
 +  }
 +  xbt_heap_push(cpu_ti_action_heap, this, min_finish);
 +
 +  XBT_OUT();
 +}
 +
 +void CpuTiAction::setPriority(double priority)
 +{
 +  XBT_IN("(%p,%g)", this, priority);
 +  m_priority = priority;
 +  xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
 +  XBT_OUT();
 +}
 +
 +double CpuTiAction::getRemains()
 +{
 +  XBT_IN("(%p)", this);
 +  p_cpu->updateRemainingAmount(surf_get_clock());
 +  XBT_OUT();
 +  return m_remains;
 +}
 +
 +static void check() {
 +  CpuTiActionPtr cupAction = new CpuTiAction(NULL, 0, true);
 +}
 +
 +#endif /* SURF_MODEL_CPUTI_H_ */
 +
diff --combined src/surf/surf.cpp
index b46787d,0000000..366e6ed
mode 100644,000000..100644
--- /dev/null
@@@ -1,1031 -1,0 +1,1051 @@@
- xbt_dynar_t model_list = NULL;
 +#include "surf_private.h"
 +#include "surf.hpp"
 +#include "network.hpp"
 +#include "cpu.hpp"
 +#include "workstation.hpp"
++#include "vm_workstation.hpp"
 +#include "simix/smx_host_private.h"
 +#include "surf_routing.hpp"
 +#include "simgrid/sg_config.h"
 +#include "mc/mc.h"
 +
 +extern "C" {
 +XBT_LOG_NEW_CATEGORY(surf, "All SURF categories");
 +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
 +                                "Logging specific to SURF (kernel)");
 +}
 +
 +/*********
 + * Utils *
 + *********/
 +
 +/* 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((smx_host_t)host) == SURF_RESOURCE_ON){
 +      XBT_INFO("Restart processes on host: %s", SIMIX_host_get_name((smx_host_t)host));
 +      SIMIX_host_autorestart((smx_host_t)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);
 +}*/
 +
++/* model_list_invoke contains only surf_workstation and surf_vm_workstation.
++ * The callback functions of cpu_model and network_model will be called from
++ * those of these workstation models. */
++xbt_dynar_t model_list = NULL; /* for destroying all models correctly */
++xbt_dynar_t model_list_invoke = NULL;  /* for invoking callbacks */
 +
-     model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
 +tmgr_history_t history = NULL;
 +lmm_system_t maxmin_system = NULL;
 +xbt_dynar_t surf_path = NULL;
 +xbt_dynar_t host_that_restart = NULL;
 +xbt_dict_t watched_hosts_lib;
 +
 +/* Don't forget to update the option description in smx_config when you change this */
 +s_surf_model_description_t surf_network_model_description[] = {
 +  {"LV08",
 +   "Realistic network analytic model (slow-start modeled by multiplying latency by 10.4, bandwidth by .92; bottleneck sharing uses a payload of S=8775 for evaluating RTT). ",
 +   surf_network_model_init_LegrandVelho},
 +  {"Constant",
 +   "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.",
 +   surf_network_model_init_Constant},
 +  {"SMPI",
 +   "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)",
 +   surf_network_model_init_SMPI},
 +  {"CM02",
 +   "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).",
 +   surf_network_model_init_CM02},
 +#ifdef HAVE_GTNETS
 +  {"GTNets",
 +   "Network pseudo-model using the GTNets simulator instead of an analytic model",
 +   surf_network_model_init_GTNETS},
 +#endif
 +#ifdef HAVE_NS3
 +  {"NS3",
 +   "Network pseudo-model using the NS3 tcp model instead of an analytic model",
 +  surf_network_model_init_NS3},
 +#endif
 +  {"Reno",
 +   "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
 +   surf_network_model_init_Reno},
 +  {"Reno2",
 +   "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
 +   surf_network_model_init_Reno2},
 +  {"Vegas",
 +   "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).",
 +   surf_network_model_init_Vegas},
 +  {NULL, NULL, NULL}      /* this array must be NULL terminated */
 +};
 +
 +s_surf_model_description_t surf_cpu_model_description[] = {
 +  {"Cas01",
 +   "Simplistic CPU model (time=size/power).",
 +   surf_cpu_model_init_Cas01},
 +  {NULL, NULL,  NULL}      /* this array must be NULL terminated */
 +};
 +
 +s_surf_model_description_t surf_workstation_model_description[] = {
 +  {"default",
 +   "Default workstation model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)",
 +   surf_workstation_model_init_current_default},
 +  {"compound",
 +   "Workstation model that is automatically chosen if you change the network and CPU models",
 +   surf_workstation_model_init_compound},
 +  {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks",
 +   surf_workstation_model_init_ptask_L07},
 +  {NULL, NULL, NULL}      /* this array must be NULL terminated */
 +};
 +
++s_surf_model_description_t surf_vm_workstation_model_description[] = {
++  {"default",
++   "Default vm workstation model.)",
++   surf_vm_workstation_model_init_current_default},
++  {NULL, NULL, NULL}      /* this array must be NULL terminated */
++};
++
 +s_surf_model_description_t surf_optimization_mode_description[] = {
 +  {"Lazy",
 +   "Lazy action management (partial invalidation in lmm + heap in action remaining).",
 +   NULL},
 +  {"TI",
 +   "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).",
 +    NULL},
 +  {"Full",
 +   "Full update of remaining and variables. Slow but may be useful when debugging.",
 +   NULL},
 +  {NULL, NULL, NULL}      /* this array must be NULL terminated */
 +};
 +
 +s_surf_model_description_t surf_storage_model_description[] = {
 +  {"default",
 +   "Simplistic storage model.",
 +   surf_storage_model_init_default},
 +  {NULL, NULL,  NULL}      /* this array must be NULL terminated */
 +};
 +
 +#ifdef CONTEXT_THREADS
 +static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
 +#endif
 +
 +static double *surf_mins = NULL; /* return value of share_resources for each model */
 +static int surf_min_index;       /* current index in surf_mins */
 +static double min;               /* duration determined by surf_solve */
 +
 +double NOW = 0;
 +
 +double surf_get_clock(void)
 +{
 +  return NOW;
 +}
 +
 +#ifdef _XBT_WIN32
 +# define FILE_DELIM "\\"
 +#else
 +# define FILE_DELIM "/"         /* FIXME: move to better location */
 +#endif
 +
 +FILE *surf_fopen(const char *name, const char *mode)
 +{
 +  unsigned int cpt;
 +  char *path_elm = NULL;
 +  char *buff;
 +  FILE *file = NULL;
 +
 +  xbt_assert(name);
 +
 +  if (__surf_is_absolute_file_path(name))       /* don't mess with absolute file names */
 +    return fopen(name, mode);
 +
 +  /* search relative files in the path */
 +  xbt_dynar_foreach(surf_path, cpt, path_elm) {
 +    buff = bprintf("%s" FILE_DELIM "%s", path_elm, name);
 +    file = fopen(buff, mode);
 +    free(buff);
 +
 +    if (file)
 +      return file;
 +  }
 +  return NULL;
 +}
 +
 +/*
 + * Returns the initial path. On Windows the initial path is
 + * the current directory for the current process in the other
 + * case the function returns "./" that represents the current
 + * directory on Unix/Linux platforms.
 + */
 +
 +const char *__surf_get_initial_path(void)
 +{
 +
 +#ifdef _XBT_WIN32
 +  unsigned i;
 +  char current_directory[MAX_PATH + 1] = { 0 };
 +  unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory);
 +  char root[4] = { 0 };
 +
 +  if (!len)
 +    return NULL;
 +
 +  strncpy(root, current_directory, 3);
 +
 +  for (i = 0; i < MAX_DRIVE; i++) {
 +    if (toupper(root[0]) == disk_drives_letter_table[i][0])
 +      return disk_drives_letter_table[i];
 +  }
 +
 +  return NULL;
 +#else
 +  return "./";
 +#endif
 +}
 +
 +/* The __surf_is_absolute_file_path() returns 1 if
 + * file_path is a absolute file path, in the other
 + * case the function returns 0.
 + */
 +int __surf_is_absolute_file_path(const char *file_path)
 +{
 +#ifdef _XBT_WIN32
 +  WIN32_FIND_DATA wfd = { 0 };
 +  HANDLE hFile = FindFirstFile(file_path, &wfd);
 +
 +  if (INVALID_HANDLE_VALUE == hFile)
 +    return 0;
 +
 +  FindClose(hFile);
 +  return 1;
 +#else
 +  return (file_path[0] == '/');
 +#endif
 +}
 +
 +/** Displays the long description of all registered models, and quit */
 +void model_help(const char *category, s_surf_model_description_t * table)
 +{
 +  int i;
 +  printf("Long description of the %s models accepted by this simulator:\n",
 +         category);
 +  for (i = 0; table[i].name; i++)
 +    printf("  %s: %s\n", table[i].name, table[i].description);
 +}
 +
 +int find_model_description(s_surf_model_description_t * table,
 +                           const char *name)
 +{
 +  int i;
 +  char *name_list = NULL;
 +
 +  for (i = 0; table[i].name; i++)
 +    if (!strcmp(name, table[i].name)) {
 +      return i;
 +    }
 +  name_list = strdup(table[0].name);
 +  for (i = 1; table[i].name; i++) {
 +    name_list = (char *) xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 3);
 +    strcat(name_list, ", ");
 +    strcat(name_list, table[i].name);
 +  }
 +  xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list);
 +  return -1;
 +}
 +
 +static XBT_INLINE void routing_asr_host_free(void *p)
 +{
 +  delete ((RoutingEdgePtr) p);
 +}
 +
 +static XBT_INLINE void routing_asr_prop_free(void *p)
 +{
 +  xbt_dict_t elm = (xbt_dict_t) p;
 +  xbt_dict_free(&elm);
 +}
 +
 +static XBT_INLINE void surf_cpu_free(void *r)
 +{
 +  delete dynamic_cast<CpuPtr>(static_cast<ResourcePtr>(r));
 +}
 +
 +static XBT_INLINE void surf_link_free(void *r)
 +{
 +  delete dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(r));
 +}
 +
 +static XBT_INLINE void surf_workstation_free(void *r)
 +{
 +  delete dynamic_cast<WorkstationCLM03Ptr>(static_cast<ResourcePtr>(r));
 +}
 +
 +
 +void sg_version(int *ver_major,int *ver_minor,int *ver_patch) {
 +  *ver_major = SIMGRID_VERSION_MAJOR;
 +  *ver_minor = SIMGRID_VERSION_MINOR;
 +  *ver_patch = SIMGRID_VERSION_PATCH;
 +}
 +
 +void surf_init(int *argc, char **argv)
 +{
 +  XBT_DEBUG("Create all Libs");
 +  host_lib = xbt_lib_new();
 +  link_lib = xbt_lib_new();
 +  as_router_lib = xbt_lib_new();
 +  storage_lib = xbt_lib_new();
 +  storage_type_lib = xbt_lib_new();
 +  watched_hosts_lib = xbt_dict_new_homogeneous(NULL);
 +
 +  XBT_DEBUG("Add routing levels");
 +  ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,routing_asr_host_free);
 +  ROUTING_ASR_LEVEL  = xbt_lib_add_level(as_router_lib,routing_asr_host_free);
 +  ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free);
 +
 +  XBT_DEBUG("Add SURF levels");
 +  SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_cpu_free);
 +  SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_workstation_free);
 +  SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_link_free);
 +
 +  xbt_init(argc, argv);
 +  if (!model_list)
-     if (p_model == static_cast<ModelPtr>(surf_cpu_model) && TRACE_is_enabled()) {
++    model_list = xbt_dynar_new(sizeof(ModelPtr), NULL);
++  if (!model_list_invoke)
++    model_list_invoke = xbt_dynar_new(sizeof(ModelPtr), NULL);
 +  if (!history)
 +    history = tmgr_history_new();
 +
 +#ifdef HAVE_TRACING
 +  TRACE_add_start_function(TRACE_surf_alloc);
 +  TRACE_add_end_function(TRACE_surf_release);
 +#endif
 +
 +  sg_config_init(argc, argv);
 +
 +  if (MC_is_active())
 +    MC_memory_init();
 +}
 +
 +void surf_exit(void)
 +{
 +  unsigned int iter;
 +  ModelPtr model = NULL;
 +
 +#ifdef HAVE_TRACING
 +  TRACE_end();                  /* Just in case it was not called by the upper
 +                                 * layer (or there is no upper layer) */
 +#endif
 +
 +  sg_config_finalize();
 +
 +  xbt_dynar_foreach(model_list, iter, model)
 +    delete model;
 +  xbt_dynar_free(&model_list);
++  xbt_dynar_free(&model_list_invoke);
 +  routing_exit();
 +
 +  if (maxmin_system) {
 +    lmm_system_free(maxmin_system);
 +    maxmin_system = NULL;
 +  }
 +  if (history) {
 +    tmgr_history_free(history);
 +    history = NULL;
 +  }
 +
 +#ifdef CONTEXT_THREADS
 +  xbt_parmap_destroy(surf_parmap);
 +  xbt_free(surf_mins);
 +  surf_mins = NULL;
 +#endif
 +  xbt_dynar_free(&host_that_restart);
 +  xbt_dynar_free(&surf_path);
 +
 +  xbt_lib_free(&host_lib);
 +  xbt_lib_free(&link_lib);
 +  xbt_lib_free(&as_router_lib);
 +  xbt_lib_free(&storage_lib);
 +  xbt_lib_free(&storage_type_lib);
 +
 +  xbt_dict_free(&watched_hosts_lib);
 +
 +  tmgr_finalize();
 +  surf_parse_lex_destroy();
 +  surf_parse_free_callbacks();
 +
 +  NOW = 0;                      /* Just in case the user plans to restart the simulation afterward */
 +}
 +/*********
 + * Model *
 + *********/
 +
 +Model::Model(string name)
 + : m_name(name), m_resOnCB(0), m_resOffCB(0),
 +   m_actSuspendCB(0), m_actCancelCB(0), m_actResumeCB(0),
 +   p_maxminSystem(0)
 +{
 +  ActionPtr action;
 +  p_readyActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
 +  p_runningActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
 +  p_failedActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
 +  p_doneActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
 +
 +  p_modifiedSet = NULL;
 +  p_actionHeap = NULL;
 +  p_updateMechanism = UM_UNDEFINED;
 +  m_selectiveUpdate = 0;
 +}
 +
 +Model::~Model(){
 +xbt_swag_free(p_readyActionSet);
 +xbt_swag_free(p_runningActionSet);
 +xbt_swag_free(p_failedActionSet);
 +xbt_swag_free(p_doneActionSet);
 +}
 +
 +double Model::shareResources(double now)
 +{
 +  //FIXME: set the good function once and for all
 +  if (p_updateMechanism == UM_LAZY)
 +      return shareResourcesLazy(now);
 +  else if (p_updateMechanism == UM_FULL)
 +      return shareResourcesFull(now);
 +  else
 +      xbt_die("Invalid cpu update mechanism!");
 +}
 +
 +double Model::shareResourcesLazy(double now)
 +{
 +  ActionLmmPtr action = NULL;
 +  double min = -1;
 +  double value;
 +
 +  XBT_DEBUG
 +      ("Before share resources, the size of modified actions set is %d",
 +       xbt_swag_size(p_modifiedSet));
 +
 +  lmm_solve(p_maxminSystem);
 +
 +  XBT_DEBUG
 +      ("After share resources, The size of modified actions set is %d",
 +       xbt_swag_size(p_modifiedSet));
 +
 +  while((action = static_cast<ActionLmmPtr>(xbt_swag_extract(p_modifiedSet)))) {
 +    int max_dur_flag = 0;
 +
 +    if (action->p_stateSet != p_runningActionSet)
 +      continue;
 +
 +    /* bogus priority, skip it */
 +    if (action->m_priority <= 0)
 +      continue;
 +
 +    action->updateRemainingLazy(now);
 +
 +    min = -1;
 +    value = lmm_variable_getvalue(action->p_variable);
 +    if (value > 0) {
 +      if (action->m_remains > 0) {
 +        value = action->m_remains / value;
 +        min = now + value;
 +      } else {
 +        value = 0.0;
 +        min = now;
 +      }
 +    }
 +
 +    if ((action->m_maxDuration != NO_MAX_DURATION)
 +        && (min == -1
 +            || action->m_start +
 +            action->m_maxDuration < min)) {
 +      min = action->m_start +
 +          action->m_maxDuration;
 +      max_dur_flag = 1;
 +    }
 +
 +    XBT_DEBUG("Action(%p) Start %lf Finish %lf Max_duration %lf", action,
 +        action->m_start, now + value,
 +        action->m_maxDuration);
 +
 +    if (min != -1) {
 +      action->heapRemove(p_actionHeap);
 +      action->heapInsert(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
 +      XBT_DEBUG("Insert at heap action(%p) min %lf now %lf", action, min,
 +                now);
 +    } else DIE_IMPOSSIBLE;
 +  }
 +
 +  //hereafter must have already the min value for this resource model
 +  if (xbt_heap_size(p_actionHeap) > 0)
 +    min = xbt_heap_maxkey(p_actionHeap) - now;
 +  else
 +    min = -1;
 +
 +  XBT_DEBUG("The minimum with the HEAP %lf", min);
 +
 +  return min;
 +}
 +
 +double Model::shareResourcesFull(double now) {
 +  THROW_UNIMPLEMENTED;
 +}
 +
 +
 +double Model::shareResourcesMaxMin(xbt_swag_t running_actions,
 +                          lmm_system_t sys,
 +                          void (*solve) (lmm_system_t))
 +{
 +  void *_action = NULL;
 +  ActionLmmPtr action = NULL;
 +  double min = -1;
 +  double value = -1;
 +
 +  solve(sys);
 +
 +  xbt_swag_foreach(_action, running_actions) {
 +    action = dynamic_cast<ActionLmmPtr>(static_cast<ActionPtr>(_action));
 +    value = lmm_variable_getvalue(action->p_variable);
 +    if ((value > 0) || (action->m_maxDuration >= 0))
 +      break;
 +  }
 +
 +  if (!_action)
 +    return -1.0;
 +
 +  if (value > 0) {
 +    if (action->m_remains > 0)
 +      min = action->m_remains / value;
 +    else
 +      min = 0.0;
 +    if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min))
 +      min = action->m_maxDuration;
 +  } else
 +    min = action->m_maxDuration;
 +
 +
 +  for (_action = xbt_swag_getNext(static_cast<ActionPtr>(action), running_actions->offset);
 +       _action;
 +       _action = xbt_swag_getNext(static_cast<ActionPtr>(action), running_actions->offset)) {
 +      action = dynamic_cast<ActionLmmPtr>(static_cast<ActionPtr>(_action));
 +    value = lmm_variable_getvalue(action->p_variable);
 +    if (value > 0) {
 +      if (action->m_remains > 0)
 +        value = action->m_remains / value;
 +      else
 +        value = 0.0;
 +      if (value < min) {
 +        min = value;
 +        XBT_DEBUG("Updating min (value) with %p: %f", action, min);
 +      }
 +    }
 +    if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min)) {
 +      min = action->m_maxDuration;
 +      XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
 +    }
 +  }
 +  XBT_DEBUG("min value : %f", min);
 +
 +  return min;
 +}
 +
 +void Model::updateActionsState(double now, double delta)
 +{
 +  if (p_updateMechanism == UM_FULL)
 +      updateActionsStateFull(now, delta);
 +  else if (p_updateMechanism == UM_LAZY)
 +      updateActionsStateLazy(now, delta);
 +  else
 +      xbt_die("Invalid cpu update mechanism!");
 +}
 +
 +void Model::updateActionsStateLazy(double now, double delta)
 +{
 +
 +}
 +
 +void Model::updateActionsStateFull(double now, double delta)
 +{
 +
 +}
 +
 +
 +void Model::addTurnedOnCallback(ResourceCallback rc)
 +{
 +  m_resOnCB = rc;
 +}
 +
 +void Model::notifyResourceTurnedOn(ResourcePtr r)
 +{
 +  m_resOnCB(r);
 +}
 +
 +void Model::addTurnedOffCallback(ResourceCallback rc)
 +{
 +  m_resOffCB = rc;
 +}
 +
 +void Model::notifyResourceTurnedOff(ResourcePtr r)
 +{
 +  m_resOffCB(r);
 +}
 +
 +void Model::addActionCancelCallback(ActionCallback ac)
 +{
 +  m_actCancelCB = ac;
 +}
 +
 +void Model::notifyActionCancel(ActionPtr a)
 +{
 +  m_actCancelCB(a);
 +}
 +
 +void Model::addActionResumeCallback(ActionCallback ac)
 +{
 +  m_actResumeCB = ac;
 +}
 +
 +void Model::notifyActionResume(ActionPtr a)
 +{
 +  m_actResumeCB(a);
 +}
 +
 +void Model::addActionSuspendCallback(ActionCallback ac)
 +{
 +  m_actSuspendCB = ac;
 +}
 +
 +void Model::notifyActionSuspend(ActionPtr a)
 +{
 +  m_actSuspendCB(a);
 +}
 +
 +
 +/************
 + * Resource *
 + ************/
 +
 +Resource::Resource(surf_model_t model, const char *name, xbt_dict_t props)
 +  : m_name(xbt_strdup(name)), m_running(true), p_model(model), m_properties(props)
 +{}
 +
 +Resource::Resource(){
 +  //FIXME:free(m_name);
 +  //FIXME:xbt_dict_free(&m_properties);
 +}
 +
 +const char *Resource::getName()
 +{
 +  return m_name;
 +}
 +
 +xbt_dict_t Resource::getProperties()
 +{
 +  return m_properties;
 +}
 +
 +e_surf_resource_state_t Resource::getState()
 +{
 +  return p_stateCurrent;
 +}
 +
++void Resource::setState(e_surf_resource_state_t state)
++{
++  p_stateCurrent = state;
++}
++
 +bool Resource::isOn()
 +{
 +  return m_running;
 +}
 +
 +void Resource::turnOn()
 +{
 +  if (!m_running) {
 +    m_running = true;
 +    p_model->notifyResourceTurnedOn(this);
 +  }
 +}
 +
 +void Resource::turnOff()
 +{
 +  if (m_running) {
 +    m_running = false;
 +    p_model->notifyResourceTurnedOff(this);
 +  }
 +}
 +
 +ResourceLmm::ResourceLmm(surf_model_t model, const char *name, xbt_dict_t props,
 +                         lmm_system_t system,
 +                         double constraint_value,
 +                         tmgr_history_t history,
 +                         e_surf_resource_state_t state_init,
 +                         tmgr_trace_t state_trace,
 +                         double metric_peak,
 +                         tmgr_trace_t metric_trace)
 +  : Resource(model, name, props)
 +{
 +  p_constraint = lmm_constraint_new(system, this, constraint_value);
 +  p_stateCurrent = state_init;
 +  if (state_trace)
 +    p_stateEvent = tmgr_history_add_trace(history, state_trace, 0.0, 0, static_cast<ResourcePtr>(this));
 +  p_power.scale = 1.0;
 +  p_power.peak = metric_peak;
 +  if (metric_trace)
 +    p_power.event = tmgr_history_add_trace(history, metric_trace, 0.0, 0, static_cast<ResourcePtr>(this));
 +}
 +
 +/**********
 + * Action *
 + **********/
 +
 +const char *surf_action_state_names[6] = {
 +  "SURF_ACTION_READY",
 +  "SURF_ACTION_RUNNING",
 +  "SURF_ACTION_FAILED",
 +  "SURF_ACTION_DONE",
 +  "SURF_ACTION_TO_FREE",
 +  "SURF_ACTION_NOT_IN_THE_SYSTEM"
 +};
 +
 +Action::Action(){}
 +
 +Action::Action(ModelPtr model, double cost, bool failed):
 +       m_cost(cost), p_model(model), m_failed(failed), m_remains(cost),
 +       m_refcount(1), m_priority(1.0), m_maxDuration(NO_MAX_DURATION),
 +       m_start(surf_get_clock()), m_finish(-1.0)
 +{
 +  #ifdef HAVE_TRACING
 +    p_category = NULL;
 +  #endif
 +  p_stateHookup.prev = 0;
 +  p_stateHookup.next = 0;
 +  if (failed)
 +    p_stateSet = p_model->p_failedActionSet;
 +  else
 +    p_stateSet = p_model->p_runningActionSet;
 +
 +  xbt_swag_insert(this, p_stateSet);
 +}
 +
 +Action::~Action() {}
 +
 +int Action::unref(){
 +  DIE_IMPOSSIBLE;
 +}
 +
 +void Action::cancel(){
 +  DIE_IMPOSSIBLE;
 +}
 +
 +void Action::recycle(){
 +  DIE_IMPOSSIBLE;
 +}
 +
 +e_surf_action_state_t Action::getState()
 +{
 +  if (p_stateSet ==  p_model->p_readyActionSet)
 +    return SURF_ACTION_READY;
 +  if (p_stateSet ==  p_model->p_runningActionSet)
 +    return SURF_ACTION_RUNNING;
 +  if (p_stateSet ==  p_model->p_failedActionSet)
 +    return SURF_ACTION_FAILED;
 +  if (p_stateSet ==  p_model->p_doneActionSet)
 +    return SURF_ACTION_DONE;
 +  return SURF_ACTION_NOT_IN_THE_SYSTEM;
 +}
 +
 +void Action::setState(e_surf_action_state_t state)
 +{
 +  //surf_action_state_t action_state = &(action->model_type->states);
 +  XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
 +  xbt_swag_remove(this, p_stateSet);
 +
 +  if (state == SURF_ACTION_READY)
 +    p_stateSet = p_model->p_readyActionSet;
 +  else if (state == SURF_ACTION_RUNNING)
 +    p_stateSet = p_model->p_runningActionSet;
 +  else if (state == SURF_ACTION_FAILED)
 +    p_stateSet = p_model->p_failedActionSet;
 +  else if (state == SURF_ACTION_DONE)
 +    p_stateSet = p_model->p_doneActionSet;
 +  else
 +    p_stateSet = NULL;
 +
 +  if (p_stateSet)
 +    xbt_swag_insert(this, p_stateSet);
 +  XBT_OUT();
 +}
 +
 +double Action::getStartTime()
 +{
 +  return m_start;
 +}
 +
 +double Action::getFinishTime()
 +{
 +  /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
 +  return m_remains == 0 ? m_finish : -1;
 +}
 +
 +double Action::getRemains()
 +{
 +  XBT_IN("(%p)", this);
 +  XBT_OUT();
 +  return m_remains;
 +}
 +
 +void Action::setData(void* data)
 +{
 +  p_data = data;
 +}
 +
 +#ifdef HAVE_TRACING
 +void Action::setCategory(const char *category)
 +{
 +  XBT_IN("(%p,%s)", this, category);
 +  p_category = xbt_strdup(category);
 +  XBT_OUT();
 +}
 +#endif
 +
 +void Action::ref(){
 +  m_refcount++;
 +}
 +
 +void ActionLmm::setMaxDuration(double duration)
 +{
 +  XBT_IN("(%p,%g)", this, duration);
 +  m_maxDuration = duration;
 +  if (p_model->p_updateMechanism == UM_LAZY)      // remove action from the heap
 +    heapRemove(p_model->p_actionHeap);
 +  XBT_OUT();
 +}
 +
 +void ActionLmm::gapRemove() {}
 +
 +void ActionLmm::setPriority(double priority)
 +{
 +  XBT_IN("(%p,%g)", this, priority);
 +  m_priority = priority;
 +  lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, priority);
 +
 +  if (p_model->p_updateMechanism == UM_LAZY)
 +      heapRemove(p_model->p_actionHeap);
 +  XBT_OUT();
 +}
 +
 +void ActionLmm::cancel(){
 +  setState(SURF_ACTION_FAILED);
 +  if (p_model->p_updateMechanism == UM_LAZY) {
 +    xbt_swag_remove(this, p_model->p_modifiedSet);
 +    heapRemove(p_model->p_actionHeap);
 +  }
 +}
 +
 +int ActionLmm::unref(){
 +  m_refcount--;
 +  if (!m_refcount) {
 +      xbt_swag_remove(static_cast<ActionPtr>(this), p_stateSet);
 +      if (p_variable)
 +        lmm_variable_free(p_model->p_maxminSystem, p_variable);
 +      if (p_model->p_updateMechanism == UM_LAZY) {
 +        /* remove from heap */
 +        heapRemove(p_model->p_actionHeap);
 +        xbt_swag_remove(this, p_model->p_modifiedSet);
 +    }
 +#ifdef HAVE_TRACING
 +    xbt_free(p_category);
 +#endif
 +      delete this;
 +      return 1;
 +  }
 +  return 0;
 +}
 +
 +void ActionLmm::suspend()
 +{
 +  XBT_IN("(%p)", this);
 +  if (m_suspended != 2) {
 +    lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, 0.0);
 +    m_suspended = 1;
 +    if (p_model->p_updateMechanism == UM_LAZY)
 +      heapRemove(p_model->p_actionHeap);
 +  }
 +  XBT_OUT();
 +}
 +
 +void ActionLmm::resume()
 +{
 +  XBT_IN("(%p)", this);
 +  if (m_suspended != 2) {
 +    lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, m_priority);
 +    m_suspended = 0;
 +    if (p_model->p_updateMechanism == UM_LAZY)
 +      heapRemove(p_model->p_actionHeap);
 +  }
 +  XBT_OUT();
 +}
 +
 +bool ActionLmm::isSuspended()
 +{
 +  return m_suspended == 1;
 +}
 +/* insert action on heap using a given key and a hat (heap_action_type)
 + * a hat can be of three types for communications:
 + *
 + * NORMAL = this is a normal heap entry stating the date to finish transmitting
 + * LATENCY = this is a heap entry to warn us when the latency is payed
 + * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
 + */
 +void ActionLmm::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
 +{
 +  m_hat = hat;
 +  xbt_heap_push(heap, this, key);
 +}
 +
 +void ActionLmm::heapRemove(xbt_heap_t heap)
 +{
 +  m_hat = NOTSET;
 +  if (m_indexHeap >= 0) {
 +    xbt_heap_remove(heap, m_indexHeap);
 +  }
 +}
 +
 +/* added to manage the communication action's heap */
 +void surf_action_lmm_update_index_heap(void *action, int i) {
 +  ((ActionLmmPtr)action)->updateIndexHeap(i);
 +}
 +
 +void ActionLmm::updateIndexHeap(int i) {
 +  m_indexHeap = i;
 +}
 +
 +double ActionLmm::getRemains()
 +{
 +  XBT_IN("(%p)", this);
 +  /* update remains before return it */
 +  if (p_model->p_updateMechanism == UM_LAZY)      /* update remains before return it */
 +    updateRemainingLazy(surf_get_clock());
 +  XBT_OUT();
 +  return m_remains;
 +}
 +
 +//FIXME split code in the right places
 +void ActionLmm::updateRemainingLazy(double now)
 +{
 +  double delta = 0.0;
 +
 +  if(p_model == static_cast<ModelPtr>(surf_network_model))
 +  {
 +    if (m_suspended != 0)
 +      return;
 +  }
 +  else
 +  {
 +    xbt_assert(p_stateSet == p_model->p_runningActionSet,
 +        "You're updating an action that is not running.");
 +
 +      /* bogus priority, skip it */
 +    xbt_assert(m_priority > 0,
 +        "You're updating an action that seems suspended.");
 +  }
 +
 +  delta = now - m_lastUpdate;
 +
 +  if (m_remains > 0) {
 +    XBT_DEBUG("Updating action(%p): remains was %f, last_update was: %f", this, m_remains, m_lastUpdate);
 +    double_update(&m_remains, m_lastValue * delta);
 +
 +#ifdef HAVE_TRACING
++    if (p_model == static_cast<ModelPtr>(surf_cpu_model_pm) && TRACE_is_enabled()) {
 +      ResourcePtr cpu = static_cast<ResourcePtr>(lmm_constraint_id(lmm_get_cnst_from_var(p_model->p_maxminSystem, p_variable, 0)));
 +      TRACE_surf_host_set_utilization(cpu->m_name, p_category, m_lastValue, m_lastUpdate, now - m_lastUpdate);
 +    }
 +#endif
 +    XBT_DEBUG("Updating action(%p): remains is now %f", this, m_remains);
 +  }
 +
 +  if(p_model == static_cast<ModelPtr>(surf_network_model))
 +  {
 +    if (m_maxDuration != NO_MAX_DURATION)
 +      double_update(&m_maxDuration, delta);
 +
 +    //FIXME: duplicated code
 +    if ((m_remains <= 0) &&
 +        (lmm_get_variable_weight(p_variable) > 0)) {
 +      m_finish = surf_get_clock();
 +      setState(SURF_ACTION_DONE);
 +      heapRemove(p_model->p_actionHeap);
 +    } else if (((m_maxDuration != NO_MAX_DURATION)
 +        && (m_maxDuration <= 0))) {
 +      m_finish = surf_get_clock();
 +      setState(SURF_ACTION_DONE);
 +      heapRemove(p_model->p_actionHeap);
 +    }
 +  }
 +
 +  m_lastUpdate = now;
 +  m_lastValue = lmm_variable_getvalue(p_variable);
 +}
 +
 +/*void Action::cancel()
 +{
 +  p_model->notifyActionCancel(this);
 +}
 +
 +void Action::suspend()
 +{
 +  p_model->notifyActionSuspend(this);
 +}
 +
 +void Action::resume()
 +{
 +  p_model->notifyActionResume(this);
 +}
 +
 +bool Action::isSuspended()
 +{
 +  return false;
 +}*/
 +
diff --combined src/surf/surf.hpp
index 874acdd,0000000..2afb2ce
mode 100644,000000..100644
--- /dev/null
@@@ -1,330 -1,0 +1,332 @@@
 +//using namespace generic;
 +
 +#ifndef SURF_MODEL_H_
 +#define SURF_MODEL_H_
 +
 +#include <xbt.h>
 +#include <string>
 +#include <vector>
 +#include <memory>
 +#include <boost/smart_ptr.hpp>
 +#include <boost/function.hpp>
 +#include <boost/functional/factory.hpp>
 +#include <boost/bind.hpp>
 +#include "surf/trace_mgr.h"
 +#include "xbt/lib.h"
 +#include "surf/surf_routing.h"
 +#include "simgrid/platf_interface.h"
 +#include "surf/surf.h"
 +#include "surf/surf_private.h"
 +
 +extern tmgr_history_t history;
 +#define NO_MAX_DURATION -1.0
 +
 +using namespace std;
 +
 +/** \ingroup SURF_simulation
 + *  \brief Return the current time
 + *
 + *  Return the current time in millisecond.
 + */
 +
 +/*********
 + * Utils *
 + *********/
 +
 +/* user-visible parameters */
 +extern double sg_tcp_gamma;
 +extern double sg_sender_gap;
 +extern double sg_latency_factor;
 +extern double sg_bandwidth_factor;
 +extern double sg_weight_S_parameter;
 +extern int sg_network_crosstraffic;
 +#ifdef HAVE_GTNETS
 +extern double sg_gtnets_jitter;
 +extern int sg_gtnets_jitter_seed;
 +#endif
 +extern xbt_dynar_t surf_path;
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +XBT_PUBLIC(double) surf_get_clock(void);
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +extern double sg_sender_gap;
 +XBT_PUBLIC(int)  SURF_CPU_LEVEL;    //Surf cpu level
 +
 +int __surf_is_absolute_file_path(const char *file_path);
 +
 +/***********
 + * Classes *
 + ***********/
 +//class Model;
 +typedef Model* ModelPtr;
 +
 +//class Resource;
 +typedef Resource* ResourcePtr;
 +typedef boost::function<void (ResourcePtr r)> ResourceCallback;
 +                      
 +//class Action;
 +typedef Action* ActionPtr;
 +typedef boost::function<void (ActionPtr a)> ActionCallback;
 +
 +//class ActionLmm;
 +typedef ActionLmm* ActionLmmPtr;
 +
 +enum heap_action_type{
 +  LATENCY = 100,
 +  MAX_DURATION,
 +  NORMAL,
 +  NOTSET
 +};
 +
 +/*********
 + * Trace *
 + *********/
 +/* For the trace and trace:connect tag (store their content till the end of the parsing) */
 +XBT_PUBLIC_DATA(xbt_dict_t) traces_set_list;
 +XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_host_avail;
 +XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_power;
 +XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_link_avail; 
 +XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_bandwidth; 
 +XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_latency;
 +
 +
 +/*********
 + * Model *
 + *********/
 +XBT_PUBLIC_DATA(xbt_dynar_t) model_list;
 +
 +class Model {
 +public:
 +  Model(string name);
 +  virtual ~Model();
 +
 +  ResourcePtr createResource(string name);
 +  ActionPtr createAction(double _cost, bool _failed);
 +  virtual double shareResources(double now);
 +  virtual double shareResourcesLazy(double now);
 +  virtual double shareResourcesFull(double now);
 +  double shareResourcesMaxMin(xbt_swag_t running_actions,
 +                                      lmm_system_t sys,
 +                                      void (*solve) (lmm_system_t));
 +  virtual void updateActionsState(double now, double delta);
 +  virtual void updateActionsStateLazy(double now, double delta);
 +  virtual void updateActionsStateFull(double now, double delta);
 +
 +  string getName() {return m_name;};
 +
 +  void addTurnedOnCallback(ResourceCallback rc);
 +  void notifyResourceTurnedOn(ResourcePtr r);
 +
 +  void addTurnedOffCallback(ResourceCallback rc);  
 +  void notifyResourceTurnedOff(ResourcePtr r);
 +
 +  void addActionCancelCallback(ActionCallback ac);
 +  void notifyActionCancel(ActionPtr a);
 +  void addActionResumeCallback(ActionCallback ac);
 +  void notifyActionResume(ActionPtr a);
 +  void addActionSuspendCallback(ActionCallback ac);  
 +  void notifyActionSuspend(ActionPtr a);
 +
 +  lmm_system_t p_maxminSystem;
 +  e_UM_t p_updateMechanism;
 +  xbt_swag_t p_modifiedSet;
 +  xbt_heap_t p_actionHeap;
 +  int m_selectiveUpdate;
 +
 +  xbt_swag_t p_readyActionSet; /**< Actions in state SURF_ACTION_READY */
 +  xbt_swag_t p_runningActionSet; /**< Actions in state SURF_ACTION_RUNNING */
 +  xbt_swag_t p_failedActionSet; /**< Actions in state SURF_ACTION_FAILED */
 +  xbt_swag_t p_doneActionSet; /**< Actions in state SURF_ACTION_DONE */
 +  string m_name;
 +
 +protected:
 +  std::vector<ActionPtr> m_failedActions, m_runningActions;
 +
 +private:
 +  ResourceCallback m_resOnCB, m_resOffCB;
 +  ActionCallback m_actCancelCB, m_actSuspendCB, m_actResumeCB;
 +};
 +
 +/************
 + * Resource *
 + ************/
 +
 +/**
 + * Resource which have a metric handled by a maxmin system
 + */
 +typedef struct {
 +  double scale;
 +  double peak;
 +  tmgr_trace_event_t event;
 +} s_surf_metric_t;
 +
 +class Resource {
 +public:
 +  Resource();
 +  Resource(ModelPtr model, const char *name, xbt_dict_t properties);
 +  virtual ~Resource() {};
 +
 +  virtual void updateState(tmgr_trace_event_t event_type, double value, double date)=0;
 +
 +  //private
 +  virtual bool isUsed()=0;
 +  //FIXME:updateActionState();
 +  //FIXME:updateResourceState();
 +  //FIXME:finilize();
 +
 +  bool isOn();
 +  void turnOn();
 +  void turnOff();
 +  void setName(string name);
 +  const char *getName();
 +  virtual xbt_dict_t getProperties();
 +
 +  ModelPtr getModel() {return p_model;};
 +  virtual e_surf_resource_state_t getState();
++  virtual void setState(e_surf_resource_state_t state);
 +  void printModel() { std::cout << p_model->getName() << "<<plop"<<std::endl;};
 +  void *p_resource;
 +  const char *m_name;
 +  xbt_dict_t m_properties;
 +  ModelPtr p_model;
 +  e_surf_resource_state_t p_stateCurrent;
 +
 +protected:
 +
 +private:
 +  bool m_running;  
 +};
 +
 +class ResourceLmm: virtual public Resource {
 +public:
 +  ResourceLmm() {};
 +  ResourceLmm(surf_model_t model, const char *name, xbt_dict_t props,
 +                           lmm_system_t system,
 +                           double constraint_value,
 +                           tmgr_history_t history,
 +                           e_surf_resource_state_t state_init,
 +                           tmgr_trace_t state_trace,
 +                           double metric_peak,
 +                           tmgr_trace_t metric_trace);
 +  lmm_constraint_t p_constraint;
 +  tmgr_trace_event_t p_stateEvent;
 +  s_surf_metric_t p_power;
 +};
 +
 +/**********
 + * Action *
 + **********/
 +
 +class Action {
 +public:
 +  Action();
 +  Action(ModelPtr model, double cost, bool failed);
 +  virtual ~Action();
 +  
 +  s_xbt_swag_hookup_t p_stateHookup;
 +
 +  e_surf_action_state_t getState(); /**< get the state*/
 +  virtual void setState(e_surf_action_state_t state); /**< Change state*/
 +  double getStartTime(); /**< Return the start time of an action */
 +  double getFinishTime(); /**< Return the finish time of an action */
 +  void setData(void* data);
 +
 +  void ref();
 +  virtual int unref();     /**< Specify that we don't use that action anymore. Returns true if the action was destroyed and false if someone still has references on it. */
 +  virtual void cancel();     /**< Cancel a running action */
 +  virtual void recycle();     /**< Recycle an action */
 +  
 +  virtual void suspend()=0;     /**< Suspend an action */
 +  virtual void resume()=0;     /**< Resume a suspended action */
 +  virtual bool isSuspended()=0;     /**< Return whether an action is suspended */
 +  virtual void setMaxDuration(double duration)=0;     /**< Set the max duration of an action*/
 +  virtual void setPriority(double priority)=0;     /**< Set the priority of an action */
 +#ifdef HAVE_TRACING
 +  void setCategory(const char *category); /**< Set the category of an action */
 +#endif
 +  virtual double getRemains();     /**< Get the remains of an action */
 +#ifdef HAVE_LATENCY_BOUND_TRACKING
 +  int getLatencyLimited();     /**< Return 1 if action is limited by latency, 0 otherwise */
 +#endif
 +
 +  xbt_swag_t p_stateSet;
 +
 +  double m_priority; /**< priority (1.0 by default) */
++  double m_bound;              /**< the capping of the CPU use  */
 +  bool m_failed;
 +  double m_start; /**< start time  */
 +  double m_finish; /**< finish time : this is modified during the run and fluctuates until the task is completed */
 +  double m_remains; /**< How much of that cost remains to be done in the currently running task */
 +  #ifdef HAVE_LATENCY_BOUND_TRACKING
 +  int m_latencyLimited;               /**< Set to 1 if is limited by latency, 0 otherwise */
 +  #endif
 +  double m_maxDuration; /*< max_duration (may fluctuate until the task is completed) */  
 +  char *p_category;               /**< tracing category for categorized resource utilization monitoring */  
 +  int    m_cost;
 +  void *p_data; /**< for your convenience */
 +protected:
 +  ModelPtr p_model;  
 +  int    m_refcount;
 +#ifdef HAVE_TRACING
 +#endif
 +  e_UM_t p_updateMechanism;
 +
 +private:
 +  int resourceUsed(void *resource_id);
 +  /* Share the resources to the actions and return in how much time
 +     the next action may terminate */
 +  double shareResources(double now);
 +  /* Update the actions' state */
 +  void updateActionsState(double now, double delta);
 +  void updateResourceState(void *id, tmgr_trace_event_t event_type,
 +                                 double value, double time);
 +
 +  xbt_swag_t p_modifiedSet;
 +  xbt_heap_t p_actionHeap;
 +  int m_selectiveUpdate;
 +};
 +
 +//FIXME:REMOVE
 +void surf_action_lmm_update_index_heap(void *action, int i);
 +
 +class ActionLmm: virtual public Action {
 +public:
 +  ActionLmm() : m_suspended(false) {
 +      p_actionListHookup.prev = 0;
 +      p_actionListHookup.next = 0;
 +  };
 +  ActionLmm(ModelPtr model, double cost, bool failed) : m_suspended(false) {
 +      p_actionListHookup.prev = 0;
 +      p_actionListHookup.next = 0;
 +  };
 +
 +  virtual void updateRemainingLazy(double now);
 +  void heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat);
 +  void heapRemove(xbt_heap_t heap);
 +  double getRemains();     /**< Get the remains of an action */
 +  void updateIndexHeap(int i);
 +
 +  virtual int unref();
 +  void cancel();
 +  void suspend();
 +  void resume();
 +  bool isSuspended();
 +  void setMaxDuration(double duration);
 +  void setPriority(double priority);
 +  void gapRemove();
 +
 +  lmm_variable_t p_variable;
 +  s_xbt_swag_hookup_t p_actionListHookup;
 +  int m_indexHeap;
 +  double m_lastUpdate;
 +  double m_lastValue;
 +  enum heap_action_type m_hat;
 +  int m_suspended;
 +};
 +
 +#endif /* SURF_MODEL_H_ */
index 8718872,0000000..3085b04
mode 100644,000000..100644
--- /dev/null
@@@ -1,436 -1,0 +1,516 @@@
-     surf_mins = xbt_new(double, xbt_dynar_length(model_list));
 +#include "surf.hpp"
 +#include "workstation.hpp"
++#include "vm_workstation.hpp"
 +#include "network.hpp"
 +#include "surf_routing_cluster.hpp"
 +#include "instr/instr_private.h"
 +
 +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_kernel);
 +
 +/*********
 + * TOOLS *
 + *********/
 +extern double NOW;
 +
 +static CpuPtr get_casted_cpu(surf_resource_t resource){
 +  return dynamic_cast<CpuPtr>(static_cast<ResourcePtr>(surf_cpu_resource_priv(resource)));
 +}
 +
 +static WorkstationCLM03Ptr get_casted_workstation(surf_resource_t resource){
 +  return dynamic_cast<WorkstationCLM03Ptr>(static_cast<ResourcePtr>(surf_workstation_resource_priv(resource)));
 +}
 +
++static WorkstationVM2013Ptr get_casted_vm_workstation(surf_resource_t resource){
++  return dynamic_cast<WorkstationVM2013Ptr>(static_cast<ResourcePtr>(surf_workstation_resource_priv(resource)));
++}
++
 +char *surf_routing_edge_name(sg_routing_edge_t edge){
 +  return edge->p_name;
 +}
 +
 +#ifdef CONTEXT_THREADS
 +static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */
 +#endif
 +
 +static double *surf_mins = NULL; /* return value of share_resources for each model */
 +static int surf_min_index;       /* current index in surf_mins */
 +static double surf_min;               /* duration determined by surf_solve */
 +
 +void surf_presolve(void)
 +{
 +  double next_event_date = -1.0;
 +  tmgr_trace_event_t event = NULL;
 +  double value = -1.0;
 +  ResourcePtr resource = NULL;
 +  ModelPtr model = NULL;
 +  unsigned int iter;
 +
 +  XBT_DEBUG
 +      ("First Run! Let's \"purge\" events and put models in the right state");
 +  while ((next_event_date = tmgr_history_next_date(history)) != -1.0) {
 +    if (next_event_date > NOW)
 +      break;
 +    while ((event =
 +            tmgr_history_get_next_event_leq(history, next_event_date,
 +                                            &value,
 +                                            (void **) &resource))) {
 +      if (value >= 0){
 +        resource->updateState(event, value, NOW);
 +      }
 +    }
 +  }
 +  xbt_dynar_foreach(model_list, iter, model)
 +      model->updateActionsState(NOW, 0.0);
 +}
 +
 +static void surf_share_resources(surf_model_t model)
 +{
 +  double next_action_end = -1.0;
 +  int i = __sync_fetch_and_add(&surf_min_index, 1);
 +  if (strcmp(model->m_name.c_str(), "network NS3")) {
 +    XBT_DEBUG("Running for Resource [%s]", model->m_name.c_str());
 +    next_action_end = model->shareResources(NOW);
 +    XBT_DEBUG("Resource [%s] : next action end = %f",
 +        model->m_name.c_str(), next_action_end);
 +  }
 +  surf_mins[i] = next_action_end;
 +}
 +
 +static void surf_update_actions_state(surf_model_t model)
 +{
 +  model->updateActionsState(NOW, surf_min);
 +}
 +
 +double surf_solve(double max_date)
 +{
 +  surf_min = -1.0; /* duration */
 +  double next_event_date = -1.0;
 +  double model_next_action_end = -1.0;
 +  double value = -1.0;
 +  ResourcePtr resource = NULL;
 +  ModelPtr model = NULL;
 +  tmgr_trace_event_t event = NULL;
 +  unsigned int iter;
 +
 +  if(!host_that_restart)
 +    host_that_restart = xbt_dynar_new(sizeof(char*), NULL);
 +
 +  if (max_date != -1.0 && max_date != NOW) {
 +    surf_min = max_date - NOW;
 +  }
 +
 +  XBT_DEBUG("Looking for next action end for all models except NS3");
 +
 +  if (surf_mins == NULL) {
-   xbt_dynar_foreach(model_list, iter, model) {
++    surf_mins = xbt_new(double, xbt_dynar_length(model_list_invoke));
 +  }
 +  surf_min_index = 0;
 +
 +  /* sequential version */
-   for (i = 0; i < xbt_dynar_length(model_list); i++) {
++  xbt_dynar_foreach(model_list_invoke, iter, model) {
 +    surf_share_resources(static_cast<ModelPtr>(model));
 +  }
 +
 +  unsigned i;
++  for (i = 0; i < xbt_dynar_length(model_list_invoke); i++) {
 +    if ((surf_min < 0.0 || surf_mins[i] < surf_min)
 +        && surf_mins[i] >= 0.0) {
 +      surf_min = surf_mins[i];
 +    }
 +  }
 +
 +  XBT_DEBUG("Min for resources (remember that NS3 don't update that value) : %f", surf_min);
 +
 +  XBT_DEBUG("Looking for next trace event");
 +
 +  do {
 +    XBT_DEBUG("Next TRACE event : %f", next_event_date);
 +
 +    next_event_date = tmgr_history_next_date(history);
 +
 +    if(!strcmp(surf_network_model->m_name.c_str(), "network NS3")){//FIXME: add surf_network_model->m_name &&
 +      if(next_event_date!=-1.0 && surf_min!=-1.0) {
 +        surf_min = MIN(next_event_date - NOW, surf_min);
 +      } else{
 +        surf_min = MAX(next_event_date - NOW, surf_min);
 +      }
 +
 +      XBT_DEBUG("Run for network at most %f", surf_min);
 +      // run until min or next flow
 +      model_next_action_end = surf_network_model->shareResources(surf_min);
 +
 +      XBT_DEBUG("Min for network : %f", model_next_action_end);
 +      if(model_next_action_end>=0.0)
 +        surf_min = model_next_action_end;
 +    }
 +
 +    if (next_event_date < 0.0) {
 +      XBT_DEBUG("no next TRACE event. Stop searching for it");
 +      break;
 +    }
 +
 +    if ((surf_min == -1.0) || (next_event_date > NOW + surf_min)) break;
 +
 +    XBT_DEBUG("Updating models (min = %g, NOW = %g, next_event_date = %g)", surf_min, NOW, next_event_date);
 +    while ((event =
 +            tmgr_history_get_next_event_leq(history, next_event_date,
 +                                            &value,
 +                                            (void **) &resource))) {
 +      if (resource->isUsed() || xbt_dict_get_or_null(watched_hosts_lib, resource->m_name)) {
 +        surf_min = next_event_date - NOW;
 +        XBT_DEBUG
 +            ("This event will modify model state. Next event set to %f",
 +             surf_min);
 +      }
 +      /* update state of model_obj according to new value. Does not touch lmm.
 +         It will be modified if needed when updating actions */
 +      XBT_DEBUG("Calling update_resource_state for resource %s with min %lf",
 +             resource->m_name, surf_min);
 +      resource->updateState(event, value, next_event_date);
 +    }
 +  } while (1);
 +
 +  /* FIXME: Moved this test to here to avoid stopping simulation if there are actions running on cpus and all cpus are with availability = 0.
 +   * This may cause an infinite loop if one cpu has a trace with periodicity = 0 and the other a trace with periodicity > 0.
 +   * The options are: all traces with same periodicity(0 or >0) or we need to change the way how the events are managed */
 +  if (surf_min == -1.0) {
 +  XBT_DEBUG("No next event at all. Bail out now.");
 +    return -1.0;
 +  }
 +
 +  XBT_DEBUG("Duration set to %f", surf_min);
 +
 +  NOW = NOW + surf_min;
++  /* FIXME: model_list or model_list_invoke? revisit here later */
 +  /* sequential version */
 +  xbt_dynar_foreach(model_list, iter, model) {
 +    surf_update_actions_state(model);
 +  }
 +
 +#ifdef HAVE_TRACING
 +  TRACE_paje_dump_buffer (0);
 +#endif
 +
 +  return surf_min;
 +}
 +
 +XBT_INLINE double surf_get_clock(void)
 +{
 +  return NOW;
 +}
 +
 +void routing_get_route_and_latency(sg_routing_edge_t src, sg_routing_edge_t dst,
 +                              xbt_dynar_t * route, double *latency){
 +  routing_platf->getRouteAndLatency(src, dst, route, latency);
 +}
 +
 +/*********
 + * MODEL *
 + *********/
 +
++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. */
++  ResourcePtr ws = static_cast<ResourcePtr>(xbt_lib_get_level((xbt_dictelm_t) host, level));
++  return ws->p_model;
++}
++
 +void *surf_as_cluster_get_backbone(AS_t as){
 +  return static_cast<AsClusterPtr>(as)->p_backbone;
 +}
 +
 +void surf_as_cluster_set_backbone(AS_t as, void* backbone){
 +  static_cast<AsClusterPtr>(as)->p_backbone = dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(backbone));
 +}
 +
 +const char *surf_model_name(surf_model_t model){
 +  return model->m_name.c_str();
 +}
 +
 +xbt_swag_t surf_model_done_action_set(surf_model_t model){
 +  return model->p_doneActionSet;
 +}
 +
 +xbt_swag_t surf_model_failed_action_set(surf_model_t model){
 +  return model->p_failedActionSet;
 +}
 +
 +xbt_swag_t surf_model_ready_action_set(surf_model_t model){
 +  return model->p_readyActionSet;
 +}
 +
 +xbt_swag_t surf_model_running_action_set(surf_model_t model){
 +  return model->p_runningActionSet;
 +}
 +
 +surf_action_t surf_workstation_model_execute_parallel_task(surf_workstation_model_t model,
 +                                                  int workstation_nb,
 +                                            void **workstation_list,
 +                                            double *computation_amount,
 +                                            double *communication_amount,
 +                                            double rate){
 +  return static_cast<ActionPtr>(model->executeParallelTask(workstation_nb, workstation_list, computation_amount, communication_amount, rate));
 +}
 +
 +surf_action_t surf_workstation_model_communicate(surf_workstation_model_t model, surf_resource_t src, surf_resource_t dst, double size, double rate){
 +  return model->communicate(get_casted_workstation(src), get_casted_workstation(dst), size, rate);
 +}
 +
 +xbt_dynar_t surf_workstation_model_get_route(surf_workstation_model_t model,
 +                                                   surf_resource_t src, surf_resource_t dst){
 +  return model->getRoute(get_casted_workstation(src), get_casted_workstation(dst));
 +}
 +
++void surf_vm_workstation_model_create(const char *name, surf_resource_t ind_phys_host){
++  surf_vm_workstation_model->createResource(name, ind_phys_host);
++}
++
 +surf_action_t surf_network_model_communicate(surf_network_model_t model, sg_routing_edge_t src, sg_routing_edge_t dst, double size, double rate){
 +  return model->communicate(src, dst, size, rate);
 +}
 +
 +const char *surf_resource_name(surf_cpp_resource_t resource){
 +  return resource->m_name;
 +}
 +
 +xbt_dict_t surf_resource_get_properties(surf_cpp_resource_t resource){
 +  return resource->getProperties();
 +}
 +
 +e_surf_resource_state_t surf_resource_get_state(surf_cpp_resource_t resource){
 +  return resource->getState();
 +}
 +
++void surf_resource_set_state(surf_cpp_resource_t resource, e_surf_resource_state_t state){
++  resource->setState(state);
++}
++
 +surf_action_t surf_workstation_sleep(surf_resource_t resource, double duration){
 +  return get_casted_workstation(resource)->sleep(duration);
 +}
 +
 +double surf_workstation_get_speed(surf_resource_t resource, double load){
 +  return get_casted_workstation(resource)->getSpeed(load);
 +}
 +
 +double surf_workstation_get_available_speed(surf_resource_t resource){
 +  return get_casted_workstation(resource)->getAvailableSpeed();
 +}
 +
 +int surf_workstation_get_core(surf_resource_t resource){
 +  return get_casted_workstation(resource)->getCore();
 +}
 +
 +surf_action_t surf_workstation_execute(surf_resource_t resource, double size){
 +  return get_casted_workstation(resource)->execute(size);
 +}
 +
 +double surf_workstation_get_current_power_peak(surf_resource_t resource){
 +  return get_casted_workstation(resource)->getCurrentPowerPeak();
 +}
 +
 +double surf_workstation_get_power_peak_at(surf_resource_t resource, int pstate_index){
 +  return get_casted_workstation(resource)->getPowerPeakAt(pstate_index);
 +}
 +
 +int surf_workstation_get_nb_pstates(surf_resource_t resource){
 +  return get_casted_workstation(resource)->getNbPstates();
 +}
 +
 +void surf_workstation_set_power_peak_at(surf_resource_t resource, int pstate_index){
 +  return get_casted_workstation(resource)->setPowerPeakAt(pstate_index);
 +}
 +
 +double surf_workstation_get_consumed_energy(surf_resource_t resource){
 +  return get_casted_workstation(resource)->getConsumedEnergy();
 +}
 +
 +xbt_dict_t surf_workstation_get_storage_list(surf_resource_t workstation){
 +  return get_casted_workstation(workstation)->getStorageList();
 +}
++
 +surf_action_t surf_workstation_open(surf_resource_t workstation, const char* mount, const char* path){
 +  return get_casted_workstation(workstation)->open(mount, path);
 +}
 +
 +surf_action_t surf_workstation_close(surf_resource_t workstation, surf_file_t fd){
 +  return get_casted_workstation(workstation)->close(fd);
 +}
 +
 +int surf_workstation_unlink(surf_resource_t workstation, surf_file_t fd){
 +  return get_casted_workstation(workstation)->unlink(fd);
 +}
 +
 +surf_action_t surf_workstation_ls(surf_resource_t workstation, const char* mount, const char *path){
 +  return get_casted_workstation(workstation)->ls(mount, path);
 +}
 +
 +size_t surf_workstation_get_size(surf_resource_t workstation, surf_file_t fd){
 +  return get_casted_workstation(workstation)->getSize(fd);
 +}
 +
 +surf_action_t surf_workstation_read(surf_resource_t resource, surf_file_t fd, sg_storage_size_t size){
 +  return get_casted_workstation(resource)->read(fd, size);
 +}
 +
 +surf_action_t surf_workstation_write(surf_resource_t resource, surf_file_t fd, sg_storage_size_t size){
 +  return get_casted_workstation(resource)->write(fd, size);
 +}
 +
 +xbt_dynar_t surf_workstation_get_info(surf_resource_t resource, surf_file_t fd){
 +  return get_casted_workstation(resource)->getInfo(fd);
 +}
 +
 +sg_storage_size_t surf_workstation_get_free_size(surf_resource_t resource, const char* name){
 +  return get_casted_workstation(resource)->getFreeSize(name);
 +}
++
 +sg_storage_size_t surf_workstation_get_used_size(surf_resource_t resource, const char* name){
 +  return get_casted_workstation(resource)->getUsedSize(name);
 +}
 +
++xbt_dynar_t surf_workstation_get_vms(surf_resource_t resource){
++  return get_casted_workstation(resource)->getVms();
++}
++
++void surf_workstation_get_params(surf_resource_t resource, ws_params_t params){
++  get_casted_workstation(resource)->getParams(params);
++}
++
++void surf_workstation_set_params(surf_resource_t resource, ws_params_t params){
++  get_casted_workstation(resource)->setParams(params);
++}
++
++void surf_vm_workstation_destroy(surf_resource_t resource){
++  delete get_casted_vm_workstation(resource);
++}
++
++void surf_vm_workstation_suspend(surf_resource_t resource){
++  get_casted_vm_workstation(resource)->suspend();
++}
++
++void surf_vm_workstation_resume(surf_resource_t resource){
++  get_casted_vm_workstation(resource)->resume();
++}
++
++void surf_vm_workstation_save(surf_resource_t resource){
++  get_casted_vm_workstation(resource)->save();
++}
++
++void surf_vm_workstation_restore(surf_resource_t resource){
++  get_casted_vm_workstation(resource)->restore();
++}
++
++void surf_vm_workstation_migrate(surf_resource_t resource, surf_resource_t ind_vm_ws_dest){
++  get_casted_vm_workstation(resource)->migrate(ind_vm_ws_dest);
++}
++
++surf_resource_t surf_vm_workstation_get_pm(surf_resource_t resource){
++  return get_casted_vm_workstation(resource)->getPm();
++}
++
++void surf_vm_workstation_set_bound(surf_resource_t resource, double bound){
++  return get_casted_vm_workstation(resource)->setBound(bound);
++}
++
++void surf_vm_workstation_set_affinity(surf_resource_t resource, surf_resource_t cpu, unsigned long mask){
++  return get_casted_vm_workstation(resource)->setAffinity(dynamic_cast<CpuLmmPtr>(get_casted_cpu(cpu)), mask);
++}
++
 +int surf_network_link_is_shared(surf_cpp_resource_t link){
 +  return dynamic_cast<NetworkCm02LinkPtr>(link)->isShared();
 +}
 +
 +double surf_network_link_get_bandwidth(surf_cpp_resource_t link){
 +  return dynamic_cast<NetworkCm02LinkPtr>(link)->getBandwidth();
 +}
 +
 +double surf_network_link_get_latency(surf_cpp_resource_t link){
 +  return dynamic_cast<NetworkCm02LinkPtr>(link)->getLatency();
 +}
 +
 +xbt_dict_t surf_storage_get_content(surf_resource_t resource){
 +  return dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(surf_storage_resource_priv(resource)))->getContent();
 +}
 +
 +sg_storage_size_t surf_storage_get_size(surf_resource_t resource){
 +  return dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(surf_storage_resource_priv(resource)))->getSize();
 +}
 +
 +surf_action_t surf_cpu_execute(surf_resource_t cpu, double size){
 +  return get_casted_cpu(cpu)->execute(size);
 +}
 +
 +surf_action_t surf_cpu_sleep(surf_resource_t cpu, double duration){
 +  return get_casted_cpu(cpu)->sleep(duration);
 +}
 +
 +double surf_action_get_start_time(surf_action_t action){
 +  return action->m_start;
 +}
 +
 +double surf_action_get_finish_time(surf_action_t action){
 +  return action->m_finish;
 +}
 +
 +double surf_action_get_remains(surf_action_t action){
 +  return action->getRemains();
 +}
 +
 +void surf_action_unref(surf_action_t action){
 +  action->unref();
 +}
 +
 +void surf_action_suspend(surf_action_t action){
 +  action->suspend();
 +}
 +
 +void surf_action_resume(surf_action_t action){
 +  action->resume();
 +}
 +
 +void surf_action_cancel(surf_action_t action){
 +  action->cancel();
 +}
 +
 +void surf_action_set_priority(surf_action_t action, double priority){
 +  action->setPriority(priority);
 +}
 +
 +void surf_action_set_category(surf_action_t action, const char *category){
 +  action->setCategory(category);
 +}
 +
 +void *surf_action_get_data(surf_action_t action){
 +  return action->p_data;
 +}
 +
 +void surf_action_set_data(surf_action_t action, void *data){
 +  action->p_data = data;
 +}
 +
 +e_surf_action_state_t surf_action_get_state(surf_action_t action){
 +  return action->getState();
 +}
 +
 +int surf_action_get_cost(surf_action_t action){
 +  return action->m_cost;
 +}
 +
++void surf_cpu_action_set_affinity(surf_action_t action, surf_resource_t cpu, unsigned long mask) {
++  dynamic_cast<CpuActionLmmPtr>(action)->setAffinity( dynamic_cast<CpuLmmPtr>(get_casted_cpu(cpu)), mask);
++}
++
++void surf_cpu_action_set_bound(surf_action_t action, double bound) {
++  dynamic_cast<CpuActionLmmPtr>(action)->setBound(bound);
++}
++
 +surf_file_t surf_storage_action_get_file(surf_action_t action){
 +  return dynamic_cast<StorageActionPtr>(action)->p_file;
 +}
 +
 +xbt_dict_t surf_storage_action_get_ls_dict(surf_action_t action){
 +  return dynamic_cast<StorageActionPtr>(action)->p_lsDict;
 +}
++
++
diff --combined src/surf/workstation.cpp
index 31aef93,0000000..4771d97
mode 100644,000000..100644
--- /dev/null
@@@ -1,321 -1,0 +1,427 @@@
-   xbt_assert(surf_cpu_model, "No CPU model defined yet!");
 +#include "workstation.hpp"
++#include "vm_workstation.hpp"
++#include "cpu_cas01.hpp"
 +#include "simgrid/sg_config.h"
 +
 +extern "C" {
 +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_workstation, surf,
 +                                "Logging specific to the SURF workstation module");
 +}
 +
 +WorkstationModelPtr surf_workstation_model = NULL;
 +
 +//FIXME:Faire hériter ou composer de cup et network
 +
 +/*************
 + * CallBacks *
 + *************/
 +
 +static void workstation_new(sg_platf_host_cbarg_t host){
 +  surf_workstation_model->createResource(host->id);
 +}
 +
 +/*********
 + * Model *
 + *********/
 +
 +void surf_workstation_model_init_current_default(void)
 +{
 +  surf_workstation_model = new WorkstationModel();
 +  xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", "yes");
 +  surf_cpu_model_init_Cas01();
 +  surf_network_model_init_LegrandVelho();
 +
 +  ModelPtr model = static_cast<ModelPtr>(surf_workstation_model);
 +  xbt_dynar_push(model_list, &model);
++  xbt_dynar_push(model_list_invoke, &model);
 +  sg_platf_host_add_cb(workstation_new);
 +}
 +
 +void surf_workstation_model_init_compound()
 +{
 +
-   return -1.0;
++  xbt_assert(surf_cpu_model_pm, "No CPU model defined yet!");
 +  xbt_assert(surf_network_model, "No network model defined yet!");
 +  surf_workstation_model = new WorkstationModel();
 +
 +  ModelPtr model = static_cast<ModelPtr>(surf_workstation_model);
 +  xbt_dynar_push(model_list, &model);
++  xbt_dynar_push(model_list_invoke, &model);
 +  sg_platf_host_add_cb(workstation_new);
 +}
 +
 +WorkstationModel::WorkstationModel() : Model("Workstation") {
 +}
 +
 +WorkstationModel::~WorkstationModel() {
 +}
 +
 +void WorkstationModel::parseInit(sg_platf_host_cbarg_t host){
 +  createResource(host->id);
 +}
 +
 +WorkstationCLM03Ptr WorkstationModel::createResource(string name){
 +
 +  WorkstationCLM03Ptr workstation = new WorkstationCLM03(surf_workstation_model, name.c_str(), NULL,
 +                (xbt_dynar_t)xbt_lib_get_or_null(storage_lib, name.c_str(), ROUTING_STORAGE_HOST_LEVEL),
 +                (RoutingEdgePtr)xbt_lib_get_or_null(host_lib, name.c_str(), ROUTING_HOST_LEVEL),
 +                dynamic_cast<CpuPtr>(static_cast<ResourcePtr>(xbt_lib_get_or_null(host_lib, name.c_str(), SURF_CPU_LEVEL))));
 +  XBT_DEBUG("Create workstation %s with %ld mounted disks", name.c_str(), xbt_dynar_length(workstation->p_storage));
 +  xbt_lib_set(host_lib, name.c_str(), SURF_WKS_LEVEL, static_cast<ResourcePtr>(workstation));
 +  return workstation;
 +}
 +
++/* Each VM has a dummy CPU action on the PM layer. This CPU action works as the
++ * constraint (capacity) of the VM in the PM layer. If the VM does not have any
++ * active task, the dummy CPU action must be deactivated, so that the VM does
++ * not get any CPU share in the PM layer. */
++void WorkstationModel::adjustWeightOfDummyCpuActions()
++{
++  /* 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) {
++    WorkstationCLM03Ptr ws_clm03 = dynamic_cast<WorkstationCLM03Ptr>(
++                                     static_cast<ResourcePtr>(ind_host[SURF_WKS_LEVEL]));
++    CpuCas01LmmPtr cpu_cas01 = dynamic_cast<CpuCas01LmmPtr>(
++                               static_cast<ResourcePtr>(ind_host[SURF_CPU_LEVEL]));
++
++    if (!ws_clm03)
++      continue;
++    /* skip if it is not a virtual machine */
++    if (ws_clm03->p_model != static_cast<ModelPtr>(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 */
++    WorkstationVM2013Ptr ws_vm2013 = dynamic_cast<WorkstationVM2013Ptr>(ws_clm03);
++
++    int is_active = lmm_constraint_used(cpu_cas01->p_model->p_maxminSystem, cpu_cas01->p_constraint);
++    // int is_active_old = constraint_is_active(cpu_cas01);
++
++    // {
++    //   xbt_assert(is_active == is_active_old, "%d %d", is_active, is_active_old);
++    // }
++
++    if (is_active) {
++      /* some tasks exist on this VM */
++      XBT_DEBUG("set the weight of the dummy CPU action on PM to 1");
++
++      /* FIXME: we shoud use lmm_update_variable_weight() ? */
++      /* FIXME: If we assgign 1.05 and 0.05, the system makes apparently wrong values. */
++      surf_action_set_priority(ws_vm2013->p_action, 1);
++
++    } else {
++      /* no task exits on this VM */
++      XBT_DEBUG("set the weight of the dummy CPU action on PM to 0");
++
++      surf_action_set_priority(ws_vm2013->p_action, 0);
++    }
++  }
++}
++
 +double WorkstationModel::shareResources(double now){
++  adjustWeightOfDummyCpuActions();
++
++  double min_by_cpu = surf_cpu_model_pm->shareResources(now);
++  double min_by_net = surf_network_model->shareResources(now);
++
++  XBT_DEBUG("model %p, %s min_by_cpu %f, %s min_by_net %f",
++      this, surf_cpu_model_pm->m_name.c_str(), min_by_cpu, surf_network_model->m_name.c_str(), min_by_net);
++
++  if (min_by_cpu >= 0.0 && min_by_net >= 0.0)
++    return min(min_by_cpu, min_by_net);
++  else if (min_by_cpu >= 0.0)
++    return min_by_cpu;
++  else if (min_by_net >= 0.0)
++    return min_by_net;
++  else
++    return min_by_cpu;  /* probably min_by_cpu == min_by_net == -1 */
 +}
 +
 +void WorkstationModel::updateActionsState(double now, double delta){
 +  return;
 +}
 +
 +ActionPtr WorkstationModel::executeParallelTask(int workstation_nb,
 +                                        void **workstation_list,
 +                                        double *computation_amount,
 +                                        double *communication_amount,
 +                                        double rate){
 +#define cost_or_zero(array,pos) ((array)?(array)[pos]:0.0)
 +  if ((workstation_nb == 1)
 +      && (cost_or_zero(communication_amount, 0) == 0.0))
 +    return ((WorkstationCLM03Ptr)workstation_list[0])->execute(computation_amount[0]);
 +  else if ((workstation_nb == 1)
 +           && (cost_or_zero(computation_amount, 0) == 0.0))
 +    return communicate((WorkstationCLM03Ptr)workstation_list[0], (WorkstationCLM03Ptr)workstation_list[0],communication_amount[0], rate);
 +  else if ((workstation_nb == 2)
 +             && (cost_or_zero(computation_amount, 0) == 0.0)
 +             && (cost_or_zero(computation_amount, 1) == 0.0)) {
 +    int i,nb = 0;
 +    double value = 0.0;
 +
 +    for (i = 0; i < workstation_nb * workstation_nb; i++) {
 +      if (cost_or_zero(communication_amount, i) > 0.0) {
 +        nb++;
 +        value = cost_or_zero(communication_amount, i);
 +      }
 +    }
 +    if (nb == 1)
 +      return communicate((WorkstationCLM03Ptr)workstation_list[0], (WorkstationCLM03Ptr)workstation_list[1],value, rate);
 +  }
 +#undef cost_or_zero
 +
 +  THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
 +  return NULL;
 +}
 +
 +/* returns an array of network_link_CM02_t */
 +xbt_dynar_t WorkstationModel::getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst)
 +{
 +  XBT_DEBUG("ws_get_route");
 +  return surf_network_model->getRoute(src->p_netElm, dst->p_netElm);
 +}
 +
 +ActionPtr WorkstationModel::communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst, double size, double rate){
 +  return surf_network_model->communicate(src->p_netElm, dst->p_netElm, size, rate);
 +}
 +
 +
 +
 +/************
 + * Resource *
 + ************/
 +WorkstationCLM03::WorkstationCLM03(WorkstationModelPtr model, const char* name, xbt_dict_t properties, xbt_dynar_t storage, RoutingEdgePtr netElm, CpuPtr cpu)
 +  : Resource(model, name, properties), p_storage(storage), p_netElm(netElm), p_cpu(cpu) {}
 +
 +bool WorkstationCLM03::isUsed(){
 +  THROW_IMPOSSIBLE;             /* This model does not implement parallel tasks */
 +  return -1;
 +}
 +
 +void WorkstationCLM03::updateState(tmgr_trace_event_t event_type, double value, double date){
 +  THROW_IMPOSSIBLE;             /* This model does not implement parallel tasks */
 +}
 +
 +ActionPtr WorkstationCLM03::execute(double size) {
 +  return p_cpu->execute(size);
 +}
 +
 +ActionPtr WorkstationCLM03::sleep(double duration) {
 +  return p_cpu->sleep(duration);
 +}
 +
 +e_surf_resource_state_t WorkstationCLM03::getState() {
 +  return p_cpu->getState();
 +}
 +
 +int WorkstationCLM03::getCore(){
 +  return p_cpu->getCore();
 +}
 +
 +double WorkstationCLM03::getSpeed(double load){
 +  return p_cpu->getSpeed(load);
 +}
 +
 +double WorkstationCLM03::getAvailableSpeed(){
 +  return p_cpu->getAvailableSpeed();
 +}
 +
 +double WorkstationCLM03::getCurrentPowerPeak()
 +{
 +  return p_cpu->getCurrentPowerPeak();
 +}
 +
 +double WorkstationCLM03::getPowerPeakAt(int pstate_index)
 +{
 +  return p_cpu->getPowerPeakAt(pstate_index);
 +}
 +
 +int WorkstationCLM03::getNbPstates()
 +{
 +  return p_cpu->getNbPstates();
 +}
 +
 +void WorkstationCLM03::setPowerPeakAt(int pstate_index)
 +{
 +      p_cpu->setPowerPeakAt(pstate_index);
 +}
 +
 +double WorkstationCLM03::getConsumedEnergy()
 +{
 +  return p_cpu->getConsumedEnergy();
 +}
 +
 +
 +xbt_dict_t WorkstationCLM03::getProperties()
 +{
 +  return p_cpu->m_properties;
 +}
 +
 +
 +StoragePtr WorkstationCLM03::findStorageOnMountList(const char* mount)
 +{
 +  StoragePtr st = NULL;
 +  s_mount_t mnt;
 +  unsigned int cursor;
 +
 +  XBT_DEBUG("Search for storage name '%s' on '%s'", mount, m_name);
 +  xbt_dynar_foreach(p_storage,cursor,mnt)
 +  {
 +    XBT_DEBUG("See '%s'",mnt.name);
 +    if(!strcmp(mount,mnt.name)){
 +      st = dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(mnt.storage));
 +      break;
 +    }
 +  }
 +  if(!st) xbt_die("Can't find mount '%s' for '%s'", mount, m_name);
 +  return st;
 +}
 +
 +xbt_dict_t WorkstationCLM03::getStorageList()
 +{
 +  s_mount_t mnt;
 +  unsigned int i;
 +  xbt_dict_t storage_list = xbt_dict_new_homogeneous(NULL);
 +  char *storage_name = NULL;
 +
 +  xbt_dynar_foreach(p_storage,i,mnt){
 +    storage_name = (char *)dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(mnt.storage))->m_name;
 +    xbt_dict_set(storage_list,mnt.name,storage_name,NULL);
 +  }
 +  return storage_list;
 +}
 +
 +ActionPtr WorkstationCLM03::open(const char* mount, const char* path) {
 +  StoragePtr st = findStorageOnMountList(mount);
 +  XBT_DEBUG("OPEN on disk '%s'", st->m_name);
 +  return st->open(mount, path);
 +}
 +
 +ActionPtr WorkstationCLM03::close(surf_file_t fd) {
 +  StoragePtr st = findStorageOnMountList(fd->mount);
 +  XBT_DEBUG("CLOSE on disk '%s'",st->m_name);
 +  return st->close(fd);
 +}
 +
 +ActionPtr WorkstationCLM03::read(surf_file_t fd, sg_storage_size_t size) {
 +  StoragePtr st = findStorageOnMountList(fd->mount);
 +  XBT_DEBUG("READ on disk '%s'",st->m_name);
 +  return st->read(fd, size);
 +}
 +
 +ActionPtr WorkstationCLM03::write(surf_file_t fd, sg_storage_size_t size) {
 +  StoragePtr st = findStorageOnMountList(fd->mount);
 +  XBT_DEBUG("WRITE on disk '%s'",st->m_name);
 +  return st->write(fd, size);
 +}
 +
 +int WorkstationCLM03::unlink(surf_file_t fd) {
 +  if (!fd){
 +    XBT_WARN("No such file descriptor. Impossible to unlink");
 +    return 0;
 +  } else {
 +//    XBT_INFO("%s %zu", fd->storage, fd->size);
 +    StoragePtr st = findStorageOnMountList(fd->mount);
 +    /* Check if the file is on this storage */
 +    if (!xbt_dict_get_or_null(st->p_content, fd->name)){
 +      XBT_WARN("File %s is not on disk %s. Impossible to unlink", fd->name,
 +          st->m_name);
 +      return 0;
 +    } else {
 +      XBT_DEBUG("UNLINK on disk '%s'",st->m_name);
 +      st->m_usedSize -= fd->size;
 +
 +      // Remove the file from storage
 +      xbt_dict_remove(st->p_content, fd->name);
 +
 +      free(fd->name);
 +      free(fd->mount);
 +      xbt_free(fd);
 +      return 1;
 +    }
 +  }
 +}
 +
 +ActionPtr WorkstationCLM03::ls(const char* mount, const char *path){
 +  XBT_DEBUG("LS on mount '%s' and file '%s'", mount, path);
 +  StoragePtr st = findStorageOnMountList(mount);
 +  return st->ls(path);
 +}
 +
 +sg_storage_size_t WorkstationCLM03::getSize(surf_file_t fd){
 +  return fd->size;
 +}
 +
 +xbt_dynar_t WorkstationCLM03::getInfo( surf_file_t fd)
 +{
 +  StoragePtr st = findStorageOnMountList(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 *, (void *)st->m_name);
 +  xbt_dynar_push_as(info, void *, st->p_typeId);
 +  xbt_dynar_push_as(info, void *, st->p_contentType);
 +
 +  return info;
 +}
 +
 +sg_storage_size_t WorkstationCLM03::getFreeSize(const char* name)
 +{
 +  StoragePtr st = findStorageOnMountList(name);
 +  return st->m_size - st->m_usedSize;
 +}
 +
 +sg_storage_size_t WorkstationCLM03::getUsedSize(const char* name)
 +{
 +  StoragePtr st = findStorageOnMountList(name);
 +  return st->m_usedSize;
 +}
 +
 +e_surf_resource_state_t WorkstationCLM03Lmm::getState() {
 +  return WorkstationCLM03::getState();
 +}
++
++xbt_dynar_t WorkstationCLM03::getVms()
++{
++  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) {
++    WorkstationCLM03Ptr ws_clm03 = dynamic_cast<WorkstationCLM03Ptr>(static_cast<ResourcePtr>(ind_host[SURF_WKS_LEVEL]));
++    if (!ws_clm03)
++      continue;
++    /* skip if it is not a virtual machine */
++    if (ws_clm03->p_model != static_cast<ModelPtr>(surf_vm_workstation_model))
++      continue;
++
++    /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
++    WorkstationVM2013Ptr ws_vm2013 = dynamic_cast<WorkstationVM2013Ptr>(ws_clm03);
++    if (this == ws_vm2013-> p_subWs)
++      xbt_dynar_push(dyn, &ws_vm2013->p_subWs);
++  }
++
++  return dyn;
++}
++
++void WorkstationCLM03::getParams(ws_params_t params)
++{
++  memcpy(params, &p_params, sizeof(s_ws_params_t));
++}
++
++void WorkstationCLM03::setParams(ws_params_t params)
++{
++  /* may check something here. */
++  memcpy(&p_params, params, sizeof(s_ws_params_t));
++}
 +/**********
 + * Action *
 + **********/
diff --combined src/surf/workstation.hpp
index 08940e0,0000000..d3c18ad
mode 100644,000000..100644
--- /dev/null
@@@ -1,122 -1,0 +1,131 @@@
- class WorkstationCLM03Lmm : public WorkstationCLM03, public ResourceLmm {
 +#include "surf.hpp"
 +#include "storage.hpp"
 +#include "cpu.hpp"
 +#include "network.hpp"
 +
 +#ifndef WORKSTATION_HPP_
 +#define WORKSTATION_HPP_
 +
 +/***********
 + * Classes *
 + ***********/
 +
 +class WorkstationModel;
 +typedef WorkstationModel *WorkstationModelPtr;
 +
 +class WorkstationCLM03;
 +typedef WorkstationCLM03 *WorkstationCLM03Ptr;
 +
 +class WorkstationCLM03Lmm;
 +typedef WorkstationCLM03Lmm *WorkstationCLM03LmmPtr;
 +
 +class WorkstationAction;
 +typedef WorkstationAction *WorkstationActionPtr;
 +
 +/*FIXME:class WorkstationActionLmm;
 +typedef WorkstationActionLmm *WorkstationActionLmmPtr;*/
 +
 +/*********
 + * Tools *
 + *********/
 +extern WorkstationModelPtr surf_workstation_model;
 +
 +/*********
 + * Model *
 + *********/
 +class WorkstationModel : public Model {
 +public:
 +  WorkstationModel(string name): Model(name) {};
 +  WorkstationModel();
 +  ~WorkstationModel();
 +  virtual void parseInit(sg_platf_host_cbarg_t host);
 +  WorkstationCLM03Ptr createResource(string name);
 +  double shareResources(double now);
++  virtual void adjustWeightOfDummyCpuActions();
++
 +  void updateActionsState(double now, double delta);
 +
 +  virtual ActionPtr executeParallelTask(int workstation_nb,
 +                                        void **workstation_list,
 +                                        double *computation_amount,
 +                                        double *communication_amount,
 +                                        double rate);
 + virtual xbt_dynar_t getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst);
 + virtual ActionPtr communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst, double size, double rate);
 +};
 +
 +/************
 + * Resource *
 + ************/
 +
 +class WorkstationCLM03 : virtual public Resource {
 +public:
 +  WorkstationCLM03(WorkstationModelPtr model, const char* name, xbt_dict_t properties, xbt_dynar_t storage, RoutingEdgePtr netElm, CpuPtr cpu);
 +
 +  void updateState(tmgr_trace_event_t event_type, double value, double date);
 +
 +  virtual ActionPtr execute(double size);
 +  virtual ActionPtr sleep(double duration);
 +  e_surf_resource_state_t getState();
 +
 +  virtual int getCore();
 +  virtual double getSpeed(double load);
 +  virtual double getAvailableSpeed();
 +  virtual double getCurrentPowerPeak();
 +  virtual double getPowerPeakAt(int pstate_index);
 +  virtual int getNbPstates();
 +  virtual void setPowerPeakAt(int pstate_index);
 +  virtual double getConsumedEnergy();
 +
 +  xbt_dict_t getProperties();
 +
 +  StoragePtr findStorageOnMountList(const char* storage);
 +  xbt_dict_t getStorageList();
 +  ActionPtr open(const char* mount, const char* path);
 +  ActionPtr close(surf_file_t fd);
 +  int unlink(surf_file_t fd);
 +  ActionPtr ls(const char* mount, const char *path);
 +  sg_storage_size_t getSize(surf_file_t fd);
 +  ActionPtr read(surf_file_t fd, sg_storage_size_t size);
 +  ActionPtr write(surf_file_t fd, sg_storage_size_t size);
 +  xbt_dynar_t getInfo( surf_file_t fd);
 +  sg_storage_size_t getFreeSize(const char* name);
 +  sg_storage_size_t getUsedSize(const char* name);
 +
 +  bool isUsed();
 +  //bool isShared();
 +  xbt_dynar_t p_storage;
 +  RoutingEdgePtr p_netElm;
 +  CpuPtr p_cpu;
 +  NetworkCm02LinkPtr p_network;
++
++  xbt_dynar_t getVms();
++
++  /* common with vm */
++  void getParams(ws_params_t params);
++  void setParams(ws_params_t params);
++  s_ws_params_t p_params;
 +};
 +
++class WorkstationCLM03Lmm : virtual public WorkstationCLM03, public ResourceLmm {
 +public:
 +  WorkstationCLM03Lmm(WorkstationModelPtr model, const char* name, xbt_dict_t props, xbt_dynar_t storage, RoutingEdgePtr netElm, CpuPtr cpu):
 +        WorkstationCLM03(model, name, props, storage, netElm, cpu){};
 +  e_surf_resource_state_t getState();
 +};
 +
 +/**********
 + * Action *
 + **********/
 +class WorkstationAction : virtual public Action {
 +public:
 +  WorkstationAction(ModelPtr model, double cost, bool failed): Action(model, cost, failed) {};
 +};
 +
 +class WorkstationActionLmm : public ActionLmm, public WorkstationAction {
 +public:
 +  WorkstationActionLmm(ModelPtr model, double cost, bool failed): ActionLmm(model, cost, failed), WorkstationAction(model, cost, failed) {};
 +};
 +
 +
 +#endif /* WORKSTATION_HPP_ */
index 507d25e,0000000..0010a53
mode 100644,000000..100644
--- /dev/null
@@@ -1,861 -1,0 +1,863 @@@
-   surf_cpu_model = new CpuL07Model();
 +/* Copyright (c) 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 "workstation_ptask_L07.hpp"
 +#include "cpu.hpp"
 +#include "surf_routing.hpp"
 +
 +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_workstation);
 +
 +static int ptask_host_count = 0;
 +static xbt_dict_t ptask_parallel_task_link_set = NULL;
 +lmm_system_t ptask_maxmin_system = NULL;
 +
 +WorkstationL07Model::WorkstationL07Model() : WorkstationModel("Workstation ptask_L07") {
 +  if (!ptask_maxmin_system)
 +      ptask_maxmin_system = lmm_system_new(1);
 +  surf_workstation_model = NULL;
 +  surf_network_model = new NetworkL07Model();
-   delete surf_cpu_model;
++  surf_cpu_model_pm = new CpuL07Model();
 +  routing_model_create(p_networkModel->createResource("__loopback__",
 +                                                        498000000, NULL,
 +                                                        0.000015, NULL,
 +                                                        SURF_RESOURCE_ON, NULL,
 +                                                        SURF_LINK_FATPIPE, NULL));
 +}
 +
 +WorkstationL07Model::~WorkstationL07Model() {
 +  xbt_dict_free(&ptask_parallel_task_link_set);
 +
-   : Resource(model, name, props), WorkstationCLM03Lmm(model, name, props, NULL, netElm, cpu)
++  delete surf_cpu_model_pm;
 +  delete surf_network_model;
 +  ptask_host_count = 0;
 +
 +  if (ptask_maxmin_system) {
 +    lmm_system_free(ptask_maxmin_system);
 +    ptask_maxmin_system = NULL;
 +  }
 +}
 +
 +double WorkstationL07Model::shareResources(double now)
 +{
 +  void *_action;
 +  WorkstationL07ActionLmmPtr action;
 +
 +  xbt_swag_t running_actions = this->p_runningActionSet;
 +  double min = this->shareResourcesMaxMin(running_actions,
 +                                              ptask_maxmin_system,
 +                                              bottleneck_solve);
 +
 +  xbt_swag_foreach(_action, running_actions) {
 +      action = dynamic_cast<WorkstationL07ActionLmmPtr>(static_cast<ActionPtr>(_action));
 +    if (action->m_latency > 0) {
 +      if (min < 0) {
 +        min = action->m_latency;
 +        XBT_DEBUG("Updating min (value) with %p (start %f): %f", action,
 +               action->m_start, min);
 +      } else if (action->m_latency < min) {
 +        min = action->m_latency;
 +        XBT_DEBUG("Updating min (latency) with %p (start %f): %f", action,
 +               action->m_start, min);
 +      }
 +    }
 +  }
 +
 +  XBT_DEBUG("min value : %f", min);
 +
 +  return min;
 +}
 +
 +void WorkstationL07Model::updateActionsState(double now, double delta)
 +{
 +  double deltap = 0.0;
 +  void *_action, *_next_action;
 +  WorkstationL07ActionLmmPtr action;
 +
 +  xbt_swag_foreach_safe(_action, _next_action, p_runningActionSet) {
 +    action = dynamic_cast<WorkstationL07ActionLmmPtr>(static_cast<ActionPtr>(_action));
 +
 +    deltap = delta;
 +    if (action->m_latency > 0) {
 +      if (action->m_latency > deltap) {
 +        double_update(&(action->m_latency), deltap);
 +        deltap = 0.0;
 +      } else {
 +        double_update(&(deltap), action->m_latency);
 +        action->m_latency = 0.0;
 +      }
 +      if ((action->m_latency == 0.0) && (action->m_suspended == 0)) {
 +        action->updateBound();
 +        lmm_update_variable_weight(ptask_maxmin_system, action->p_variable, 1.0);
 +      }
 +    }
 +    XBT_DEBUG("Action (%p) : remains (%g) updated by %g.",
 +           action, action->m_remains, lmm_variable_getvalue(action->p_variable) * delta);
 +    double_update(&(action->m_remains), lmm_variable_getvalue(action->p_variable) * delta);
 +
 +    if (action->m_maxDuration != NO_MAX_DURATION)
 +      double_update(&(action->m_maxDuration), delta);
 +
 +    XBT_DEBUG("Action (%p) : remains (%g).",
 +           action, action->m_remains);
 +    if ((action->m_remains <= 0) &&
 +        (lmm_get_variable_weight(action->p_variable) > 0)) {
 +      action->m_finish = surf_get_clock();
 +      action->setState(SURF_ACTION_DONE);
 +    } else if ((action->m_maxDuration != NO_MAX_DURATION) &&
 +               (action->m_maxDuration <= 0)) {
 +      action->m_finish = surf_get_clock();
 +     action->setState(SURF_ACTION_DONE);
 +    } else {
 +      /* Need to check that none of the model has failed */
 +      lmm_constraint_t cnst = NULL;
 +      int i = 0;
 +      void *constraint_id = NULL;
 +
 +      while ((cnst = lmm_get_cnst_from_var(ptask_maxmin_system, action->p_variable,
 +                                    i++))) {
 +        constraint_id = lmm_constraint_id(cnst);
 +
 +        if (static_cast<WorkstationCLM03LmmPtr>(constraint_id)->p_stateCurrent == SURF_RESOURCE_OFF) {
 +          XBT_DEBUG("Action (%p) Failed!!", action);
 +          action->m_finish = surf_get_clock();
 +          action->setState(SURF_ACTION_FAILED);
 +          break;
 +        }
 +      }
 +    }
 +  }
 +  return;
 +}
 +
 +ActionPtr WorkstationL07Model::executeParallelTask(int workstation_nb,
 +                                                   void **workstation_list,
 +                                                 double
 +                                                 *computation_amount, double
 +                                                 *communication_amount,
 +                                                 double rate)
 +{
 +  WorkstationL07ActionLmmPtr action;
 +  int i, j;
 +  unsigned int cpt;
 +  int nb_link = 0;
 +  int nb_host = 0;
 +  double latency = 0.0;
 +
 +  if (ptask_parallel_task_link_set == NULL)
 +    ptask_parallel_task_link_set = xbt_dict_new_homogeneous(NULL);
 +
 +  xbt_dict_reset(ptask_parallel_task_link_set);
 +
 +  /* Compute the number of affected resources... */
 +  for (i = 0; i < workstation_nb; i++) {
 +    for (j = 0; j < workstation_nb; j++) {
 +      xbt_dynar_t route=NULL;
 +
 +      if (communication_amount[i * workstation_nb + j] > 0) {
 +        double lat=0.0;
 +        unsigned int cpt;
 +        void *_link;
 +        LinkL07Ptr link;
 +
 +        routing_platf->getRouteAndLatency(dynamic_cast<WorkstationL07Ptr>(
 +                                                 static_cast<ResourcePtr>(
 +                                                  workstation_list[i]))->p_netElm,
 +                                                dynamic_cast<WorkstationL07Ptr>(
 +                                                 static_cast<ResourcePtr>(
 +                                                      workstation_list[j]))->p_netElm,
 +                                                &route,
 +                                                &lat);
 +        latency = MAX(latency, lat);
 +
 +        xbt_dynar_foreach(route, cpt, _link) {
 +           link = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(_link));
 +           xbt_dict_set(ptask_parallel_task_link_set, link->m_name, link, NULL);
 +        }
 +      }
 +    }
 +  }
 +
 +  nb_link = xbt_dict_length(ptask_parallel_task_link_set);
 +  xbt_dict_reset(ptask_parallel_task_link_set);
 +
 +  for (i = 0; i < workstation_nb; i++)
 +    if (computation_amount[i] > 0)
 +      nb_host++;
 +
 +  action = new WorkstationL07ActionLmm(this, 1, 0);
 +  XBT_DEBUG("Creating a parallel task (%p) with %d cpus and %d links.",
 +         action, workstation_nb, nb_link);
 +  action->m_suspended = 0;        /* Should be useless because of the
 +                                   calloc but it seems to help valgrind... */
 +  action->m_workstationNb = workstation_nb;
 +  action->p_workstationList = (WorkstationCLM03Ptr *) workstation_list;
 +  action->p_computationAmount = computation_amount;
 +  action->p_communicationAmount = communication_amount;
 +  action->m_latency = latency;
 +  action->m_rate = rate;
 +
 +  action->p_variable = lmm_variable_new(ptask_maxmin_system, action, 1.0,
 +                       (action->m_rate > 0) ? action->m_rate : -1.0,
 +                       workstation_nb + nb_link);
 +
 +  if (action->m_latency > 0)
 +    lmm_update_variable_weight(ptask_maxmin_system, action->p_variable, 0.0);
 +
 +  for (i = 0; i < workstation_nb; i++)
 +    lmm_expand(ptask_maxmin_system,
 +             static_cast<CpuLmmPtr>(dynamic_cast<WorkstationL07Ptr>(
 +                                         static_cast<ResourcePtr>(workstation_list[i]))->p_cpu)->p_constraint,
 +               action->p_variable, computation_amount[i]);
 +
 +  for (i = 0; i < workstation_nb; i++) {
 +    for (j = 0; j < workstation_nb; j++) {
 +      void *_link;
 +      LinkL07Ptr link;
 +
 +      xbt_dynar_t route=NULL;
 +      if (communication_amount[i * workstation_nb + j] == 0.0)
 +        continue;
 +
 +      routing_platf->getRouteAndLatency(dynamic_cast<WorkstationL07Ptr>(
 +                                         static_cast<ResourcePtr>(workstation_list[i]))->p_netElm,
 +                                        dynamic_cast<WorkstationL07Ptr>(
 +                                         static_cast<ResourcePtr>(workstation_list[j]))->p_netElm,
 +                                          &route, NULL);
 +
 +      xbt_dynar_foreach(route, cpt, _link) {
 +        link = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(_link));
 +        lmm_expand_add(ptask_maxmin_system, link->p_constraint,
 +                       action->p_variable,
 +                       communication_amount[i * workstation_nb + j]);
 +      }
 +    }
 +  }
 +
 +  if (nb_link + nb_host == 0) {
 +    action->m_cost = 1.0;
 +    action->m_remains = 0.0;
 +  }
 +
 +  return static_cast<ActionPtr>(action);
 +}
 +
 +ResourcePtr WorkstationL07Model::createResource(const char *name, double power_scale,
 +                               double power_initial,
 +                               tmgr_trace_t power_trace,
 +                               e_surf_resource_state_t state_initial,
 +                               tmgr_trace_t state_trace,
 +                               xbt_dict_t cpu_properties)
 +{
 +  WorkstationL07Ptr wk = NULL;
 +  xbt_assert(!surf_workstation_resource_priv(surf_workstation_resource_by_name(name)),
 +              "Host '%s' declared several times in the platform file.",
 +              name);
 +
 +  wk = new WorkstationL07(this, name, cpu_properties,
 +                                static_cast<RoutingEdgePtr>(xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL)),
 +                                dynamic_cast<CpuPtr>(static_cast<ResourcePtr>(xbt_lib_get_or_null(host_lib, name, SURF_CPU_LEVEL))));
 +
 +  xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, static_cast<ResourcePtr>(wk));
 +
 +  return wk;//FIXME:xbt_lib_get_elm_or_null(host_lib, name);
 +}
 +
 +ActionPtr WorkstationL07Model::communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst,
 +                                       double size, double rate)
 +{
 +  void **workstation_list = xbt_new0(void *, 2);
 +  double *computation_amount = xbt_new0(double, 2);
 +  double *communication_amount = xbt_new0(double, 4);
 +  ActionPtr res = NULL;
 +
 +  workstation_list[0] = static_cast<ResourcePtr>(src);
 +  workstation_list[1] = static_cast<ResourcePtr>(dst);
 +  communication_amount[1] = size;
 +
 +  res = executeParallelTask(2, workstation_list,
 +                                    computation_amount,
 +                                    communication_amount, rate);
 +
 +  return res;
 +}
 +
 +xbt_dynar_t WorkstationL07Model::getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst)
 +{
 +  xbt_dynar_t route=NULL;
 +  routing_platf->getRouteAndLatency(src->p_netElm, dst->p_netElm, &route, NULL);
 +  return route;
 +}
 +
 +ResourcePtr CpuL07Model::createResource(const char *name, double power_scale,
 +                               double power_initial,
 +                               tmgr_trace_t power_trace,
 +                               e_surf_resource_state_t state_initial,
 +                               tmgr_trace_t state_trace,
 +                               xbt_dict_t cpu_properties)
 +{
 +  CpuL07Ptr cpu = NULL;
 +  xbt_assert(!surf_workstation_resource_priv(surf_workstation_resource_by_name(name)),
 +              "Host '%s' declared several times in the platform file.",
 +              name);
 +
 +  cpu = new CpuL07(this, name, cpu_properties);
 +
 +  cpu->p_power.scale = power_scale;
 +  xbt_assert(cpu->p_power.scale > 0, "Power has to be >0");
 +
 +  cpu->m_powerCurrent = power_initial;
 +  if (power_trace)
 +    cpu->p_power.event =
 +        tmgr_history_add_trace(history, power_trace, 0.0, 0, static_cast<ResourcePtr>(cpu));
 +
 +  cpu->p_stateCurrent = state_initial;
 +  if (state_trace)
 +    cpu->p_stateEvent =
 +        tmgr_history_add_trace(history, state_trace, 0.0, 0, static_cast<ResourcePtr>(cpu));
 +
 +  cpu->p_constraint =
 +      lmm_constraint_new(ptask_maxmin_system, cpu,
 +                         cpu->m_powerCurrent * cpu->p_power.scale);
 +
 +  xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, static_cast<ResourcePtr>(cpu));
 +
 +  return cpu;//FIXME:xbt_lib_get_elm_or_null(host_lib, name);
 +}
 +
 +ResourcePtr NetworkL07Model::createResource(const char *name,
 +                                 double bw_initial,
 +                                 tmgr_trace_t bw_trace,
 +                                 double lat_initial,
 +                                 tmgr_trace_t lat_trace,
 +                                 e_surf_resource_state_t
 +                                 state_initial,
 +                                 tmgr_trace_t state_trace,
 +                                 e_surf_link_sharing_policy_t
 +                                 policy, xbt_dict_t properties)
 +{
 +  LinkL07Ptr nw_link = new LinkL07(this, xbt_strdup(name), properties);
 +  xbt_assert(!xbt_lib_get_or_null(link_lib, name, SURF_LINK_LEVEL),
 +              "Link '%s' declared several times in the platform file.",
 +              name);
 +
 +  nw_link->m_bwCurrent = bw_initial;
 +  if (bw_trace)
 +    nw_link->p_bwEvent =
 +        tmgr_history_add_trace(history, bw_trace, 0.0, 0, static_cast<ResourcePtr>(nw_link));
 +  nw_link->p_stateCurrent = state_initial;
 +  nw_link->m_latCurrent = lat_initial;
 +  if (lat_trace)
 +    nw_link->p_latEvent =
 +        tmgr_history_add_trace(history, lat_trace, 0.0, 0, static_cast<ResourcePtr>(nw_link));
 +  if (state_trace)
 +    nw_link->p_stateEvent =
 +        tmgr_history_add_trace(history, state_trace, 0.0, 0, static_cast<ResourcePtr>(nw_link));
 +
 +  nw_link->p_constraint =
 +      lmm_constraint_new(ptask_maxmin_system, nw_link,
 +                         nw_link->m_bwCurrent);
 +
 +  if (policy == SURF_LINK_FATPIPE)
 +    lmm_constraint_shared(nw_link->p_constraint);
 +
 +  xbt_lib_set(link_lib, name, SURF_LINK_LEVEL, static_cast<ResourcePtr>(nw_link));
 +  return nw_link;
 +}
 +
 +void WorkstationL07Model::addTraces()
 +{
 +  xbt_dict_cursor_t cursor = NULL;
 +  char *trace_name, *elm;
 +
 +  if (!trace_connect_list_host_avail)
 +    return;
 +
 +  /* Connect traces relative to cpu */
 +  xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
 +    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 +    CpuL07Ptr host = dynamic_cast<CpuL07Ptr>(
 +                         static_cast<ResourcePtr>(
 +                           surf_cpu_resource_priv(
 +                             surf_cpu_resource_by_name(elm))));
 +
 +    xbt_assert(host, "Host %s undefined", elm);
 +    xbt_assert(trace, "Trace %s undefined", trace_name);
 +
 +    host->p_stateEvent = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(host));
 +  }
 +
 +  xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
 +    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 +    CpuL07Ptr host = dynamic_cast<CpuL07Ptr>(
 +                         static_cast<ResourcePtr>(
 +                           surf_cpu_resource_priv(
 +                             surf_cpu_resource_by_name(elm))));
 +
 +    xbt_assert(host, "Host %s undefined", elm);
 +    xbt_assert(trace, "Trace %s undefined", trace_name);
 +
 +    host->p_power.event = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(host));
 +  }
 +
 +  /* Connect traces relative to network */
 +  xbt_dict_foreach(trace_connect_list_link_avail, cursor, trace_name, elm) {
 +    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 +    LinkL07Ptr link = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL)));
 +
 +    xbt_assert(link, "Link %s undefined", elm);
 +    xbt_assert(trace, "Trace %s undefined", trace_name);
 +
 +    link->p_stateEvent = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(link));
 +  }
 +
 +  xbt_dict_foreach(trace_connect_list_bandwidth, cursor, trace_name, elm) {
 +    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 +    LinkL07Ptr link = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL)));
 +
 +    xbt_assert(link, "Link %s undefined", elm);
 +    xbt_assert(trace, "Trace %s undefined", trace_name);
 +
 +    link->p_bwEvent = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(link));
 +  }
 +
 +  xbt_dict_foreach(trace_connect_list_latency, cursor, trace_name, elm) {
 +    tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name);
 +    LinkL07Ptr link = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL)));
 +
 +    xbt_assert(link, "Link %s undefined", elm);
 +    xbt_assert(trace, "Trace %s undefined", trace_name);
 +
 +    link->p_latEvent = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(link));
 +  }
 +}
 +
 +/************
 + * Resource *
 + ************/
 +
 +WorkstationL07::WorkstationL07(WorkstationModelPtr model, const char* name, xbt_dict_t props, RoutingEdgePtr netElm, CpuPtr cpu)
-   static_cast<CpuL07ModelPtr>(surf_cpu_model)->createResource(
++  : Resource(model, name, props),
++    WorkstationCLM03Lmm(model, name, props, NULL, netElm, cpu),
++    WorkstationCLM03(model, name, props, NULL, netElm, cpu)
 +{
 +}
 +
 +double WorkstationL07::getPowerPeakAt(int pstate_index)
 +{
 +      XBT_DEBUG("[ws_get_power_peak_at] Not implemented for workstation_ptask_L07");
 +      return 0.0;
 +}
 +
 +int WorkstationL07::getNbPstates()
 +{
 +      XBT_DEBUG("[ws_get_nb_pstates] Not implemented for workstation_ptask_L07");
 +      return 0.0;
 +}
 +
 +void WorkstationL07::setPowerPeakAt(int pstate_index)
 +{
 +      XBT_DEBUG("[ws_set_power_peak_at] Not implemented for workstation_ptask_L07");
 +}
 +
 +double WorkstationL07::getConsumedEnergy()
 +{
 +      XBT_DEBUG("[ws_get_consumed_energy] Not implemented for workstation_ptask_L07");
 +      return 0.0;
 +}
 +
 +CpuL07::CpuL07(CpuL07ModelPtr model, const char* name, xbt_dict_t props)
 + : Resource(model, name, props), CpuLmm(model, name, props) {
 +
 +}
 +
 +LinkL07::LinkL07(NetworkL07ModelPtr model, const char* name, xbt_dict_t props)
 + : Resource(model, name, props), NetworkCm02LinkLmm(model, name, props) {
 +
 +}
 +
 +bool CpuL07::isUsed(){
 +  return lmm_constraint_used(ptask_maxmin_system, p_constraint);
 +}
 +
 +bool LinkL07::isUsed(){
 +  return lmm_constraint_used(ptask_maxmin_system, p_constraint);
 +}
 +
 +void CpuL07::updateState(tmgr_trace_event_t event_type, double value, double date){
 +  XBT_DEBUG("Updating cpu %s (%p) with value %g", m_name, this, value);
 +  if (event_type == p_power.event) {
 +      m_powerCurrent = value;
 +    lmm_update_constraint_bound(ptask_maxmin_system, p_constraint, m_powerCurrent * p_power.scale);
 +    if (tmgr_trace_event_free(event_type))
 +      p_power.event = NULL;
 +  } else if (event_type == p_stateEvent) {
 +    if (value > 0)
 +      p_stateCurrent = SURF_RESOURCE_ON;
 +    else
 +      p_stateCurrent = SURF_RESOURCE_OFF;
 +    if (tmgr_trace_event_free(event_type))
 +      p_stateEvent = NULL;
 +  } else {
 +    XBT_CRITICAL("Unknown event ! \n");
 +    xbt_abort();
 +  }
 +  return;
 +}
 +
 +void LinkL07::updateState(tmgr_trace_event_t event_type, double value, double date){
 +  XBT_DEBUG("Updating link %s (%p) with value=%f for date=%g", m_name, this, value, date);
 +  if (event_type == p_bwEvent) {
 +    m_bwCurrent = value;
 +    lmm_update_constraint_bound(ptask_maxmin_system, p_constraint, m_bwCurrent);
 +    if (tmgr_trace_event_free(event_type))
 +      p_bwEvent = NULL;
 +  } else if (event_type == p_latEvent) {
 +    lmm_variable_t var = NULL;
 +    WorkstationL07ActionLmmPtr action;
 +    lmm_element_t elem = NULL;
 +
 +    m_latCurrent = value;
 +    while ((var = lmm_get_var_from_cnst(ptask_maxmin_system, p_constraint, &elem))) {
 +      action = (WorkstationL07ActionLmmPtr) lmm_variable_id(var);
 +      action->updateBound();
 +    }
 +    if (tmgr_trace_event_free(event_type))
 +      p_latEvent = NULL;
 +  } else if (event_type == p_stateEvent) {
 +    if (value > 0)
 +      p_stateCurrent = SURF_RESOURCE_ON;
 +    else
 +      p_stateCurrent = SURF_RESOURCE_OFF;
 +    if (tmgr_trace_event_free(event_type))
 +      p_stateEvent = NULL;
 +  } else {
 +    XBT_CRITICAL("Unknown event ! \n");
 +    xbt_abort();
 +  }
 +  return;
 +}
 +
 +e_surf_resource_state_t WorkstationL07::getState()
 +{
 +  return p_cpu->p_stateCurrent;
 +}
 +
 +e_surf_resource_state_t CpuL07::getState()
 +{
 +  return p_stateCurrent;
 +}
 +
 +double CpuL07::getSpeed(double load)
 +{
 +  return load * p_power.scale;
 +}
 +
 +double CpuL07::getAvailableSpeed()
 +{
 +  return m_powerCurrent;
 +}
 +
 +ActionPtr WorkstationL07::execute(double size)
 +{
 +  void **workstation_list = xbt_new0(void *, 1);
 +  double *computation_amount = xbt_new0(double, 1);
 +  double *communication_amount = xbt_new0(double, 1);
 +
 +  workstation_list[0] = static_cast<ResourcePtr>(this);
 +  communication_amount[0] = 0.0;
 +  computation_amount[0] = size;
 +
 +  return static_cast<WorkstationL07ModelPtr>(p_model)->executeParallelTask(1, workstation_list,
 +                                            computation_amount,
 +                                     communication_amount, -1);
 +}
 +
 +ActionPtr WorkstationL07::sleep(double duration)
 +{
 +  WorkstationL07ActionLmmPtr action = NULL;
 +
 +  XBT_IN("(%s,%g)", m_name, duration);
 +
 +  action = dynamic_cast<WorkstationL07ActionLmmPtr>(execute(1.0));
 +  action->m_maxDuration = duration;
 +  action->m_suspended = 2;
 +  lmm_update_variable_weight(ptask_maxmin_system, action->p_variable, 0.0);
 +
 +  XBT_OUT();
 +  return action;
 +}
 +
 +double LinkL07::getBandwidth()
 +{
 +  return m_bwCurrent;
 +}
 +
 +double LinkL07::getLatency()
 +{
 +  return m_latCurrent;
 +}
 +
 +bool LinkL07::isShared()
 +{
 +  return lmm_constraint_is_shared(p_constraint);
 +}
 +
 +/**********
 + * Action *
 + **********/
 +
 +WorkstationL07ActionLmm::~WorkstationL07ActionLmm(){
 +  free(p_workstationList);
 +  free(p_communicationAmount);
 +  free(p_computationAmount);
 +#ifdef HAVE_TRACING
 +  xbt_free(p_category);
 +#endif
 +}
 +
 +void WorkstationL07ActionLmm::updateBound()
 +{
 +  double lat_current = 0.0;
 +  double lat_bound = -1.0;
 +  int i, j;
 +
 +  for (i = 0; i < m_workstationNb; i++) {
 +    for (j = 0; j < m_workstationNb; j++) {
 +      xbt_dynar_t route=NULL;
 +
 +      if (p_communicationAmount[i * m_workstationNb + j] > 0) {
 +        double lat = 0.0;
 +        routing_platf->getRouteAndLatency(dynamic_cast<WorkstationL07Ptr>(
 +                                           static_cast<ResourcePtr>(((void**)p_workstationList)[i]))->p_netElm,
 +                                          dynamic_cast<WorkstationL07Ptr>(
 +                                           static_cast<ResourcePtr>(((void**)p_workstationList)[j]))->p_netElm,
 +                                                        &route, &lat);
 +
 +        lat_current = MAX(lat_current, lat * p_communicationAmount[i * m_workstationNb + j]);
 +      }
 +    }
 +  }
 +  lat_bound = sg_tcp_gamma / (2.0 * lat_current);
 +  XBT_DEBUG("action (%p) : lat_bound = %g", this, lat_bound);
 +  if ((m_latency == 0.0) && (m_suspended == 0)) {
 +    if (m_rate < 0)
 +      lmm_update_variable_bound(ptask_maxmin_system, p_variable, lat_bound);
 +    else
 +      lmm_update_variable_bound(ptask_maxmin_system, p_variable, min(m_rate, lat_bound));
 +  }
 +}
 +
 +int WorkstationL07ActionLmm::unref()
 +{
 +  m_refcount--;
 +  if (!m_refcount) {
 +    xbt_swag_remove(static_cast<ActionPtr>(this), p_stateSet);
 +    if (p_variable)
 +      lmm_variable_free(ptask_maxmin_system, p_variable);
 +    delete this;
 +    return 1;
 +  }
 +  return 0;
 +}
 +
 +void WorkstationL07ActionLmm::cancel()
 +{
 +  setState(SURF_ACTION_FAILED);
 +  return;
 +}
 +
 +void WorkstationL07ActionLmm::suspend()
 +{
 +  XBT_IN("(%p))", this);
 +  if (m_suspended != 2) {
 +    m_suspended = 1;
 +    lmm_update_variable_weight(ptask_maxmin_system, p_variable, 0.0);
 +  }
 +  XBT_OUT();
 +}
 +
 +void WorkstationL07ActionLmm::resume()
 +{
 +  XBT_IN("(%p)", this);
 +  if (m_suspended != 2) {
 +    lmm_update_variable_weight(ptask_maxmin_system, p_variable, 1.0);
 +    m_suspended = 0;
 +  }
 +  XBT_OUT();
 +}
 +
 +bool WorkstationL07ActionLmm::isSuspended()
 +{
 +  return m_suspended == 1;
 +}
 +
 +void WorkstationL07ActionLmm::setMaxDuration(double duration)
 +{                               /* FIXME: should inherit */
 +  XBT_IN("(%p,%g)", this, duration);
 +  m_maxDuration = duration;
 +  XBT_OUT();
 +}
 +
 +void WorkstationL07ActionLmm::setPriority(double priority)
 +{                               /* FIXME: should inherit */
 +  XBT_IN("(%p,%g)", this, priority);
 +  m_priority = priority;
 +  XBT_OUT();
 +}
 +
 +double WorkstationL07ActionLmm::getRemains()
 +{
 +  XBT_IN("(%p)", this);
 +  XBT_OUT();
 +  return m_remains;
 +}
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +static void ptask_finalize(void)
 +{
 +  xbt_dict_free(&ptask_parallel_task_link_set);
 +
 +  delete surf_workstation_model;
 +  surf_workstation_model = NULL;
 +  delete surf_network_model;
 +  surf_network_model = NULL;
 +
 +  ptask_host_count = 0;
 +
 +  if (ptask_maxmin_system) {
 +    lmm_system_free(ptask_maxmin_system);
 +    ptask_maxmin_system = NULL;
 +  }
 +}
 +
 +/**************************************/
 +/******* Resource Private    **********/
 +/**************************************/
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +/**************************************/
 +/*** Resource Creation & Destruction **/
 +/**************************************/
 +
 +static void ptask_parse_workstation_init(sg_platf_host_cbarg_t host)
 +{
 +  double power_peak = xbt_dynar_get_as(host->power_peak, host->pstate, double);
 +  //cpu->power_peak = power_peak;
 +  xbt_dynar_free(&(host->power_peak));  /* kill memory leak */
 +  static_cast<WorkstationL07ModelPtr>(surf_workstation_model)->createResource(
 +      host->id,
 +      power_peak,
 +      host->power_scale,
 +      host->power_trace,
 +      host->initial_state,
 +      host->state_trace,
 +      host->properties);
 +}
 +
 +static void ptask_parse_cpu_init(sg_platf_host_cbarg_t host)
 +{
 +  double power_peak = xbt_dynar_get_as(host->power_peak, host->pstate, double);
-   xbt_assert(!surf_cpu_model, "CPU model type already defined");
++  static_cast<CpuL07ModelPtr>(surf_cpu_model_pm)->createResource(
 +      host->id,
 +      power_peak,
 +      host->power_scale,
 +      host->power_trace,
 +      host->initial_state,
 +      host->state_trace,
 +      host->properties);
 +}
 +
 +
 +
 +static void ptask_parse_link_init(sg_platf_link_cbarg_t link)
 +{
 +  if (link->policy == SURF_LINK_FULLDUPLEX) {
 +    char *link_id;
 +    link_id = bprintf("%s_UP", link->id);
 +    static_cast<NetworkL07ModelPtr>(surf_network_model)->createResource(link_id,
 +                               link->bandwidth,
 +                               link->bandwidth_trace,
 +                               link->latency,
 +                               link->latency_trace,
 +                               link->state,
 +                               link->state_trace,
 +                               link->policy,
 +                               link->properties);
 +    xbt_free(link_id);
 +    link_id = bprintf("%s_DOWN", link->id);
 +    static_cast<NetworkL07ModelPtr>(surf_network_model)->createResource(link_id,
 +                               link->bandwidth,
 +                               link->bandwidth_trace,
 +                               link->latency,
 +                               link->latency_trace,
 +                               link->state,
 +                               link->state_trace,
 +                               link->policy,
 +                               NULL); /* FIXME: We need to deep copy the
 +                                       * properties or we won't be able to free
 +                                       * it */
 +    xbt_free(link_id);
 +  } else {
 +        static_cast<NetworkL07ModelPtr>(surf_network_model)->createResource(link->id,
 +                               link->bandwidth,
 +                               link->bandwidth_trace,
 +                               link->latency,
 +                               link->latency_trace,
 +                               link->state,
 +                               link->state_trace,
 +                               link->policy,
 +                               link->properties);
 +  }
 +
 +  current_property_set = NULL;
 +}
 +
 +static void ptask_add_traces(){
 +  static_cast<WorkstationL07ModelPtr>(surf_workstation_model)->addTraces();
 +}
 +
 +static void ptask_define_callbacks()
 +{
 +  sg_platf_host_add_cb(ptask_parse_cpu_init);
 +  sg_platf_host_add_cb(ptask_parse_workstation_init);
 +  sg_platf_link_add_cb(ptask_parse_link_init);
 +  sg_platf_postparse_add_cb(ptask_add_traces);
 +}
 +
 +/**************************************/
 +/*************** Generic **************/
 +/**************************************/
 +void surf_workstation_model_init_ptask_L07(void)
 +{
 +  XBT_INFO("surf_workstation_model_init_ptask_L07");
++  xbt_assert(!surf_cpu_model_pm, "CPU model type already defined");
 +  xbt_assert(!surf_network_model, "network model type already defined");
 +  ptask_define_callbacks();
 +  surf_workstation_model = new WorkstationL07Model();
 +  ModelPtr model = static_cast<ModelPtr>(surf_workstation_model);
 +  xbt_dynar_push(model_list, &model);
 +}
index 0cd7713,0000000..0fcb23c
mode 100644,000000..100644
--- /dev/null
@@@ -1,184 -1,0 +1,184 @@@
-   ~CpuL07Model() {surf_cpu_model = NULL;};
 +#include "workstation.hpp"
 +
 +#ifndef WORKSTATION_L07_HPP_
 +#define WORKSTATION_L07_HPP_
 +
 +/***********
 + * Classes *
 + ***********/
 +
 +class WorkstationL07Model;
 +typedef WorkstationL07Model *WorkstationL07ModelPtr;
 +
 +class CpuL07Model;
 +typedef CpuL07Model *CpuL07ModelPtr;
 +
 +class NetworkL07Model;
 +typedef NetworkL07Model *NetworkL07ModelPtr;
 +
 +class WorkstationL07;
 +typedef WorkstationL07 *WorkstationL07Ptr;
 +
 +class CpuL07;
 +typedef CpuL07 *CpuL07Ptr;
 +
 +class LinkL07;
 +typedef LinkL07 *LinkL07Ptr;
 +
 +class WorkstationL07ActionLmm;
 +typedef WorkstationL07ActionLmm *WorkstationL07ActionLmmPtr;
 +
 +/*FIXME:class WorkstationActionLmm;
 +typedef WorkstationActionLmm *WorkstationActionLmmPtr;*/
 +
 +/*********
 + * Tools *
 + *********/
 +
 +/*********
 + * Model *
 + *********/
 +class WorkstationL07Model : public WorkstationModel {
 +public:
 +  WorkstationL07Model();
 +  ~WorkstationL07Model();
 +
 +  double shareResources(double now);
 +  void updateActionsState(double now, double delta);
 +  ResourcePtr createResource(const char *name, double power_scale,
 +                                 double power_initial,
 +                                 tmgr_trace_t power_trace,
 +                                 e_surf_resource_state_t state_initial,
 +                                 tmgr_trace_t state_trace,
 +                                 xbt_dict_t cpu_properties);
 +  ActionPtr executeParallelTask(int workstation_nb,
 +                                        void **workstation_list,
 +                                        double *computation_amount,
 +                                        double *communication_amount,
 +                                        double rate);
 +  xbt_dynar_t getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst);
 +  ActionPtr communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst, double size, double rate);
 +  void addTraces();
 +  CpuL07ModelPtr p_cpuModel;
 +  NetworkL07ModelPtr p_networkModel;
 +};
 +
 +class CpuL07Model : public CpuModel {
 +public:
 +  CpuL07Model() : CpuModel("cpuL07") {};
++  ~CpuL07Model() {surf_cpu_model_pm = NULL;};
 +  ResourcePtr createResource(const char *name, double power_scale,
 +                                 double power_initial,
 +                                 tmgr_trace_t power_trace,
 +                                 e_surf_resource_state_t state_initial,
 +                                 tmgr_trace_t state_trace,
 +                                 xbt_dict_t cpu_properties);
 +  void addTraces() {DIE_IMPOSSIBLE;};
 +  WorkstationL07ModelPtr p_workstationModel;
 +};
 +
 +class NetworkL07Model : public NetworkCm02Model {
 +public:
 +  NetworkL07Model() : NetworkCm02Model(0) {};
 +  ~NetworkL07Model() {surf_network_model = NULL;};
 +  ResourcePtr createResource(const char *name,
 +                                                 double bw_initial,
 +                                                 tmgr_trace_t bw_trace,
 +                                                 double lat_initial,
 +                                                 tmgr_trace_t lat_trace,
 +                                                 e_surf_resource_state_t
 +                                                 state_initial,
 +                                                 tmgr_trace_t state_trace,
 +                                                 e_surf_link_sharing_policy_t
 +                                                 policy, xbt_dict_t properties);
 +
 +  xbt_dynar_t getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst) {DIE_IMPOSSIBLE;};
 +  ActionPtr communicate(RoutingEdgePtr src, RoutingEdgePtr dst, double size, double rate) {DIE_IMPOSSIBLE;};
 +  void addTraces() {DIE_IMPOSSIBLE;};
 +  WorkstationL07ModelPtr p_workstationModel;
 +};
 +
 +/************
 + * Resource *
 + ************/
 +
 +class WorkstationL07 : public WorkstationCLM03Lmm {
 +public:
 +  WorkstationL07(WorkstationModelPtr model, const char* name, xbt_dict_t props, RoutingEdgePtr netElm, CpuPtr cpu);
 +  //bool isUsed();
 +  bool isUsed() {DIE_IMPOSSIBLE;};
 +  void updateState(tmgr_trace_event_t event_type, double value, double date) {DIE_IMPOSSIBLE;};
 +  ActionPtr execute(double size);
 +  ActionPtr sleep(double duration);
 +  e_surf_resource_state_t getState();
 +  double getPowerPeakAt(int pstate_index);
 +  int getNbPstates();
 +  void setPowerPeakAt(int pstate_index);
 +  double getConsumedEnergy();
 +};
 +
 +class CpuL07 : public CpuLmm {
 +public:
 +  CpuL07(CpuL07ModelPtr model, const char* name, xbt_dict_t properties);
 +  bool isUsed();
 +  //bool isUsed() {DIE_IMPOSSIBLE;};
 +  void updateState(tmgr_trace_event_t event_type, double value, double date);
 +  e_surf_resource_state_t getState();
 +  double getSpeed(double load);
 +  double getAvailableSpeed();
 +  ActionPtr execute(double size) {DIE_IMPOSSIBLE;};
 +  ActionPtr sleep(double duration) {DIE_IMPOSSIBLE;};
 +
 +  double getCurrentPowerPeak() {};
 +  double getPowerPeakAt(int pstate_index) {};
 +  int getNbPstates() {};
 +  void setPowerPeakAt(int pstate_index) {};
 +  double getConsumedEnergy() {};
 +
 +  double m_powerCurrent;
 +};
 +
 +class LinkL07 : public NetworkCm02LinkLmm {
 +public:
 +  LinkL07(NetworkL07ModelPtr model, const char* name, xbt_dict_t props);
 +  bool isUsed();
 +  void updateState(tmgr_trace_event_t event_type, double value, double date);
 +  double getBandwidth();
 +  double getLatency();
 +  bool isShared();
 +
 +  double m_latCurrent;
 +  tmgr_trace_event_t p_latEvent;
 +  double m_bwCurrent;
 +  tmgr_trace_event_t p_bwEvent;
 +};
 +
 +/**********
 + * Action *
 + **********/
 +class WorkstationL07ActionLmm : public WorkstationActionLmm {
 +public:
 +  WorkstationL07ActionLmm(ModelPtr model, double cost, bool failed)
 +  : Action(model, cost, failed), WorkstationActionLmm(model, cost, failed) {};
 + ~WorkstationL07ActionLmm();
 +
 +  void updateBound();
 +
 +  int unref();
 +  void cancel();
 +  void suspend();
 +  void resume();
 +  bool isSuspended();
 +  void setMaxDuration(double duration);
 +  void setPriority(double priority);
 +  double getRemains();
 +
 +  int m_workstationNb;
 +  WorkstationCLM03Ptr *p_workstationList;
 +  double *p_computationAmount;
 +  double *p_communicationAmount;
 +  double m_latency;
 +  double m_rate;
 +};
 +
 +#endif /* WORKSTATION_L07_HPP_ */
@@@ -58,23 -58,23 +58,23 @@@ void test(char *platform
    parse_platform_file(platform);
  
    /*********************** CPU ***********************************/
-   XBT_DEBUG("%p", surf_cpu_model);
+   XBT_DEBUG("%p", surf_cpu_model_pm);
    cpuA = surf_cpu_resource_by_name("Cpu A");
    cpuB = surf_cpu_resource_by_name("Cpu B");
  
    /* Let's check that those two processors exist */
 -  XBT_DEBUG("%s : %p", surf_resource_name(cpuA), cpuA);
 -  XBT_DEBUG("%s : %p", surf_resource_name(cpuB), cpuB);
 +  XBT_DEBUG("%s : %p", surf_resource_name(surf_cpu_resource_priv(cpuA)), cpuA);
 +  XBT_DEBUG("%s : %p", surf_resource_name(surf_cpu_resource_priv(cpuB)), cpuB);
  
    /* Let's do something on it */
 -  actionA = surf_cpu_model_pm->extension.cpu.execute(cpuA, 1000.0);
 -  actionB = surf_cpu_model_pm->extension.cpu.execute(cpuB, 1000.0);
 -  actionC = surf_cpu_model_pm->extension.cpu.sleep(cpuB, 7.32);
 +  actionA = surf_cpu_execute(cpuA, 1000.0);
 +  actionB = surf_cpu_execute(cpuB, 1000.0);
 +  actionC = surf_cpu_sleep(cpuB, 7.32);
  
    /* Use whatever calling style you want... */
 -  stateActionA = surf_cpu_model_pm->action_state_get(actionA);     /* When you know actionA model type */
 -  stateActionB = actionB->model_obj->action_state_get(actionB);        /* If you're unsure about it's model type */
 -  stateActionC = surf_cpu_model_pm->action_state_get(actionC);     /* When you know actionA model type */
 +  stateActionA = surf_action_get_state(actionA);     /* When you know actionA model type */
 +  stateActionB = surf_action_get_state(actionB);        /* If you're unsure about it's model type */
 +  stateActionC = surf_action_get_state(actionC);     /* When you know actionA model type */
  
    /* And just look at the state of these tasks */
    XBT_DEBUG("actionA : %p (%s)", actionA, string_action(stateActionA));
    cardB = sg_routing_edge_by_name_or_null("Cpu B");
  
    /* Let's check that those two processors exist */
 -  XBT_DEBUG("%s : %p", surf_resource_name(cardA), cardA);
 -  XBT_DEBUG("%s : %p", surf_resource_name(cardB), cardB);
 +  XBT_DEBUG("%s : %p", surf_routing_edge_name(cardA), cardA);
 +  XBT_DEBUG("%s : %p", surf_routing_edge_name(cardB), cardB);
  
    /* Let's do something on it */
 -  surf_network_model->extension.network.communicate(cardA, cardB,
 -                                                    150.0, -1.0);
 +  surf_network_model_communicate(surf_network_model, cardA, cardB, 150.0, -1.0);
  
    surf_solve(-1.0);                 /* Takes traces into account. Returns 0.0 */
    do {
      XBT_DEBUG("Next Event : %g", now);
      XBT_DEBUG("\t CPU actions");
      while ((action =
-             xbt_swag_extract(surf_model_failed_action_set((surf_model_t)surf_cpu_model)))) {
 -            xbt_swag_extract(surf_cpu_model_pm->states.failed_action_set))) {
++            xbt_swag_extract(surf_model_failed_action_set((surf_model_t)surf_cpu_model_pm)))) {
        XBT_DEBUG("\t * Failed : %p", action);
 -      action->model_obj->action_unref(action);
 +      surf_action_unref(action);
      }
      while ((action =
-             xbt_swag_extract(surf_model_done_action_set((surf_model_t)surf_cpu_model)))) {
 -            xbt_swag_extract(surf_cpu_model_pm->states.done_action_set))) {
++            xbt_swag_extract(surf_model_done_action_set((surf_model_t)surf_cpu_model_pm)))) {
        XBT_DEBUG("\t * Done : %p", action);
 -      action->model_obj->action_unref(action);
 +      surf_action_unref(action);
      }
      XBT_DEBUG("\t Network actions");
      while ((action =
 -            xbt_swag_extract(surf_network_model->states.
 -                             failed_action_set))) {
 +            xbt_swag_extract(surf_model_failed_action_set((surf_model_t)surf_network_model)))) {
        XBT_DEBUG("\t * Failed : %p", action);
 -      action->model_obj->action_unref(action);
 +      surf_action_unref(action);
      }
      while ((action =
 -            xbt_swag_extract(surf_network_model->states.
 -                             done_action_set))) {
 +            xbt_swag_extract(surf_model_done_action_set((surf_model_t)surf_network_model)))) {
        XBT_DEBUG("\t * Done : %p", action);
 -      action->model_obj->action_unref(action);
 +      surf_action_unref(action);
      }
  
 -  } while ((xbt_swag_size(surf_network_model->states.running_action_set) ||
 -            xbt_swag_size(surf_cpu_model_pm->states.running_action_set)) &&
 +  } while ((xbt_swag_size(surf_model_running_action_set((surf_model_t)surf_network_model)) ||
-             xbt_swag_size(surf_model_running_action_set((surf_model_t)surf_cpu_model))) &&
++            xbt_swag_size(surf_model_running_action_set((surf_model_t)surf_cpu_model_pm))) &&
             surf_solve(-1.0) >= 0.0);
  
    XBT_DEBUG("Simulation Terminated");