Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge with master and fix conflicts
authoralebre <adrien.lebre@inria.fr>
Thu, 21 Feb 2013 12:02:15 +0000 (13:02 +0100)
committeralebre <adrien.lebre@inria.fr>
Thu, 21 Feb 2013 12:02:15 +0000 (13:02 +0100)
20 files changed:
1  2 
buildtools/Cmake/DefinePackages.cmake
include/msg/datatypes.h
include/msg/msg.h
include/simgrid/simix.h
include/xbt/ex.h
src/include/surf/surf.h
src/msg/msg_private.h
src/msg/msg_vm.c
src/simgrid/sg_config.c
src/simix/smx_host.c
src/simix/smx_network.c
src/simix/smx_process.c
src/simix/smx_smurf_private.h
src/simix/smx_user.c
src/surf/storage.c
src/surf/surf.c
src/surf/surf_private.h
src/surf/workstation.c
src/surf/workstation_ptask_L07.c
src/xbt/ex.c

@@@ -216,7 -216,6 +216,7 @@@ set(SURF_SR
    src/surf/trace_mgr.c
    src/surf/workstation.c
    src/surf/workstation_ptask_L07.c
 +  src/surf/vm_workstation.c
    src/xbt/xbt_sg_stubs.c
    )
  
@@@ -234,7 -233,6 +234,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
@@@ -374,8 -372,10 +374,10 @@@ set(JTRACE_JAVA_SR
  
  if(HAVE_TRACING)
    list(APPEND JMSG_C_SRC ${JTRACE_C_SRC})
+   list(APPEND JMSG_JAVA_SRC ${JTRACE_JAVA_SRC})
  else()
    list(APPEND EXTRA_DIST ${JTRACE_C_SRC})
+   list(APPEND EXTRA_DIST ${JTRACE_JAVA_SRC})
  endif()
  
  set(LUA_SRC
@@@ -718,7 -718,9 +720,9 @@@ set(txt_file
    AUTHORS
    COPYING
    README
+   README.java
    ChangeLog
+   ChangeLog.SimGrid-java
    INSTALL
    LICENSE-LGPL-2.1
    NEWS
    )
  
  set(EXAMPLES_CMAKEFILES_TXT
+   examples/java/CMakeLists.txt
+   examples/java/async/CMakeLists.txt
    examples/java/bittorrent/CMakeLists.txt
+   examples/java/chord/CMakeLists.txt
+   examples/java/cloud/CMakeLists.txt
+   examples/java/commTime/CMakeLists.txt
+   examples/java/io/CMakeLists.txt
+   examples/java/kademlia/CMakeLists.txt
+   examples/java/master_slave_bypass/CMakeLists.txt
+   examples/java/master_slave_kill/CMakeLists.txt
+   examples/java/masterslave/CMakeLists.txt
+   examples/java/migration/CMakeLists.txt
+   examples/java/mutualExclusion/CMakeLists.txt
+   examples/java/pingPong/CMakeLists.txt
+   examples/java/priority/CMakeLists.txt
+   examples/java/startKillTime/CMakeLists.txt
+   examples/java/suspend/CMakeLists.txt
+   examples/java/tracing/CMakeLists.txt
    examples/lua/CMakeLists.txt
    examples/msg/CMakeLists.txt
    examples/msg/actions/CMakeLists.txt
@@@ -775,6 -794,7 +796,7 @@@ set(TESHSUITE_CMAKEFILES_TX
    teshsuite/simdag/network/p2p/CMakeLists.txt
    teshsuite/simdag/partask/CMakeLists.txt
    teshsuite/simdag/platforms/CMakeLists.txt
+   teshsuite/simdag/availability/CMakeLists.txt
    teshsuite/xbt/CMakeLists.txt
    teshsuite/smpi/CMakeLists.txt
    teshsuite/smpi/mpich-test/CMakeLists.txt
@@@ -809,6 -829,7 +831,7 @@@ set(CMAKE_SOURCE_FILE
    buildtools/Cmake/GenerateDocWin.cmake
    buildtools/Cmake/MaintainerMode.cmake
    buildtools/Cmake/MakeExe.cmake
+   buildtools/Cmake/MakeJava.cmake
    buildtools/Cmake/MakeLib.cmake
    buildtools/Cmake/MakeLibWin.cmake
    buildtools/Cmake/Modules/FindF2c.cmake
    buildtools/Cmake/Scripts/postinstall.sh
    buildtools/Cmake/Scripts/preinstall.sh
    buildtools/Cmake/Scripts/tesh.pl
-   buildtools/Cmake/Scripts/test_java.sh
    buildtools/Cmake/Scripts/update_tesh.pl
    buildtools/Cmake/Supernovae.cmake
    buildtools/Cmake/UnitTesting.cmake
    buildtools/Cmake/src/internal_config.h.in
    buildtools/Cmake/src/simgrid.nsi.in
    buildtools/Cmake/test_prog/prog_AC_CHECK_MCSC.c
-   buildtools/Cmake/test_prog/prog_getline.c
    buildtools/Cmake/test_prog/prog_gnu_dynlinker.c
    buildtools/Cmake/test_prog/prog_gtnets.cpp
    buildtools/Cmake/test_prog/prog_mutex_timedlock.c
diff --combined include/msg/datatypes.h
@@@ -46,13 -46,14 +46,13 @@@ 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;
  #ifdef MSG_USE_DEPRECATED
    msg_mailbox_t *mailboxes;     /**< the channels  */
  #endif
  } s_msg_host_priv_t, *msg_host_priv_t;
  
  static inline msg_host_priv_t MSG_host_priv(msg_host_t host){
-   return xbt_lib_get_level(host, MSG_HOST_LEVEL);
+   return (msg_host_priv_t )xbt_lib_get_level(host, MSG_HOST_LEVEL);
  }
  
  
@@@ -80,15 -81,23 +80,14 @@@ 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);
 +}
  
  /* ******************************** File ************************************ */
  typedef struct simdata_file *simdata_file_t;
  
diff --combined include/msg/msg.h
@@@ -43,16 -43,16 +43,16 @@@ XBT_PUBLIC(void) MSG_config(const char 
   *
   *  We allow to link against compiled versions that differ in the patch level.
   */
- #define MSG_init(argc,argv)  {                      \
-         int ver_major,ver_minor,ver_patch;              \
-         sg_version(&ver_major,&ver_minor,&ver_patch);   \
-         if ((ver_major != SIMGRID_VERSION_MAJOR) ||     \
-             (ver_minor != SIMGRID_VERSION_MINOR)) {     \
-           fprintf(stderr,"FATAL ERROR: Your program was compiled with SimGrid version %d.%d.%d, and then linked against SimGrid %d.%d.%d. Please fix this.\n", \
-               SIMGRID_VERSION_MAJOR,SIMGRID_VERSION_MINOR,SIMGRID_VERSION_PATCH,ver_major,ver_minor,ver_patch);                          \
-         }                                               \
-         MSG_init_nocheck(argc,argv);                    \
-       }
+ #define MSG_init(argc,argv)  {                                          \
+     int ver_major,ver_minor,ver_patch;                                  \
+     sg_version(&ver_major,&ver_minor,&ver_patch);                       \
+     if ((ver_major != SIMGRID_VERSION_MAJOR) ||                         \
+         (ver_minor != SIMGRID_VERSION_MINOR)) {                         \
+       fprintf(stderr,"FATAL ERROR: Your program was compiled with SimGrid version %d.%d.%d, and then linked against SimGrid %d.%d.%d. Please fix this.\n", \
+               SIMGRID_VERSION_MAJOR,SIMGRID_VERSION_MINOR,SIMGRID_VERSION_PATCH,ver_major,ver_minor,ver_patch); \
+     }                                                                   \
+     MSG_init_nocheck(argc,argv);                                        \
+   }
  
  XBT_PUBLIC(void) MSG_init_nocheck(int *argc, char **argv);
  XBT_PUBLIC(msg_error_t) MSG_main(void);
@@@ -195,6 -195,8 +195,8 @@@ XBT_PUBLIC(msg_error_t) MSG_task_destro
  
  XBT_PUBLIC(msg_error_t) MSG_task_receive_from_host(msg_task_t * task, const char *alias,
                                         msg_host_t host);
+ XBT_PUBLIC(msg_error_t) MSG_task_receive_from_host_bounded(msg_task_t * task, const char *alias,
+                                        msg_host_t host, double rate);
  
  XBT_PUBLIC(msg_error_t) MSG_task_execute(msg_task_t task);
  XBT_PUBLIC(msg_error_t) MSG_parallel_task_execute(msg_task_t task);
@@@ -206,7 -208,7 +208,7 @@@ XBT_PUBLIC(double) MSG_task_get_compute
  XBT_PUBLIC(void) MSG_task_set_compute_duration(msg_task_t task,
                                                 double compute_duration);
  XBT_PUBLIC(void) MSG_task_set_data_size(msg_task_t task,
-                                              double data_size);
+                                         double data_size);
  
  XBT_PUBLIC(double) MSG_task_get_remaining_computation(msg_task_t task);
  XBT_PUBLIC(double) MSG_task_get_remaining_communication(msg_task_t task);
@@@ -226,6 -228,20 +228,20 @@@ XBT_PUBLIC(msg_error_t
      MSG_task_receive(msg_task_t * task, const char *alias);
  #define MSG_task_recv(t,a) MSG_task_receive(t,a)
  
+ XBT_PUBLIC(msg_error_t)
+     MSG_task_receive_ext_bounded(msg_task_t * task, const char *alias, double timeout,
+                      msg_host_t host, double rate);
+ XBT_PUBLIC(msg_error_t)
+     MSG_task_receive_with_timeout_bounded(msg_task_t * task, const char *alias,
+                               double timeout, double rate);
+ XBT_PUBLIC(msg_error_t)
+     MSG_task_receive_bounded(msg_task_t * task, const char *alias,double rate);
+ #define MSG_task_recv_bounded(t,a,r) MSG_task_receive_bounded(t,a,r)
  XBT_PUBLIC(msg_comm_t) MSG_task_isend(msg_task_t task, const char *alias);
  XBT_PUBLIC(msg_comm_t) MSG_task_isend_bounded(msg_task_t task, const char *alias, double maxrate);
  XBT_PUBLIC(msg_comm_t) MSG_task_isend_with_matching(msg_task_t task,
  XBT_PUBLIC(void) MSG_task_dsend(msg_task_t task, const char *alias, void_f_pvoid_t cleanup);
  XBT_PUBLIC(void) MSG_task_dsend_bounded(msg_task_t task, const char *alias, void_f_pvoid_t cleanup, double maxrate);
  XBT_PUBLIC(msg_comm_t) MSG_task_irecv(msg_task_t * task, const char *alias);
+ XBT_PUBLIC(msg_comm_t) MSG_task_irecv_bounded(msg_task_t * task, const char *alias, double rate);
  XBT_PUBLIC(int) MSG_comm_test(msg_comm_t comm);
  XBT_PUBLIC(int) MSG_comm_testany(xbt_dynar_t comms);
  XBT_PUBLIC(void) MSG_comm_destroy(msg_comm_t comm);
@@@ -254,7 -271,7 +271,7 @@@ XBT_PUBLIC(int) MSG_task_listen_from_ho
  XBT_PUBLIC(msg_error_t)
      MSG_task_send_with_timeout(msg_task_t task, const char *alias,
                             double timeout);
-     
  XBT_PUBLIC(msg_error_t)
      MSG_task_send_with_timeout_bounded(msg_task_t task, const char *alias,
                             double timeout, double maxrate);
@@@ -275,6 -292,10 +292,10 @@@ XBT_PUBLIC(msg_error_t
      MSG_mailbox_get_task_ext(msg_mailbox_t mailbox, msg_task_t * task,
                           msg_host_t host, double timeout);
  
+ XBT_PUBLIC(msg_error_t)
+     MSG_mailbox_get_task_ext_bounded(msg_mailbox_t mailbox, msg_task_t *task,
+                                      msg_host_t host, double timeout, double rate);
  XBT_PUBLIC(msg_error_t)
      MSG_mailbox_put_with_timeout(msg_mailbox_t mailbox, msg_task_t task,
                               double timeout);
@@@ -341,36 -362,29 +362,36 @@@ XBT_PUBLIC(int) MSG_get_channel_number(
   *
   */
  /* This function should not be called directly, but rather from MSG_vm_start_from_template that does not exist yet*/
 -XBT_PUBLIC(msg_vm_t) MSG_vm_start(msg_host_t location, const char *name, int coreAmount);
 +
 +// TODO add VDI later
 +XBT_PUBLIC(msg_vm_t) MSG_vm_create_core(msg_host_t location, const char *name);
 +XBT_PUBLIC(msg_vm_t) MSG_vm_create(msg_host_t ind_pm, const char *name,
 +    int core_nb, int mem_cap, int net_cap, char *disk_path, int disk_size);
 +
 +XBT_PUBLIC(void) MSG_vm_start(msg_vm_t);
  
  XBT_PUBLIC(int) MSG_vm_is_suspended(msg_vm_t);
  XBT_PUBLIC(int) MSG_vm_is_running(msg_vm_t);
  
 -XBT_PUBLIC(void) MSG_vm_bind(msg_vm_t vm, msg_process_t process);
 -XBT_PUBLIC(void) MSG_vm_unbind(msg_vm_t vm, msg_process_t process); // simple wrapper over process_kill
 +XBT_PUBLIC(const char*) MSG_vm_get_name(msg_vm_t);
  
  XBT_PUBLIC(void) MSG_vm_migrate(msg_vm_t vm, msg_host_t destination);
  
 +/* Suspend the execution of the VM, but keep its state on memory. */
  XBT_PUBLIC(void) MSG_vm_suspend(msg_vm_t vm);
 -  // \forall p in VM, MSG_process_suspend(p) // Freeze the processes
 -
 -XBT_PUBLIC(void) MSG_vm_resume(msg_vm_t vm);  // Simulate the fact of reading the processes from disk and resuming them
 -  // \forall p in VM, MSG_process_resume(p) // unfreeze them
 +XBT_PUBLIC(void) MSG_vm_resume(msg_vm_t vm);
  
 -XBT_PUBLIC(void) MSG_vm_shutdown(msg_vm_t vm); // killall
 +/* Save the VM state to a disk. */
 +XBT_PUBLIC(void) MSG_vm_save(msg_vm_t vm);
 +XBT_PUBLIC(void) MSG_vm_restore(msg_vm_t vm);
  
 -XBT_PUBLIC(void) MSG_vm_reboot(msg_vm_t vm);
 +/* Shutdown the guest operating system. */
 +XBT_PUBLIC(void) MSG_vm_shutdown(msg_vm_t vm);
  
  XBT_PUBLIC(void) MSG_vm_destroy(msg_vm_t vm);
  
 -XBT_PUBLIC(xbt_dynar_t) MSG_vms_as_dynar(void);
 +/* TODO: do we need this? */
 +// XBT_PUBLIC(xbt_dynar_t) MSG_vms_as_dynar(void);
  
  /*
  void* MSG_process_get_property(msg_process_t, char* key)
diff --combined include/simgrid/simix.h
@@@ -167,12 -167,6 +167,6 @@@ extern char* smx_context_factory_name
  extern int smx_context_stack_size;
  extern int smx_context_stack_size_was_set;
  
- #ifdef HAVE_THREAD_LOCAL_STORAGE
- extern __thread smx_context_t smx_current_context;
- #else
- extern smx_context_t smx_current_context;
- #endif
  /* *********************** */
  /* Context type definition */
  /* *********************** */
@@@ -283,7 -277,6 +277,6 @@@ XBT_PUBLIC(void) SIMIX_process_on_exit(
  XBT_PUBLIC(void) SIMIX_comm_set_copy_data_callback(void (*callback) (smx_action_t, void*, size_t));
  XBT_PUBLIC(void) SIMIX_comm_copy_pointer_callback(smx_action_t comm, void* buff, size_t buff_size);
  XBT_PUBLIC(void) SIMIX_comm_copy_buffer_callback(smx_action_t comm, void* buff, size_t buff_size);
- XBT_PUBLIC(void) smpi_comm_copy_data_callback(smx_action_t comm, void* buff, size_t buff_size);
  
  XBT_PUBLIC(smx_action_t) SIMIX_comm_get_send_match(smx_rdv_t rdv, int (*match_fun)(void*, void*), void* data);
  XBT_PUBLIC(int) SIMIX_comm_has_send_match(smx_rdv_t rdv, int (*match_fun)(void*, void*), void* data);
@@@ -299,7 -292,6 +292,6 @@@ XBT_PUBLIC(void) SIMIX_comm_finish(smx_
  
  /******************************* Host simcalls ********************************/
  /* TODO use handlers and keep smx_host_t hidden from higher levels */
- XBT_PUBLIC(xbt_dict_t) simcall_host_get_dict(void);
  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);
@@@ -328,16 -320,6 +320,16 @@@ XBT_PUBLIC(e_smx_state_t) simcall_host_
  XBT_PUBLIC(void) simcall_host_execution_set_priority(smx_action_t execution, double priority);
  XBT_PUBLIC(e_smx_state_t) simcall_host_execution_wait(smx_action_t execution);
  
 +/******************************* 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(const char*) simcall_vm_get_phys_host(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 */
@@@ -416,6 -398,16 +408,16 @@@ XBT_PUBLIC(smx_action_t) simcall_comm_i
                                                int (*match_fun)(void *, void *, smx_action_t),
                                                void *data);
  
+ XBT_PUBLIC(void) simcall_comm_recv_bounded(smx_rdv_t rdv, void *dst_buff,
+                                      size_t * dst_buff_size,
+                                      int (*match_fun)(void *, void *, smx_action_t),
+                                      void *data, double timeout, double rate);
+ XBT_PUBLIC(smx_action_t) simcall_comm_irecv_bounded(smx_rdv_t rdv, void *dst_buff,
+                                               size_t * dst_buff_size,
+                                               int (*match_fun)(void *, void *, smx_action_t),
+                                               void *data, double rate);
  XBT_PUBLIC(void) simcall_comm_destroy(smx_action_t comm);
  XBT_PUBLIC(smx_action_t) simcall_comm_iprobe(smx_rdv_t rdv, int src, int tag,
                                  int (*match_fun)(void *, void *, smx_action_t), void *data);
@@@ -464,13 -456,10 +466,10 @@@ XBT_PUBLIC(void) simcall_cond_broadcast
  XBT_PUBLIC(smx_sem_t) simcall_sem_init(int capacity);
  XBT_PUBLIC(void) simcall_sem_destroy(smx_sem_t sem);
  XBT_PUBLIC(void) simcall_sem_release(smx_sem_t sem);
- XBT_PUBLIC(void) simcall_sem_release_forever(smx_sem_t sem);
  XBT_PUBLIC(int) simcall_sem_would_block(smx_sem_t sem);
- XBT_PUBLIC(void) simcall_sem_block_onto(smx_sem_t sem);
  XBT_PUBLIC(void) simcall_sem_acquire(smx_sem_t sem);
  XBT_PUBLIC(void) simcall_sem_acquire_timeout(smx_sem_t sem,
                                             double max_duration);
- XBT_PUBLIC(unsigned int) simcall_sem_acquire_any(xbt_dynar_t sems);
  XBT_PUBLIC(int) simcall_sem_get_capacity(smx_sem_t sem);
  
  XBT_PUBLIC(double) simcall_file_read(void* ptr, size_t size, size_t nmemb, smx_file_t stream);
diff --combined include/xbt/ex.h
@@@ -262,8 -262,7 +262,8 @@@ typedef enum 
    thread_error,                 /**< error while [un]locking */
    host_error,                   /**< host failed */
    tracing_error,                /**< error during the simulation tracing */
 -  io_error                      /**< disk or file error */
 +  io_error,                      /**< disk or file error */
 +  vm_error                      /**< vm  error */
  } xbt_errcat_t;
  
  XBT_PUBLIC(const char *) xbt_ex_catname(xbt_errcat_t cat);
@@@ -477,7 -476,7 +477,7 @@@ XBT_PUBLIC(void) xbt_ex_free(xbt_ex_t e
  /** @brief Shows a backtrace of the current location */
  XBT_PUBLIC(void) xbt_backtrace_display_current(void);
  /** @brief reimplementation of glibc backtrace based directly on gcc library, without implicit malloc  */
- XBT_PUBLIC(int)xbt_backtrace_no_malloc(void**bt, int size);
+ XBT_PUBLIC(int) xbt_backtrace_no_malloc(void**bt, int size);
  /** @brief Captures a backtrace for further use */
  XBT_PUBLIC(void) xbt_backtrace_current(xbt_ex_t * e);
  /** @brief Display a previously captured backtrace */
diff --combined src/include/surf/surf.h
@@@ -29,7 -29,6 +29,6 @@@ extern double sg_sender_gap
  extern double sg_latency_factor;
  extern double sg_bandwidth_factor;
  extern double sg_weight_S_parameter;
- extern int sg_maxmin_selective_update;
  extern int sg_network_crosstraffic;
  #ifdef HAVE_GTNETS
  extern double sg_gtnets_jitter;
@@@ -81,13 -80,6 +80,13 @@@ enum heap_action_type
    NOTSET
  };
  
 +
 +typedef struct surf_resource {
 +  surf_model_t model;
 +  char *name;
 +  xbt_dict_t properties;
 +} s_surf_resource_t, *surf_resource_t;
 +
  /** \ingroup SURF_actions
   *  \brief Action structure
   *
@@@ -114,12 -106,7 +113,12 @@@ typedef struct surf_action 
           * and fluctuates until the task is completed */
    void *data;                   /**< for your convenience */
    int refcount;
 -  surf_model_t model_type;
 +
 +  /* 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
@@@ -249,15 -236,12 +248,15 @@@ typedef struct surf_storage_model_exten
    surf_action_t(*ls) (void *storage, const char *path);
  } s_surf_model_extension_storage_t;
  
 -     /** \ingroup SURF_models
 -      *  \brief Workstation model extension public
 -      *
 -      *  Public functions specific to the workstation model.
 -      */
 +/** \ingroup SURF_models
 + *  \brief Workstation model extension public
 + *
 + *  Public functions specific to the workstation model.
 + */
  typedef struct surf_workstation_model_extension_public {
 +  /* This points to the surf cpu model object bound to the workstation model. */
 +  surf_model_t cpu_model;
 +
    surf_action_t(*execute) (void *workstation, double size);                                /**< Execute a computation amount on a workstation
                                        and create the corresponding action */
    surf_action_t(*sleep) (void *workstation, double duration);                              /**< Make a workstation sleep during a given duration */
  
  } 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;
 +
 +  void (*create) (const char *name, void *ind_phys_workstation); // First operation of the VM model
 +  // start does not appear here as it corresponds to turn the state from created to running (see smx_vm.c)
 +  int (*get_state) (void *ind_vm_workstation);
 +  void (*set_state) (void *ind_vms_workstation, int state);
 +  void (*migrate) (void *ind_vm_workstation, void *ind_dest_phys_workstation); // will be vm_ws_migrate()
 +  const char * (*get_phys_host) (void *ind_vm_workstation); // will be vm_ws_get_phys_host()
 +  void (*destroy) (void *ind_vm_workstation); // will be vm_ws_destroy(), which destroies the vm-workstation-specific data
 +} s_surf_model_extension_vm_workstation_t;
  
 -
 +/** \ingroup SURF_models
 + *  \brief Model types
 + *
 + *  The type of the model object. For example, we will have two model objects
 + *  of the surf cpu model. One is for physical machines, and the other is for
 + *  virtual machines.
 + *
 + */
 +typedef enum {
 +  SURF_MODEL_TYPE_CPU = 0,
 +  SURF_MODEL_TYPE_NETWORK,
 +  SURF_MODEL_TYPE_STORAGE,
 +  SURF_MODEL_TYPE_WORKSTATION,
 +  SURF_MODEL_TYPE_VM_WORKSTATION,
 +  SURF_MODEL_TYPE_NEW_MODEL
 +} e_surf_model_type_t;
  
  /** \ingroup SURF_models
   *  \brief Model datatype
@@@ -337,9 -288,7 +336,9 @@@ 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_action_state_t(*action_state_get) (surf_action_t action);
 +  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);
      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;
@@@ -405,14 -352,11 +404,14 @@@ 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;
 -} s_surf_resource_t, *surf_resource_t;
 +static inline surf_model_t surf_resource_model(const void *host, int level) {
 +  /* If level is SURF_WKS_LEVEL, ws is a workstation_CLM03 object. It has
 +   * surf_resource at the generic_resource field. */
 +  surf_resource_t ws = xbt_lib_get_level((void *) host, level);
 +  return ws->model;
 +}
 +
 +
  
  /**
   * Resource which have a metric handled by a maxmin system
@@@ -437,14 -381,9 +436,14 @@@ typedef struct surf_resource_lmm 
  
  
  /** \ingroup SURF_models
 - *  \brief The CPU model
 + *  \brief The CPU model object for the physical machine layer
   */
 -XBT_PUBLIC_DATA(surf_model_t) surf_cpu_model;
 +XBT_PUBLIC_DATA(surf_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;
  
  /** \ingroup SURF_models
   *  \brief Initializes the CPU model with the model Cas01
   *  You can change this behavior by setting the cpu/optim configuration
   *  variable to a different value.
   *
-  *  This function is called by surf_workstation_model_init_CLM03
-  *  so you shouldn't have to call it by yourself.
-  *
-  *  \see surf_workstation_model_init_CLM03()
+  *  You shouldn't have to call it by yourself.
   */
  XBT_PUBLIC(void) surf_cpu_model_init_Cas01(void);
  
   *  \brief Initializes the CPU model with trace integration [Deprecated]
   *
   *  You shouldn't have to call it by yourself.
-  *  \see surf_workstation_model_init_CLM03()
   */
 -XBT_PUBLIC(void) surf_cpu_model_init_ti(void);
 +XBT_PUBLIC(surf_model_t) surf_cpu_model_init_ti(void);
  
- /** \brief This function call the share resources function needed
-  *
-  */
- XBT_PUBLIC(double) generic_share_resources(double now);
- /** \brief This function call the update action state function needed
-  *
-  */
- XBT_PUBLIC(void)   generic_update_actions_state(double now, double delta);
  /** \ingroup SURF_models
   *  \brief The list of all available optimization modes (both for cpu and networks).
   *  These optimization modes can be set using --cfg=cpu/optim:... and --cfg=network/optim:...
@@@ -490,8 -415,6 +475,6 @@@ XBT_PUBLIC_DATA(s_surf_model_descriptio
   */
  XBT_PUBLIC_DATA(s_surf_model_description_t) surf_cpu_model_description[];
  
- XBT_PUBLIC(void) create_workstations(void);
  /**\brief create new host bypass the parser
   *
   */
@@@ -546,21 -469,12 +529,12 @@@ XBT_PUBLIC(void) surf_network_model_ini
  /** \ingroup SURF_models
   *  \brief Initializes the platform with the network model CM02
   *
-  *  This function is called by surf_workstation_model_init_CLM03
-  *  or by yourself only if you plan using surf_workstation_model_init_compound
+  *  You sould call this function by yourself only if you plan using
+  *  surf_workstation_model_init_compound.
   *  See comments in the code for more information.
-  *
-  *  \see surf_workstation_model_init_CLM03()
   */
  XBT_PUBLIC(void) surf_network_model_init_CM02(void);
  
- /**
-  * brief initialize the the network model bypassing the XML parser
-  */
- XBT_PUBLIC(void) surf_network_model_init_bypass(const char *id,
-                                                 double initial_bw,
-                                                 double initial_lat);
  #ifdef HAVE_GTNETS
  /** \ingroup SURF_models
   *  \brief Initializes the platform with the network model GTNETS
@@@ -660,16 -574,6 +634,16 @@@ XBT_PUBLIC_DATA(s_surf_model_descriptio
   */
  XBT_PUBLIC_DATA(surf_model_t) surf_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_model_t) surf_vm_workstation_model;
 +
  /** \ingroup SURF_models
   *  \brief Initializes the platform with a compound workstation model
   *
@@@ -691,18 -595,6 +665,6 @@@ XBT_PUBLIC(void) surf_workstation_model
   */
  XBT_PUBLIC(void) surf_workstation_model_init_current_default(void);
  
- /** \ingroup SURF_models
-  *  \brief Initializes the platform with the workstation model CLM03
-  *
-  *  This platform model seperates the workstation model and the network model.
-  *  The workstation model will be initialized with the model CLM03, the network
-  *  model with the model CM02 and the CPU model with the model Cas01.
-  *  In future releases, some other network models will be implemented and will be
-  *  combined with the workstation model CLM03.
-  *
-  */
- XBT_PUBLIC(void) surf_workstation_model_init_CLM03(void);
  /** \ingroup SURF_models
   *  \brief Initializes the platform with the model KCCFLN05
   *
@@@ -730,7 -622,6 +692,7 @@@ XBT_PUBLIC_DATA(s_surf_model_descriptio
   *  \brief List of initialized models
   */
  XBT_PUBLIC_DATA(xbt_dynar_t) model_list;
 +XBT_PUBLIC_DATA(xbt_dynar_t) model_list_invoke;
  
  /*******************************************/
  /*** SURF Globals **************************/
   *  This function has to be called to initialize the common
   *  structures.  Then you will have to create the environment by
   *  calling 
-  *  e.g. surf_workstation_model_init_CLM03()
+  *  e.g. surf_workstation_model_init_CM02()
   *
-  *  \see surf_workstation_model_init_CLM03(), surf_workstation_model_init_compound(), surf_exit()
+  *  \see surf_workstation_model_init_CM02(), surf_workstation_model_init_compound(), surf_exit()
   */
  XBT_PUBLIC(void) surf_init(int *argc, char **argv);     /* initialize common structures */
  
@@@ -788,14 -679,10 +750,10 @@@ XBT_PUBLIC(void) surf_exit(void)
  
  /* Prototypes of the functions that handle the properties */
  XBT_PUBLIC_DATA(xbt_dict_t) current_property_set;       /* the prop set for the currently parsed element (also used in SIMIX) */
- XBT_PUBLIC(void) parse_properties(void);
  
  /* surf parse file related (public because called from a test suite) */
  XBT_PUBLIC(void) parse_platform_file(const char *file);
  
- /* Stores the sets */
- XBT_PUBLIC_DATA(xbt_dict_t) set_list;
  /* 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;
diff --combined src/msg/msg_private.h
@@@ -68,6 -68,8 +68,6 @@@ typedef struct simdata_process 
    int argc;                     /* arguments number if any */
    msg_error_t last_errno;       /* the last value returned by a MSG_function */
  
 -  msg_vm_t vm;                 /* virtual machine the process is in */
 -
    void* data;                   /* user data */
  } s_simdata_process_t, *simdata_process_t;
  
@@@ -87,8 -89,21 +87,8 @@@ typedef struct msg_comm 
    msg_task_t *task_received;      /* where the task will be received (NULL for the sender) */
    msg_error_t status;           /* status of the communication once finished */
  } s_msg_comm_t;
 -/*
 -typedef enum {
 -  msg_vm_state_suspended, msg_vm_state_running, msg_vm_state_migrating
 -} e_msg_vm_state_t;
  
 -typedef struct msg_vm {
 -  const 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;
 -*/
 +
  /************************** Global variables ********************************/
  typedef struct MSG_Global {
    xbt_fifo_t host;
    unsigned long int sent_msg;   /* Total amount of messages sent during the simulation */
    void (*task_copy_callback) (msg_task_t task, msg_process_t src, msg_process_t dst);
    void_f_pvoid_t process_data_cleanup;
 -  xbt_swag_t vms;
  } s_MSG_Global_t, *MSG_Global_t;
  
  /*extern MSG_Global_t msg_global;*/
@@@ -122,8 -138,6 +122,6 @@@ XBT_PUBLIC_DATA(MSG_Global_t) msg_globa
  msg_host_t __MSG_host_create(smx_host_t workstation);
  void __MSG_host_destroy(msg_host_priv_t host);
  
- void __MSG_display_process_status(void);
  void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc);
  void MSG_process_create_from_SIMIX(smx_process_t *process, const char *name,
                                     xbt_main_func_t code, void *data,
@@@ -163,16 -177,16 +161,16 @@@ void TRACE_msg_process_sleep_out(msg_pr
  void TRACE_msg_process_end(msg_process_t process);
  
  /* declaration of instrumentation functions from instr_msg_vm.c */
 -char *instr_vm_id (msg_vm_t vm, char *str, int len);
 -char *instr_vm_id_2 (const char *vm_name, char *str, int len);
 +char *instr_vm_id(msg_vm_t vm, char *str, int len);
 +char *instr_vm_id_2(const char *vm_name, char *str, int len);
  void TRACE_msg_vm_change_host(msg_vm_t vm, msg_host_t old_host,
                                     msg_host_t new_host);
 -void TRACE_msg_vm_create (const char *vm_name, msg_host_t host);
 +void TRACE_msg_vm_create(const char *vm_name, msg_host_t host);
  void TRACE_msg_vm_kill(msg_vm_t process);
  void TRACE_msg_vm_suspend(msg_vm_t vm);
  void TRACE_msg_vm_resume(msg_vm_t vm);
 -void TRACE_msg_vm_sleep_in(msg_vm_t vm);
 -void TRACE_msg_vm_sleep_out(msg_vm_t vm);
 +void TRACE_msg_vm_save(msg_vm_t vm);
 +void TRACE_msg_vm_restore(msg_vm_t vm);
  void TRACE_msg_vm_end(msg_vm_t vm);
  
  SG_END_DECL()
diff --combined src/msg/msg_vm.c
@@@ -3,20 -3,6 +3,20 @@@
  /* 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. */
  
 +// QUESTIONS:
 +// 1./ check how and where a new VM is added to the list of the hosts
 +// 2./ Diff between SIMIX_Actions and SURF_Actions
 +// => SIMIX_actions : point synchro entre processus de niveau (theoretically speaking I do not have to create such SIMIX_ACTION
 +// =>  Surf_Actions
 +
 +// TODO
 +//    MSG_TRACE can be revisited in order to use  the host
 +//    To implement a mixed model between workstation and vm_workstation,
 +//     please give a look at surf_model_private_t model_private at SURF Level and to the share resource functions
 +//     double (*share_resources) (double now);
 +//    For the action into the vm workstation model, we should be able to leverage the usual one (and if needed, look at
 +//            the workstation model.
 +
  #include "msg_private.h"
  #include "xbt/sysdep.h"
  #include "xbt/log.h"
  XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_vm, msg,
                                  "Cloud-oriented parts of the MSG API");
  
 -/** @brief Create a new (empty) VMs.
 - *  @ingroup msg_VMs
 +
 +/* **** ******** GENERAL ********* **** */
 +
 +/** \ingroup m_vm_management
 + * \brief Returns the value of a given vm property
   *
 - *  @bug it is expected that in the future, the coreAmount parameter will be used
 - *  to add extra constraints on the execution, but the argument is ignored for now.
 + * \param vm a vm
 + * \param name a property name
 + * \return value of a property (or NULL if property not set)
   */
  
 -msg_vm_t MSG_vm_start(msg_host_t location, const char *name, int coreAmount) {
 -  msg_vm_t res = xbt_new0(s_msg_vm_t,1);
 -  res->all_vms_hookup.prev = NULL;
 -  res->host_vms_hookup.prev = NULL;
 -  res->state = msg_vm_state_running;
 -  res->location = location;
 -  res->coreAmount = coreAmount;
 -  res->name = xbt_strdup(name);
 -  res->processes = xbt_dynar_new(sizeof(msg_process_t),NULL);
 +const char *MSG_vm_get_property_value(msg_vm_t vm, const char *name)
 +{
 +  return MSG_host_get_property_value(vm, name);
 +}
  
 -  xbt_swag_insert(res,msg_global->vms);
 -  xbt_swag_insert(res, MSG_host_priv(location)->vms);
 +/** \ingroup m_vm_management
 + * \brief Returns a xbt_dict_t consisting of the list of properties assigned to this host
 + *
 + * \param vm a vm
 + * \return a dict containing the properties
 + */
 +xbt_dict_t MSG_vm_get_properties(msg_vm_t vm)
 +{
 +  xbt_assert((vm != NULL), "Invalid parameters (vm is NULL)");
  
 -  #ifdef HAVE_TRACING
 -  TRACE_msg_vm_create(name, location);
 -  #endif
 +  return (simcall_host_get_properties(vm));
 +}
  
 +/** \ingroup m_host_management
 + * \brief Change the value of a given host property
 + *
 + * \param host a host
 + * \param name a property name
 + * \param value what to change the property to
 + * \param free_ctn the freeing function to use to kill the value on need
 + */
 +void MSG_vm_set_property_value(msg_vm_t vm, const char *name, void *value,void_f_pvoid_t free_ctn) {
  
 -  return res;
 +  xbt_dict_set(MSG_host_get_properties(vm), name, value,free_ctn);
  }
 -/** @brief Returns a newly constructed dynar containing all existing VMs in the system.
 - *  @ingroup msg_VMs
 +
 +/** \ingroup msg_vm_management
 + * \brief Finds a msg_vm_t using its name.
   *
 - * Don't forget to free the dynar after use.
 + * This is a name directory service
 + * \param name the name of a vm.
 + * \return the corresponding vm
 + *
 + * Please note that a VM is a specific host. Hence, you should give a different name
 + * for each VM/PM.
   */
 -xbt_dynar_t MSG_vms_as_dynar(void) {
 -  xbt_dynar_t res = xbt_dynar_new(sizeof(msg_vm_t),NULL);
 -  msg_vm_t vm;
 -  xbt_swag_foreach(vm,msg_global->vms) {
 -    xbt_dynar_push(res,&vm);
 -  }
 -  return res;
 +
 +msg_vm_t MSG_vm_get_by_name(const char *name){
 +      return MSG_get_host_by_name(name);
  }
  
 -/** @brief Returns whether the given VM is currently suspended
 +/** \ingroup m_vm_management
 + *
 + * \brief Return the name of the #msg_host_t.
 + *
 + * This functions checks whether \a host is a valid pointer or not and return
 +   its name.
 + */
 +const char *MSG_vm_get_name(msg_vm_t vm) {
 +  return MSG_host_get_name(vm);
 +}
 +
 +
 +/* **** Check state of a VM **** */
 +static inline int __MSG_vm_is_state(msg_vm_t vm, e_surf_vm_state_t state) {
 +  return simcall_vm_get_state(vm) == state;
 +}
 +
 +/** @brief Returns whether the given VM has just reated, not running.
   *  @ingroup msg_VMs
   */
 -int MSG_vm_is_suspended(msg_vm_t vm) {
 -  return vm->state == msg_vm_state_suspended;
 +int MSG_vm_is_created(msg_vm_t vm)
 +{
 +  return __MSG_vm_is_state(vm, SURF_VM_STATE_CREATED);
  }
 +
  /** @brief Returns whether the given VM is currently running
   *  @ingroup msg_VMs
   */
 -int MSG_vm_is_running(msg_vm_t vm) {
 -  return vm->state == msg_vm_state_running;
 +int MSG_vm_is_running(msg_vm_t vm)
 +{
 +  return __MSG_vm_is_state(vm, SURF_VM_STATE_RUNNING);
 +}
 +
 +/** @brief Returns whether the given VM is currently migrating
 + *  @ingroup msg_VMs
 + */
 +int MSG_vm_is_migrating(msg_vm_t vm)
 +{
 +  return __MSG_vm_is_state(vm, SURF_VM_STATE_MIGRATING);
 +}
 +
 +/** @brief Returns whether the given VM is currently suspended, not running.
 + *  @ingroup msg_VMs
 + */
 +int MSG_vm_is_suspended(msg_vm_t vm)
 +{
 +  return __MSG_vm_is_state(vm, SURF_VM_STATE_SUSPENDED);
 +}
 +
 +/** @brief Returns whether the given VM is being saved (FIXME: live saving or not?).
 + *  @ingroup msg_VMs
 + */
 +int MSG_vm_is_saving(msg_vm_t vm)
 +{
 +  return __MSG_vm_is_state(vm, SURF_VM_STATE_SAVING);
 +}
 +
 +/** @brief Returns whether the given VM has been saved, not running.
 + *  @ingroup msg_VMs
 + */
 +int MSG_vm_is_saved(msg_vm_t vm)
 +{
 +  return __MSG_vm_is_state(vm, SURF_VM_STATE_SAVED);
  }
 -/** @brief Add the given process into the VM.
 +
 +/** @brief Returns whether the given VM is being restored, not running.
   *  @ingroup msg_VMs
 + */
 +int MSG_vm_is_restoring(msg_vm_t vm)
 +{
 +  return __MSG_vm_is_state(vm, SURF_VM_STATE_RESTORING);
 +}
 +
 +
 +
 +/* ------------------------------------------------------------------------- */
 +/* ------------------------------------------------------------------------- */
 +
 +/* **** ******** MSG vm actions ********* **** */
 +
 +/** @brief Create a new VM with specified parameters.
 + *  @ingroup msg_VMs*
   *
 - * Afterward, when the VM is migrated or suspended or whatever, the process will have the corresponding handling, too.
 + */
 +msg_vm_t MSG_vm_create(msg_host_t ind_pm, const char *name,
 +                                           int core_nb, int mem_cap, int net_cap, char *disk_path, int disk_size)
 +{
 +  msg_vm_t vm = MSG_vm_create_core(ind_pm, name);
 +
 +  MSG_vm_set_property_value(vm, "CORE_NB", bprintf("%d", core_nb), free);
 +  MSG_vm_set_property_value(vm, "MEM_CAP", bprintf("%d", mem_cap), free);
 +  MSG_vm_set_property_value(vm, "NET_CAP", bprintf("%d", net_cap), free);
 +
 +  /* TODO: We will revisit the disk support later. */
 +
 +  return vm;
 +}
 +
 +
 +/** @brief Create a new VM object. The VM is not yet started. The resource of the VM is allocated upon MSG_vm_start().
 + *  @ingroup msg_VMs*
   *
 + * A VM is treated as a host. The name of the VM must be unique among all hosts.
   */
 -void MSG_vm_bind(msg_vm_t vm, msg_process_t process) {
 -  /* check if the process is already in a VM */
 -  simdata_process_t simdata = simcall_process_get_data(process);
 -  if (simdata->vm) {
 -    msg_vm_t old_vm = simdata->vm;
 -    int pos = xbt_dynar_search(old_vm->processes,&process);
 -    xbt_dynar_remove_at(old_vm->processes,pos, NULL);
 -  }
 -  /* check if the host is in the right host */
 -  if (simdata->m_host != vm->location) {
 -    MSG_process_migrate(process,vm->location);
 +msg_vm_t MSG_vm_create_core(msg_host_t ind_pm, const char *name)
 +{
 +  /* make sure the VM of the same name does not exit */
 +  {
 +    void *ind_host_tmp = xbt_lib_get_elm_or_null(host_lib, name);
 +    if (ind_host_tmp) {
 +      XBT_ERROR("host %s already exits", name);
 +      return NULL;
 +    }
    }
 -  simdata->vm = vm;
  
 -  XBT_DEBUG("binding Process %s to %p",MSG_process_get_name(process),vm);
 +  /* Note: ind_vm and vm_workstation point to the same elm object. */
 +  msg_vm_t ind_vm = NULL;
 +  void *ind_vm_workstation =  NULL;
 +
 +  // Ask simix to create the surf vm resource
 +  ind_vm_workstation = simcall_vm_create(name, ind_pm);
 +  ind_vm = (msg_vm_t) __MSG_host_create(ind_vm_workstation);
 +
 +  XBT_DEBUG("A new VM (%s) has been created", name);
 +
 +  #ifdef HAVE_TRACING
 +  TRACE_msg_vm_create(name, ind_pm);
 +  #endif
 +
 +  return ind_vm;
 +}
  
 -  xbt_dynar_push_as(vm->processes,msg_process_t,process);
 +
 +/** @brief Start a vm (ie. boot)
 + *  @ingroup msg_VMs
 + *
 + *  If the VM cannot be started, an exception is generated.
 + *
 + */
 +void MSG_vm_start(msg_vm_t vm)
 +{
 +  //Please note that vm start can raise an exception if the VM cannot be started.
 +  simcall_vm_start(vm);
 +
 +  #ifdef HAVE_TRACING
 +  TRACE_msg_vm_start(vm);
 +  #endif
  }
 -/** @brief Removes the given process from the given VM, and kill it
 +
 +
 +
 +/** @brief Immediately kills all processes within the given VM. Any memory that they allocated will be leaked.
   *  @ingroup msg_VMs
   *
 - *  Will raise a not_found exception if the process were not bound to that VM
 + * FIXME: No extra delay occurs. If you want to simulate this too, you want to
 + * use a #MSG_process_sleep() or something. I'm not quite sure.
   */
 -void MSG_vm_unbind(msg_vm_t vm, msg_process_t process) {
 -  int pos = xbt_dynar_search(vm->processes,process);
 -  xbt_dynar_remove_at(vm->processes,pos, NULL);
 -  MSG_process_kill(process);
 +void MSG_vm_shutdown(msg_vm_t vm)
 +{
 +  /* msg_vm_t equals to msg_host_t */
 +  simcall_vm_shutdown(vm);
 +
 +  // #ifdef HAVE_TRACING
 +  // TRACE_msg_vm_(vm);
 +  // #endif
  }
  
 -/** @brief Immediately change the host on which all processes are running.
 +
 +/** @brief Migrate the VM to the given host.
   *  @ingroup msg_VMs
   *
 - * No migration cost occurs. If you want to simulate this too, you want to use a
 + * FIXME: No migration cost occurs. If you want to simulate this too, you want to use a
   * MSG_task_send() before or after, depending on whether you want to do cold or hot
   * migration.
   */
 -void MSG_vm_migrate(msg_vm_t vm, msg_host_t destination) {
 -  unsigned int cpt;
 -  msg_process_t process;
 -  xbt_dynar_foreach(vm->processes,cpt,process) {
 -    MSG_process_migrate(process,destination);
 -  }
 -  xbt_swag_remove(vm, MSG_host_priv(vm->location)->vms);
 -  xbt_swag_insert_at_tail(vm, MSG_host_priv(destination)->vms);
 -  
 +void MSG_vm_migrate(msg_vm_t vm, msg_host_t destination)
 +{
 +  /* some thoughts:
 +   * - One approach is ...
 +   *   We first create a new VM (i.e., destination VM) on the destination
 +   *   physical host. The destination VM will receive the state of the source
 +   *   VM over network. We will finally destroy the source VM.
 +   *   - This behavior is similar to the way of migration in the real world.
 +   *     Even before a migration is completed, we will see a destination VM,
 +   *     consuming resources.
 +   *   - We have to relocate all processes. The existing process migraion code
 +   *     will work for this?
 +   *   - The name of the VM is a somewhat unique ID in the code. It is tricky
 +   *     for the destination VM?
 +   *
 +   * - Another one is ...
 +   *   We update the information of the given VM to place it to the destination
 +   *   physical host.
 +   *
 +   * The second one would be easier.
 +   *   
 +   */
 +
    #ifdef HAVE_TRACING
 -  TRACE_msg_vm_change_host(vm,vm->location,destination);
 +  const char *old_pm_name = simcall_vm_get_phys_host(vm);
 +  msg_host_t old_pm_ind  = xbt_lib_get_elm_or_null(host_lib, old_pm_name);
    #endif
  
 -  vm->location = destination;
 +  simcall_vm_migrate(vm, destination);
 +
 +
 +  #ifdef HAVE_TRACING
 +  TRACE_msg_vm_change_host(vm, old_pm_ind, destination);
 +  #endif
  }
  
 +
  /** @brief Immediately suspend the execution of all processes within the given VM.
   *  @ingroup msg_VMs
   *
 - * No suspension cost occurs. If you want to simulate this too, you want to
 - * use a \ref MSG_file_write() before or after, depending on the exact semantic
 - * of VM suspend to you.
 - */
 -void MSG_vm_suspend(msg_vm_t vm) {
 -  unsigned int cpt;
 -  msg_process_t process;
 -  xbt_dynar_foreach(vm->processes,cpt,process) {
 -    XBT_DEBUG("suspend process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
 -    MSG_process_suspend(process);
 -  }
 + * This function stops the exection of the VM. All the processes on this VM
 + * will pause. The state of the VM is perserved. We can later resume it again.
 + *
 + * No suspension cost occurs.
 + */
 +void MSG_vm_suspend(msg_vm_t vm)
 +{
 +  simcall_vm_suspend(vm);
  
    #ifdef HAVE_TRACING
    TRACE_msg_vm_suspend(vm);
    #endif
  }
  
 -/** @brief Immediately resumes the execution of all processes within the given VM.
 +
 +/** @brief Resume the execution of the VM. All processes on the VM run again.
   *  @ingroup msg_VMs
   *
 - * No resume cost occurs. If you want to simulate this too, you want to
 - * use a \ref MSG_file_read() before or after, depending on the exact semantic
 - * of VM resume to you.
 - */
 -void MSG_vm_resume(msg_vm_t vm) {
 -  unsigned int cpt;
 -  msg_process_t process;
 -  xbt_dynar_foreach(vm->processes,cpt,process) {
 -    XBT_DEBUG("resume process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
 -    MSG_process_resume(process);
 -  }
 + * No resume cost occurs.
 + */
 +void MSG_vm_resume(msg_vm_t vm)
 +{
 +  simcall_vm_resume(vm);
  
    #ifdef HAVE_TRACING
    TRACE_msg_vm_resume(vm);
    #endif
  }
  
 -/** @brief Immediately kills all processes within the given VM. Any memory that they allocated will be leaked.
 +
 +/** @brief Immediately save the execution of all processes within the given VM.
   *  @ingroup msg_VMs
   *
 - * No extra delay occurs. If you want to simulate this too, you want to
 - * use a #MSG_process_sleep() or something. I'm not quite sure.
 + * This function stops the exection of the VM. All the processes on this VM
 + * will pause. The state of the VM is perserved. We can later resume it again.
 + *
 + * FIXME: No suspension cost occurs. If you want to simulate this too, you want to
 + * use a \ref MSG_file_write() before or after, depending on the exact semantic
 + * of VM save to you.
   */
 -void MSG_vm_shutdown(msg_vm_t vm)
 +void MSG_vm_save(msg_vm_t vm)
  {
 -  msg_process_t process;
 -  XBT_DEBUG("%lu processes in the VM", xbt_dynar_length(vm->processes));
 -  while (!xbt_dynar_is_empty(vm->processes)) {
 -    process = xbt_dynar_get_as(vm->processes,0,msg_process_t);
 -    MSG_process_kill(process);
 -  }
 -
 +  simcall_vm_save(vm);
    #ifdef HAVE_TRACING
 -  TRACE_msg_vm_kill(vm);
 +  TRACE_msg_vm_save(vm);
    #endif
 -
  }
  
 -/**
 - * \ingroup msg_VMs
 - * \brief Reboot the VM, restarting all the processes in it.
 +/** @brief Restore the execution of the VM. All processes on the VM run again.
 + *  @ingroup msg_VMs
 + *
 + * FIXME: No restore cost occurs. If you want to simulate this too, you want to
 + * use a \ref MSG_file_read() before or after, depending on the exact semantic
 + * of VM restore to you.
   */
 -void MSG_vm_reboot(msg_vm_t vm)
 +void MSG_vm_restore(msg_vm_t vm)
  {
 -  xbt_dynar_t process_list = xbt_dynar_new(sizeof(msg_process_t), NULL);
 -  msg_process_t process;
 -  unsigned int cpt;
 -
 -  xbt_dynar_foreach(vm->processes, cpt, process) {
 -    xbt_dynar_push_as(process_list, msg_process_t, process);
 -  }
 +  simcall_vm_restore(vm);
  
 -  xbt_dynar_foreach(process_list, cpt, process) {
 -    msg_process_t new_process = MSG_process_restart(process);
 -    MSG_vm_bind(vm, new_process);
 -  }
 -
 -  xbt_dynar_free(&process_list);
 +  #ifdef HAVE_TRACING
 +  TRACE_msg_vm_restore(vm);
 +  #endif
  }
  
 -/** @brief Destroy a msg_vm_t.
 +
 +/** @brief Destroy a VM. Destroy the VM object from the simulation.
   *  @ingroup msg_VMs
   */
 -void MSG_vm_destroy(msg_vm_t vm) {
 -  unsigned int cpt;
 -  msg_process_t process;
 -  xbt_dynar_foreach(vm->processes,cpt,process) {
 -    //FIXME: Slow ?
 -    simdata_process_t simdata = simcall_process_get_data(process);
 -    simdata->vm = NULL;
 -  }
 +void MSG_vm_destroy(msg_vm_t vm)
 +{
 +  /* First, terminate all processes on the VM */
 +  simcall_vm_shutdown(vm);
 +
 +  /* Then, destroy the VM object */
 +  simcall_vm_destroy(vm);
  
    #ifdef HAVE_TRACING
    TRACE_msg_vm_end(vm);
    #endif
 -
 -  xbt_free(vm->name);
 -  xbt_dynar_free(&vm->processes);
 -  xbt_free(vm);
  }
diff --combined src/simgrid/sg_config.c
@@@ -663,6 -663,12 +663,12 @@@ void sg_config_init(int *argc, char **a
                       xbt_cfgelm_int, &default_small_messages_threshold, 1, 1, NULL,
                       NULL);
  
+     int default_send_is_detached_threshold = 65536;
+     xbt_cfg_register(&_sg_cfg_set, "smpi/send_is_detached_thres",
+                      "Threshold of message size where MPI_Send stops behaving like MPI_Isend and becomes MPI_Ssend",
+                      xbt_cfgelm_int, &default_send_is_detached_threshold, 1, 1, NULL,
+                      NULL);
      //For smpi/bw_factor and smpi/lat_factor
      //Default value have to be "threshold0:value0;threshold1:value1;...;thresholdN:valueN"
      //test is if( size >= thresholdN ) return valueN;
      xbt_cfg_setdefault_string(_sg_cfg_set, "smpi/lat_factor", "65472:11.6436;15424:3.48845;9376:2.59299;5776:2.18796;3484:1.88101;1426:1.61075;732:1.9503;257:1.95341;0:2.01467");
  
      xbt_cfg_register(&_sg_cfg_set, "smpi/os",
-                      "Small messages timings (MPI_Isend/Send minimum time for small messages)",
+                      "Small messages timings (MPI_Send minimum time for small messages)",
                       xbt_cfgelm_string, NULL, 1, 1, NULL,
                       NULL);
      xbt_cfg_setdefault_string(_sg_cfg_set, "smpi/os", "1:0:0:0:0");
  
+     xbt_cfg_register(&_sg_cfg_set, "smpi/ois",
+                      "Small messages timings (MPI_Isend minimum time for small messages)",
+                      xbt_cfgelm_string, NULL, 1, 1, NULL,
+                      NULL);
+     xbt_cfg_setdefault_string(_sg_cfg_set, "smpi/ois", "1:0:0:0:0");
      xbt_cfg_register(&_sg_cfg_set, "smpi/or",
                       "Small messages timings (MPI_Recv minimum time for small messages)",
                       xbt_cfgelm_string, NULL, 1, 1, NULL,
@@@ -785,9 -797,6 +797,9 @@@ void surf_config_models_setup(
    XBT_DEBUG("Call workstation_model_init");
    surf_workstation_model_description[workstation_id].model_init_preparse();
  
 +  XBT_DEBUG("Call vm_workstation_model_init");
 +  surf_vm_workstation_model_init();
 +
    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();
diff --combined src/simix/smx_host.c
@@@ -51,8 -51,7 +51,7 @@@ void SIMIX_host_destroy(void *h
  
    /* Clean Simulator data */
    if (xbt_swag_size(host->process_list) != 0) {
-     char *msg =
-         bprintf("Shutting down host, but it's not empty:");
+     char *msg = xbt_strdup("Shutting down host, but it's not empty:");
      char *tmp;
      smx_process_t process = NULL;
  
@@@ -136,8 -135,7 +135,8 @@@ 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)");
  
 -  return surf_workstation_model->extension.workstation.get_properties(host);
 +  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 +  return ws_model->extension.workstation.get_properties(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)");
  
 -  return surf_workstation_model->extension.workstation.
 -      get_speed(host, 1.0);
 +  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 +  return ws_model->extension.workstation.get_speed(host, 1.0);
  }
  
  double SIMIX_pre_host_get_available_speed(smx_simcall_t simcall, smx_host_t host){
  double SIMIX_host_get_available_speed(smx_host_t host){
    xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
  
 -  return surf_workstation_model->extension.workstation.
 -      get_available_speed(host);
 +  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 +  return ws_model->extension.workstation.get_available_speed(host);
  }
  
  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)");
  
 -  return surf_workstation_model->extension.workstation.
 -      get_state(host);
 +  surf_model_t ws_model = surf_resource_model(host, SURF_WKS_LEVEL);
 +  return ws_model->extension.workstation.get_state(host);
  }
  
  void* SIMIX_pre_host_self_get_data(smx_simcall_t simcall){
@@@ -323,12 -321,13 +322,12 @@@ smx_action_t SIMIX_host_execute(const c
    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_model->extension.workstation.execute(host,
 -    computation_amount);
 -    surf_workstation_model->action_data_set(action->execution.surf_exec, action);
 -    surf_workstation_model->set_priority(action->execution.surf_exec, priority);
 +    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);
    }
  
    XBT_DEBUG("Create execute action %p", action);
@@@ -367,54 -366,28 +366,54 @@@ smx_action_t SIMIX_host_parallel_execut
    for (i = 0; i < host_nb; i++)
      workstation_list[i] = 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 =
 -      surf_workstation_model->extension.workstation.
 +      ws_model->extension.workstation.
        execute_parallel_task(host_nb, workstation_list, computation_amount,
                        communication_amount, rate);
  
 -    surf_workstation_model->action_data_set(action->execution.surf_exec, action);
 +    ws_model->action_data_set(action->execution.surf_exec, action);
    }
    XBT_DEBUG("Create parallel execute action %p", action);
  
    return action;
  }
  
 +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);
 +
 +  xbt_assert((model == surf_workstation_model) || (model == surf_vm_workstation_model));
 +
 +  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) {
 -    surf_workstation_model->action_unref(action->execution.surf_exec);
 +    ws_model->action_unref(action->execution.surf_exec);
      action->execution.surf_exec = NULL;
    }
    xbt_free(action->name);
@@@ -427,10 -400,8 +426,10 @@@ 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)
 -    surf_workstation_model->action_cancel(action->execution.surf_exec);
 +    ws_model->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 = surf_workstation_model->get_remains(action->execution.surf_exec);
 +    result = ws_model->get_remains(action->execution.surf_exec);
  
    return result;
  }
@@@ -458,10 -428,8 +457,10 @@@ void SIMIX_pre_host_execution_set_prior
    return 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)
 -    surf_workstation_model->set_priority(action->execution.surf_exec, priority);
 +    ws_model->set_priority(action->execution.surf_exec, priority);
  }
  
  void SIMIX_pre_host_execution_wait(smx_simcall_t simcall, smx_action_t action){
  
  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)
 -    surf_workstation_model->suspend(action->execution.surf_exec);
 +    ws_model->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)
 -    surf_workstation_model->resume(action->execution.surf_exec);
 +    ws_model->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 (surf_workstation_model->extension.
 -        workstation.get_state(simcall->issuer->smx_host) != SURF_RESOURCE_ON) {
 +    if (ws_model->extension.workstation.get_state(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)
  {
    if (action->type == SIMIX_ACTION_EXECUTE && /* FIMXE: handle resource failure
@@@ -580,13 -543,11 +579,13 @@@ 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){
 -    surf_workstation_model->set_category(action->execution.surf_exec, category);
 +    ws_model->set_category(action->execution.surf_exec, category);
    }else if (action->type == SIMIX_ACTION_COMMUNICATE){
 -    surf_workstation_model->set_category(action->comm.surf_comm, category);
 +    ws_model->set_category(action->comm.surf_comm, category);
    }
  }
  #endif
diff --combined src/simix/smx_network.c
@@@ -13,7 -13,7 +13,7 @@@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_n
                                  "Logging specific to SIMIX (network)");
  
  static xbt_dict_t rdv_points = NULL;
- XBT_IMPORT_NO_EXPORT(unsigned long int) smx_total_comms = 0;
+ XBT_EXPORT_NO_IMPORT(unsigned long int) smx_total_comms = 0;
  
  static void SIMIX_waitany_remove_simcall_from_actions(smx_simcall_t simcall);
  static void SIMIX_comm_copy_data(smx_action_t comm);
@@@ -337,17 -337,17 +337,17 @@@ void SIMIX_comm_destroy_internal_action
  #ifdef HAVE_LATENCY_BOUND_TRACKING
      action->latency_limited = SIMIX_comm_is_latency_bounded(action);
  #endif
 -    action->comm.surf_comm->model_type->action_unref(action->comm.surf_comm);
 +    action->comm.surf_comm->model_obj->action_unref(action->comm.surf_comm);
      action->comm.surf_comm = NULL;
    }
  
    if (action->comm.src_timeout){
 -    action->comm.src_timeout->model_type->action_unref(action->comm.src_timeout);
 +    action->comm.src_timeout->model_obj->action_unref(action->comm.src_timeout);
      action->comm.src_timeout = NULL;
    }
  
    if (action->comm.dst_timeout){
 -    action->comm.dst_timeout->model_type->action_unref(action->comm.dst_timeout);
 +    action->comm.dst_timeout->model_obj->action_unref(action->comm.dst_timeout);
      action->comm.dst_timeout = NULL;
    }
  }
@@@ -458,6 -458,17 +458,17 @@@ void SIMIX_pre_comm_recv(smx_simcall_t 
    simcall->mc_value = 0;
    SIMIX_pre_comm_wait(simcall, comm, timeout);
  }
+ void SIMIX_pre_comm_recv_bounded(smx_simcall_t simcall, smx_rdv_t rdv,
+                                   void *dst_buff, size_t *dst_buff_size,
+                                   int (*match_fun)(void *, void *, smx_action_t),
+                                 void *data, double timeout, double rate){
+   smx_action_t comm = SIMIX_comm_irecv_bounded(simcall->issuer, rdv, dst_buff,
+                                      dst_buff_size, match_fun, data, rate);
+   simcall->mc_value = 0;
+   SIMIX_pre_comm_wait(simcall, comm, timeout);
+ }
  smx_action_t SIMIX_pre_comm_irecv(smx_simcall_t simcall, smx_rdv_t rdv,
                                    void *dst_buff, size_t *dst_buff_size,
                                    int (*match_fun)(void *, void *, smx_action_t),
    return SIMIX_comm_irecv(simcall->issuer, rdv, dst_buff, dst_buff_size,
                          match_fun, data);
  }
  smx_action_t SIMIX_comm_irecv(smx_process_t dst_proc, smx_rdv_t rdv,
                                void *dst_buff, size_t *dst_buff_size,
                                int (*match_fun)(void *, void *, smx_action_t), void *data)
    return other_action;
  }
  
+ smx_action_t SIMIX_pre_comm_irecv_bounded(smx_simcall_t simcall, smx_rdv_t rdv,
+                                   void *dst_buff, size_t *dst_buff_size,
+                                   int (*match_fun)(void *, void *, smx_action_t),
+                                 void *data, double rate){
+   return SIMIX_comm_irecv_bounded(simcall->issuer, rdv, dst_buff, dst_buff_size,
+                         match_fun, data, rate);
+ }
+ smx_action_t SIMIX_comm_irecv_bounded(smx_process_t dst_proc, smx_rdv_t rdv,
+                               void *dst_buff, size_t *dst_buff_size,
+                               int (*match_fun)(void *, void *, smx_action_t), void *data, double rate)
+ {
+   XBT_DEBUG("recv from %p %p\n", rdv, rdv->comm_fifo);
+   smx_action_t this_action = SIMIX_comm_new(SIMIX_COMM_RECEIVE);
+   smx_action_t other_action;
+   //communication already done, get it inside the fifo of completed comms
+   //permanent receive v1
+   //int already_received=0;
+   if(rdv->permanent_receiver && xbt_fifo_size(rdv->done_comm_fifo)!=0){
+     XBT_DEBUG("We have a comm that has probably already been received, trying to match it, to skip the communication\n");
+     //find a match in the already received fifo
+     other_action = SIMIX_fifo_get_comm(rdv->done_comm_fifo, SIMIX_COMM_SEND, match_fun, data, this_action);
+     //if not found, assume the receiver came first, register it to the mailbox in the classical way
+     if (!other_action)  {
+       XBT_DEBUG("We have messages in the permanent receive list, but not the one we are looking for, pushing request into fifo\n");
+       other_action = this_action;
+       SIMIX_rdv_push(rdv, this_action);
+     }else{
+       if(other_action->comm.surf_comm &&      SIMIX_comm_get_remains(other_action)==0.0)
+       {
+         XBT_DEBUG("comm %p has been already sent, and is finished, destroy it\n",&(other_action->comm));
+         other_action->state = SIMIX_DONE;
+         other_action->comm.type = SIMIX_COMM_DONE;
+         other_action->comm.rdv = NULL;
+         //SIMIX_comm_destroy(this_action);
+         //--smx_total_comms; // this creation was a pure waste
+         //already_received=1;
+         //other_action->comm.refcount--;
+       }/*else{
+          XBT_DEBUG("Not yet finished, we have to wait %d\n", xbt_fifo_size(rdv->comm_fifo));
+          }*/
+       other_action->comm.refcount--;
+       SIMIX_comm_destroy(this_action);
+       --smx_total_comms; // this creation was a pure waste
+     }
+   }else{
+     /* Prepare an action describing us, so that it gets passed to the user-provided filter of other side */
+     /* Look for communication action matching our needs. We also provide a description of
+      * ourself so that the other side also gets a chance of choosing if it wants to match with us.
+      *
+      * If it is not found then push our communication into the rendez-vous point */
+     other_action = SIMIX_fifo_get_comm(rdv->comm_fifo, SIMIX_COMM_SEND, match_fun, data, this_action);
+     if (!other_action) {
+       XBT_DEBUG("Receive pushed first %d\n", xbt_fifo_size(rdv->comm_fifo));
+       other_action = this_action;
+       SIMIX_rdv_push(rdv, this_action);
+     } else {
+       SIMIX_comm_destroy(this_action);
+       --smx_total_comms; // this creation was a pure waste
+       other_action->state = SIMIX_READY;
+       other_action->comm.type = SIMIX_COMM_READY;
+       //other_action->comm.refcount--;
+     }
+     xbt_fifo_push(dst_proc->comms, other_action);
+   }
+   /* Setup communication action */
+   other_action->comm.dst_proc = dst_proc;
+   other_action->comm.dst_buff = dst_buff;
+   other_action->comm.dst_buff_size = dst_buff_size;
+   other_action->comm.dst_data = data;
+   if (rate < other_action->comm.rate || other_action->comm.rate == -1.0)
+         other_action->comm.rate = rate;
+   other_action->comm.match_fun = match_fun;
+   /*if(already_received)//do the actual copy, because the first one after the comm didn't have all the info
+     SIMIX_comm_copy_data(other_action);*/
+   if (MC_is_active()) {
+     other_action->state = SIMIX_RUNNING;
+     return other_action;
+   }
+   SIMIX_comm_start(other_action);
+   // }
+   return other_action;
+ }
  smx_action_t SIMIX_pre_comm_iprobe(smx_simcall_t simcall, smx_rdv_t rdv,
                                     int src, int tag,
                                     int (*match_fun)(void *, void *, smx_action_t),
diff --combined src/simix/smx_process.c
@@@ -95,7 -95,6 +95,6 @@@ void SIMIX_process_cleanup(smx_process_
      }
    }
  
-   /*xbt_swag_remove(process, simix_global->process_to_run);*/
    xbt_swag_remove(process, simix_global->process_list);
    xbt_swag_remove(process, SIMIX_host_priv(process->smx_host)->process_list);
    xbt_swag_insert(process, simix_global->process_to_destroy);
@@@ -344,35 -343,36 +343,36 @@@ void SIMIX_process_kill(smx_process_t p
  
      switch (process->waiting_action->type) {
  
-       case SIMIX_ACTION_EXECUTE:          
-       case SIMIX_ACTION_PARALLEL_EXECUTE:
-         SIMIX_host_execution_destroy(process->waiting_action);
-         break;
-       case SIMIX_ACTION_COMMUNICATE:
-         xbt_fifo_remove(process->comms, process->waiting_action);
-         SIMIX_comm_cancel(process->waiting_action);
-         break;
-         case SIMIX_ACTION_SLEEP:
-           SIMIX_process_sleep_destroy(process->waiting_action);
-           break;
-         case SIMIX_ACTION_SYNCHRO:
-           SIMIX_synchro_stop_waiting(process, &process->simcall);
-           SIMIX_synchro_destroy(process->waiting_action);
-           break;
-         case SIMIX_ACTION_IO:
-           SIMIX_io_destroy(process->waiting_action);
-           break;
-         /* **************************************/
-         /* TUTORIAL: New API                    */
-         case SIMIX_ACTION_NEW_API:
-           SIMIX_new_api_destroy(process->waiting_action);
-           break;
-         /* **************************************/
+     case SIMIX_ACTION_EXECUTE:
+     case SIMIX_ACTION_PARALLEL_EXECUTE:
+       SIMIX_host_execution_destroy(process->waiting_action);
+       break;
+     case SIMIX_ACTION_COMMUNICATE:
+       xbt_fifo_remove(process->comms, process->waiting_action);
+       SIMIX_comm_cancel(process->waiting_action);
+       SIMIX_comm_destroy(process->waiting_action);
+       break;
+     case SIMIX_ACTION_SLEEP:
+       SIMIX_process_sleep_destroy(process->waiting_action);
+       break;
+     case SIMIX_ACTION_SYNCHRO:
+       SIMIX_synchro_stop_waiting(process, &process->simcall);
+       SIMIX_synchro_destroy(process->waiting_action);
+       break;
+     case SIMIX_ACTION_IO:
+       SIMIX_io_destroy(process->waiting_action);
+       break;
+       /* **************************************/
+       /* TUTORIAL: New API                    */
+     case SIMIX_ACTION_NEW_API:
+       SIMIX_new_api_destroy(process->waiting_action);
+       break;
+       /* **************************************/
  
      }
    }
@@@ -721,6 -721,7 +721,7 @@@ void SIMIX_post_process_sleep(smx_actio
        case SURF_ACTION_FAILED:
          simcall->issuer->context->iwannadie = 1;
          //SMX_EXCEPTION(simcall->issuer, host_error, 0, "Host failed");
+         state = SIMIX_SRC_HOST_FAILURE;
          break;
  
        case SURF_ACTION_DONE:
@@@ -747,7 -748,7 +748,7 @@@ void SIMIX_process_sleep_destroy(smx_ac
  {
    XBT_DEBUG("Destroy action %p", action);
    if (action->sleep.surf_sleep)
 -    action->sleep.surf_sleep->model_type->action_unref(action->sleep.surf_sleep);
 +    action->sleep.surf_sleep->model_obj->action_unref(action->sleep.surf_sleep);
    xbt_mallocator_release(simix_global->action_mallocator, action);
  }
  
    inline static SIMCALL_FUNC_RETURN_TYPE(RES) simcall_BODY_##NAME(MAP(SIMCALL_ARG, ##__VA_ARGS__)) { \
      smx_process_t self = SIMIX_process_self(); \
      self->simcall.call = TYPE; \
-     memset(self->simcall.args, 0, sizeof(self->simcall.args));  \
+     memset(&self->simcall.result, 0, sizeof(self->simcall.result)); \
+     memset(self->simcall.args, 0, sizeof(self->simcall.args)); \
      MAP_WITH_DEFAULT_ARGS(SIMCALL_INIT_FIELD, (), ##__VA_ARGS__) \
      if (self != simix_global->maestro_process) { \
        XBT_DEBUG("Yield process '%s' on simcall %s (%d)", self->name, \
@@@ -274,18 -275,6 +275,18 @@@ ACTION(SIMCALL_HOST_EXECUTION_GET_REMAI
  ACTION(SIMCALL_HOST_EXECUTION_GET_STATE, host_execution_get_state, WITH_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
  ACTION(SIMCALL_HOST_EXECUTION_SET_PRIORITY, host_execution_set_priority, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t), TDOUBLE(priority)) sep \
  ACTION(SIMCALL_HOST_EXECUTION_WAIT, host_execution_wait, WITHOUT_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
 +ACTION(SIMCALL_VM_CREATE, vm_create, WITH_ANSWER, TPTR(result), TSTRING(name), TSPEC(phys_host, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_START, vm_start, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_phys_host, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_SET_STATE, vm_set_state, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TINT(state)) sep \
 +ACTION(SIMCALL_VM_GET_STATE, vm_get_state, WITH_ANSWER, TINT(result), TSPEC(ind_vm, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_MIGRATE, vm_migrate, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TSPEC(ind_dst_pm, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_GET_PHYS_HOST, vm_get_phys_host, WITH_ANSWER, TSTRING(result), TSPEC(ind_vm, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_DESTROY, vm_destroy, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_SUSPEND, vm_suspend, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_RESUME, vm_resume, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_SHUTDOWN, vm_shutdown, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_SAVE, vm_save, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
 +ACTION(SIMCALL_VM_RESTORE, vm_restore, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
  ACTION(SIMCALL_PROCESS_CREATE, process_create, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t*), TSTRING(name), TSPEC(code, xbt_main_func_t), TPTR(data), TSTRING(hostname), TDOUBLE(kill_time), TINT(argc), TSPEC(argv, char**), TSPEC(properties, xbt_dict_t), TINT(auto_restart)) sep \
  ACTION(SIMCALL_PROCESS_KILL, process_kill, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
  ACTION(SIMCALL_PROCESS_KILLALL, process_killall, WITH_ANSWER, TVOID(result), TINT(reset_pid)) sep \
@@@ -318,6 -307,8 +319,8 @@@ ACTION(SIMCALL_COMM_SEND, comm_send, WI
  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 \
@@@ -460,8 -451,6 +463,6 @@@ xbt_dict_t SIMIX_pre_asr_get_properties
  
  /*************************** New simcall interface ****************************/
  
- smx_simcall_t __SIMIX_simcall(e_smx_simcall_t simcall_id, u_smx_scalar_t *args);
  typedef smx_action_t (*simcall_handler_t)(u_smx_scalar_t *);
  
  extern const char *simcall_types[];
diff --combined src/simix/smx_user.c
@@@ -274,145 -274,6 +274,145 @@@ e_smx_state_t simcall_host_execution_wa
    return simcall_BODY_host_execution_wait(execution);
  }
  
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Create a VM on the given physical host.
 + *
 + * \param name VM name
 + * \param host Physical host
 + *
 + * \return The host object of the VM
 + */
 +void* simcall_vm_create(const char *name, smx_host_t phys_host){
 +  /* will jump to SIMIX_pre_vm_create() in src/simix/smx_smurf_private.h */
 +  return simcall_BODY_vm_create(name, phys_host);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Start the given VM to the given physical host
 + *
 + * \param vm VM
 + */
 +void simcall_vm_start(smx_host_t vm)
 +{
 +  /* will jump to SIMIX_pre_vm_start in src/simix/smx_smurf_private.h */
 +  simcall_BODY_vm_start(vm);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Get the state of the given VM
 + *
 + * \param vm VM
 + * \return The state of the VM
 + */
 +int simcall_vm_get_state(smx_host_t vm)
 +{
 +  /* will jump to SIMIX_pre_vm_get_state in src/simix/smx_smurf_private.h */
 +  return simcall_BODY_vm_get_state(vm);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Get the name of the physical host on which the given VM runs.
 + *
 + * \param vm VM
 + * \return The name of the physical host
 + */
 +const char *simcall_vm_get_phys_host(smx_host_t vm)
 +{
 +  /* will jump to SIMIX_pre_vm_migrate in src/simix/smx_smurf_private.h */
 +  simcall_BODY_vm_get_phys_host(vm);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Migrate the given VM to the given physical host
 + *
 + * \param vm VM
 + * \param host Destination physical host
 + */
 +void simcall_vm_migrate(smx_host_t vm, smx_host_t host)
 +{
 +  /* will jump to SIMIX_pre_vm_migrate in src/simix/smx_smurf_private.h */
 +  simcall_BODY_vm_migrate(vm, host);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Suspend the given VM
 + *
 + * \param vm VM
 + */
 +void simcall_vm_suspend(smx_host_t vm)
 +{
 +  /* will jump to SIMIX_pre_vm_suspend in src/simix/smx_smurf_private.h */
 +  simcall_BODY_vm_suspend(vm);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Resume the given VM
 + *
 + * \param vm VM
 + */
 +void simcall_vm_resume(smx_host_t vm)
 +{
 +  /* will jump to SIMIX_pre_vm_resume in src/simix/smx_smurf_private.h */
 +  simcall_BODY_vm_resume(vm);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Save the given VM
 + *
 + * \param vm VM
 + */
 +void simcall_vm_save(smx_host_t vm)
 +{
 +  /* will jump to SIMIX_pre_vm_save in src/simix/smx_smurf_private.h */
 +  simcall_BODY_vm_save(vm);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Restore the given VM
 + *
 + * \param vm VM
 + */
 +void simcall_vm_restore(smx_host_t vm)
 +{
 +  /* will jump to SIMIX_pre_vm_restore in src/simix/smx_smurf_private.h */
 +  simcall_BODY_vm_restore(vm);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Shutdown the given VM
 + *
 + * \param vm VM
 + */
 +void simcall_vm_shutdown(smx_host_t vm)
 +{
 +  /* will jump to SIMIX_pre_vm_shutdown in src/simix/smx_smurf_private.h */
 +  simcall_BODY_vm_shutdown(vm);
 +}
 +
 +/**
 + * \ingroup simix_vm_management
 + * \brief Destroy the given VM
 + *
 + * \param vm VM
 + */
 +void simcall_vm_destroy(smx_host_t vm)
 +{
 +   /* will jump to SIMIX_pre_vm_destroy in src/simix/smx_smurf_private.h */
 +  simcall_BODY_vm_destroy(vm);
 +}
 +
 +
  /**
   * \ingroup simix_process_management
   * \brief Creates and runs a new SIMIX process.
@@@ -746,7 -607,7 +746,7 @@@ smx_rdv_t simcall_rdv_get_by_name(cons
  {
    xbt_assert(name != NULL, "Invalid parameter for simcall_rdv_get_by_name (name is NULL)");
  
-   /* FIXME: this is a horrible lost of performance, so we hack it out by
+   /* FIXME: this is a horrible loss of performance, so we hack it out by
     * skipping the simcall (for now). It works in parallel, it won't work on
     * distributed but probably we will change MSG for that. */
  
@@@ -874,6 -735,39 +874,39 @@@ smx_action_t simcall_comm_irecv(smx_rdv
  }
  
  
+ /**
+  * \ingroup simix_comm_management
+  */
+ void simcall_comm_recv_bounded(smx_rdv_t rdv, void *dst_buff, size_t * dst_buff_size,
+                          int (*match_fun)(void *, void *, smx_action_t), void *data, double timeout, double rate)
+ {
+   xbt_assert(isfinite(timeout), "timeout is not finite!");
+   xbt_assert(rdv, "No rendez-vous point defined for recv");
+   if (MC_is_active()) {
+     /* the model-checker wants two separate simcalls */
+     smx_action_t comm = simcall_comm_irecv_bounded(rdv, dst_buff, dst_buff_size,
+         match_fun, data, rate);
+     simcall_comm_wait(comm, timeout);
+   }
+   else {
+     simcall_BODY_comm_recv_bounded(rdv, dst_buff, dst_buff_size,
+                            match_fun, data, timeout, rate);
+   }
+ }
+ /**
+  * \ingroup simix_comm_management
+  */
+ smx_action_t simcall_comm_irecv_bounded(smx_rdv_t rdv, void *dst_buff, size_t *dst_buff_size,
+                                   int (*match_fun)(void *, void *, smx_action_t), void *data, double rate)
+ {
+   xbt_assert(rdv, "No rendez-vous point defined for irecv");
+   return simcall_BODY_comm_irecv_bounded(rdv, dst_buff, dst_buff_size,
+                                  match_fun, data, rate);
+ }
  /**
   * \ingroup simix_comm_management
   */
diff --combined src/surf/storage.c
@@@ -269,13 -269,13 +269,13 @@@ static void* storage_create_resource(co
    return storage;
  }
  
 -static void storage_finalize(void)
 +static void storage_finalize(surf_model_t storage_model)
  {
    lmm_system_free(storage_maxmin_system);
    storage_maxmin_system = NULL;
  
 -  surf_model_exit(surf_storage_model);
 -  surf_storage_model = NULL;
 +  surf_model_exit(storage_model);
 +  storage_model = NULL;
  
    if(storage_list)
      xbt_dynar_free(&storage_list);
    storage_running_action_set_that_does_not_need_being_checked = NULL;
  }
  
 -static void storage_update_actions_state(double now, double delta)
 +static void storage_update_actions_state(surf_model_t storage_model, double now, double delta)
  {
    surf_action_storage_t action = NULL;
    surf_action_storage_t next_action = NULL;
 -  xbt_swag_t running_actions = surf_storage_model->states.running_action_set;
 +  xbt_swag_t running_actions = storage_model->states.running_action_set;
  
    // Update the disk usage
    // Update the file size
    return;
  }
  
 -static double storage_share_resources(double NOW)
 +static double storage_share_resources(surf_model_t storage_model, double NOW)
  {
    XBT_DEBUG("storage_share_resources %f",NOW);
    s_surf_action_storage_t action;
    storage_t storage;
    surf_action_storage_t write_action;
  
 -  double min_completion = generic_maxmin_share_resources(surf_storage_model->states.running_action_set,
 +  double min_completion = generic_maxmin_share_resources(storage_model->states.running_action_set,
        xbt_swag_offset(action, generic_lmm_action.variable),
        storage_maxmin_system, lmm_solve);
  
@@@ -495,7 -495,6 +495,7 @@@ static void surf_storage_model_init_int
        xbt_swag_new(xbt_swag_offset(action, state_hookup));
  
    surf_storage_model->name = "Storage";
 +  surf_storage_model->type = SURF_MODEL_TYPE_STORAGE;
    surf_storage_model->action_unref = storage_action_unref;
    surf_storage_model->action_cancel = storage_action_cancel;
    surf_storage_model->action_state_set = storage_action_state_set;
@@@ -594,7 -593,7 +594,7 @@@ static xbt_dict_t parse_storage_content
  
    surf_stat_t content;
  
-   while ((read = getline(&line, &len, file)) != -1) {
+   while ((read = xbt_getline(&line, &len, file)) != -1) {
      if (read){
      content = xbt_new0(s_surf_stat_t,1);
      if(sscanf(line,"%s %d %s %s %ld %s %s %s",user_rights,&nb,user,group,&size,date,time,path)==8) {
diff --combined src/surf/surf.c
@@@ -110,11 -110,7 +110,11 @@@ int __surf_is_absolute_file_path(const 
  
  double NOW = 0;
  
 -xbt_dynar_t model_list = NULL;
 +/* 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 */
  tmgr_history_t history = NULL;
  lmm_system_t maxmin_system = NULL;
  xbt_dynar_t surf_path = NULL;
@@@ -419,8 -415,6 +419,8 @@@ void surf_init(int *argc, char **argv
    xbt_init(argc, argv);
    if (!model_list)
      model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
 +  if (!model_list_invoke)
 +    model_list_invoke = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
    if (!history)
      history = tmgr_history_new();
  
@@@ -474,11 -468,8 +474,11 @@@ void surf_exit(void
    sg_config_finalize();
  
    xbt_dynar_foreach(model_list, iter, model)
 -      model->model_private->finalize();
 +      model->model_private->finalize(model);
    xbt_dynar_free(&model_list);
 +
 +  xbt_dynar_free(&model_list_invoke);
 +
    routing_exit();
  
    if (maxmin_system) {
@@@ -539,10 -530,8 +539,10 @@@ void surf_presolve(void
        }
      }
    }
 +
 +  /* FIXME: see what is check_update_action_state(). if necessary, use model_list_invoke. */
    xbt_dynar_foreach(model_list, iter, model)
 -      model->model_private->update_actions_state(NOW, 0.0);
 +      model->model_private->update_actions_state(model, NOW, 0.0);
  }
  
  double surf_solve(double max_date)
    XBT_DEBUG("Looking for next action end for all models except NS3");
  
    if (surf_mins == NULL) {
 -    surf_mins = xbt_new(double, xbt_dynar_length(model_list));
 +    surf_mins = xbt_new(double, xbt_dynar_length(model_list_invoke));
    }
    surf_min_index = 0;
  
    if (surf_get_nthreads() > 1) {
      /* parallel version */
  #ifdef CONTEXT_THREADS
 -    xbt_parmap_apply(surf_parmap, (void_f_pvoid_t) surf_share_resources, model_list);
 +    xbt_parmap_apply(surf_parmap, (void_f_pvoid_t) surf_share_resources, model_list_invoke);
  #else
      xbt_die("Asked to run in parallel, but no thread at hand...");
  #endif
    }
    else {
      /* sequential version */
 -    xbt_dynar_foreach(model_list, iter, model) {
 +    xbt_dynar_foreach(model_list_invoke, iter, model) {
        surf_share_resources(model);
      }
    }
  
    unsigned i;
 -  for (i = 0; i < xbt_dynar_length(model_list); i++) {
 +  for (i = 0; i < xbt_dynar_length(model_list_invoke); i++) {
      if ((min < 0.0 || surf_mins[i] < min)
          && surf_mins[i] >= 0.0) {
        min = surf_mins[i];
  
        XBT_DEBUG("Run for network at most %f", min);
        // run until min or next flow
 -      model_next_action_end = surf_network_model->model_private->share_resources(min);
 +      model_next_action_end = surf_network_model->model_private->share_resources(surf_network_model, min);
  
        XBT_DEBUG("Min for network : %f", model_next_action_end);
        if(model_next_action_end>=0.0)
  
      if ((min == -1.0) || (next_event_date > NOW + min)) break;
  
-     XBT_DEBUG("Updating models");
+     XBT_DEBUG("Updating models (min = %g, NOW = %g, next_event_date = %g)",min, NOW, next_event_date);
      while ((event =
              tmgr_history_get_next_event_leq(history, next_event_date,
                                              &value,
               resource->model->name, min);
        resource->model->model_private->update_resource_state(resource,
                                                              event, value,
-                                                             NOW + min);
+                                                             next_event_date);
      }
    } while (1);
  
  #endif
    }
    else {
 +    /* FIXME: model_list or model_list_invoke? revisit here later */
      /* sequential version */
      xbt_dynar_foreach(model_list, iter, model) {
        surf_update_actions_state(model);
@@@ -688,7 -676,7 +688,7 @@@ static void surf_share_resources(surf_m
    int i = __sync_fetch_and_add(&surf_min_index, 1);
    if (strcmp(model->name,"network NS3")) {
      XBT_DEBUG("Running for Resource [%s]", model->name);
 -    next_action_end = model->model_private->share_resources(NOW);
 +    next_action_end = model->model_private->share_resources(model, NOW);
      XBT_DEBUG("Resource [%s] : next action end = %f",
          model->name, next_action_end);
    }
  
  static void surf_update_actions_state(surf_model_t model)
  {
 -  model->model_private->update_actions_state(NOW, min);
 +  model->model_private->update_actions_state(model, NOW, min);
  }
  
  /**
@@@ -765,11 -753,18 +765,18 @@@ void surf_set_nthreads(int nthreads) 
   * sees it and react accordingly. This would kill that need for surf to call simix.
   *
   */
+ static void remove_watched_host(void *key)
+ {
+   xbt_dict_remove(watched_hosts_lib, *(char**)key);
+ }
  void surf_watched_hosts(void)
  {
    char *key;
    void *host;
    xbt_dict_cursor_t cursor;
+   xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL);
  
    XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib");
    xbt_dict_foreach(watched_hosts_lib,cursor,key,host)
      if(SIMIX_host_get_state(host) == SURF_RESOURCE_ON){
        XBT_INFO("Restart processes on host: %s",SIMIX_host_get_name(host));
        SIMIX_host_autorestart(host);
-       xbt_dict_remove(watched_hosts_lib,key);
+       xbt_dynar_push_as(hosts, char*, key);
      }
      else
        XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key);
    }
+   xbt_dynar_map(hosts, remove_watched_host);
+   xbt_dynar_free(&hosts);
  }
diff --combined src/surf/surf_private.h
@@@ -31,12 -31,12 +31,12 @@@ typedef struct surf_model_private 
    int (*resource_used) (void *resource_id);
    /* Share the resources to the actions and return in how much time
       the next action may terminate */
 -  double (*share_resources) (double now);
 +  double (*share_resources) (surf_model_t model, double now);
    /* Update the actions' state */
 -  void (*update_actions_state) (double now, double delta);
 -  void (*update_resource_state) (void *id, tmgr_trace_event_t event_type,
 +  void (*update_actions_state) (surf_model_t model, double now, double delta);
 +  void (*update_resource_state) (void *resource, tmgr_trace_event_t event_type,
                                   double value, double time);
 -  void (*finalize) (void);
 +  void (*finalize) (surf_model_t model);
  
    lmm_system_t maxmin_system;
    e_UM_t update_mechanism;
@@@ -93,7 -93,6 +93,6 @@@ extern tmgr_history_t history
  //void surf_config(const char *name, va_list pa);
  
  void net_action_recycle(surf_action_t action);
- double net_action_get_remains(surf_action_t action);
  #ifdef HAVE_LATENCY_BOUND_TRACKING
  int net_get_link_latency_limited(surf_action_t action);
  #endif
@@@ -153,6 -152,7 +152,7 @@@ typedef struct s_as 
    void (*get_route_and_latency) (AS_t as, sg_routing_edge_t src, sg_routing_edge_t dst, sg_platf_route_cbarg_t into, double *latency);
  
    xbt_dynar_t(*get_onelink_routes) (AS_t as);
+   void (*get_graph) (xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges, AS_t rc);
    sg_platf_route_cbarg_t(*get_bypass_route) (AS_t as, sg_routing_edge_t src, sg_routing_edge_t dst, double *lat);
    void (*finalize) (AS_t as);
  
@@@ -192,6 -192,7 +192,7 @@@ XBT_PUBLIC(void) generic_free_route(sg_
  XBT_PUBLIC(void) routing_get_route_and_latency(sg_routing_edge_t src, sg_routing_edge_t dst,
                                xbt_dynar_t * route, double *latency);
  
+ XBT_PUBLIC(void) generic_get_graph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges, AS_t rc);
  /**
   * Resource protected methods
   */
@@@ -204,7 -205,6 +205,6 @@@ XBT_PUBLIC_DATA(int) surfxml_bufferstac
  /* from surf_instr.c */
  void TRACE_surf_host_set_power(double date, const char *resource, double power);
  void TRACE_surf_link_set_bandwidth(double date, const char *resource, double bandwidth);
- void TRACE_surf_link_set_latency(double date, const char *resource, double latency);
  
  
  #endif                          /* _SURF_SURF_PRIVATE_H */
diff --combined src/surf/workstation.c
  #include "storage_private.h"
  #include "surf/surf_resource.h"
  #include "simgrid/sg_config.h"
 -
 -typedef struct workstation_CLM03 {
 -  s_surf_resource_t generic_resource;   /* Must remain first to add this to a trace */
 -  void *net_elm;
 -  xbt_dynar_t storage;
 -} s_workstation_CLM03_t, *workstation_CLM03_t;
 +#include "workstation_private.h"
  
  XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_workstation, surf,
                                  "Logging specific to the SURF workstation module");
  
  surf_model_t surf_workstation_model = NULL;
  
 -static void workstation_new(sg_platf_host_cbarg_t host)
 +
 +void __init_workstation_CLM03(workstation_CLM03_t ws, const char *id)
  {
 -  workstation_CLM03_t workstation = xbt_new0(s_workstation_CLM03_t, 1);
 +  ws->generic_resource.model = surf_workstation_model;
 +  ws->generic_resource.name = xbt_strdup(id);
 +  ws->storage = xbt_lib_get_or_null(storage_lib, id, ROUTING_STORAGE_HOST_LEVEL);
 +  ws->net_elm = xbt_lib_get_or_null(host_lib, id, ROUTING_HOST_LEVEL);
  
 -  workstation->generic_resource.model = surf_workstation_model;
 -  workstation->generic_resource.name = xbt_strdup(host->id);
 -  workstation->storage = xbt_lib_get_or_null(storage_lib,host->id,ROUTING_STORAGE_HOST_LEVEL);
 -  workstation->net_elm = xbt_lib_get_or_null(host_lib,host->id,ROUTING_HOST_LEVEL);
 -  XBT_DEBUG("Create workstation %s with %ld mounted disks",host->id,xbt_dynar_length(workstation->storage));
 -  xbt_lib_set(host_lib, host->id, SURF_WKS_LEVEL, workstation);
 +  XBT_DEBUG("Create ws %s with %ld mounted disks", id, xbt_dynar_length(ws->storage));
 +  xbt_lib_set(host_lib, id, SURF_WKS_LEVEL, ws);
  }
  
 -static int ws_resource_used(void *resource_id)
 +static void workstation_new(sg_platf_host_cbarg_t host)
  {
 -  THROW_IMPOSSIBLE;             /* This model does not implement parallel tasks */
 -  return -1;
 +  workstation_CLM03_t workstation = xbt_new0(s_workstation_CLM03_t, 1);
 +
 +  __init_workstation_CLM03(workstation, host->id);
  }
  
 +
  static void ws_parallel_action_cancel(surf_action_t action)
  {
    THROW_UNIMPLEMENTED;          /* This model does not implement parallel tasks */
@@@ -51,13 -54,11 +51,13 @@@ static int ws_parallel_action_free(surf
  
  static int ws_action_unref(surf_action_t action)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      return surf_network_model->action_unref(action);
 -  else if (action->model_type == surf_cpu_model)
 -    return surf_cpu_model->action_unref(action);
 -  else if (action->model_type == surf_workstation_model)
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    return action->model_obj->action_unref(action);
 +      // previously was: Adrien/Arnaud 6 feb
 +        // surf_cpu_model->action_unref(action);
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
      return ws_parallel_action_free(action);
    else
      DIE_IMPOSSIBLE;
  
  static void ws_action_cancel(surf_action_t action)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      surf_network_model->action_cancel(action);
 -  else if (action->model_type == surf_cpu_model)
 -    surf_cpu_model->action_cancel(action);
 -  else if (action->model_type == surf_workstation_model)
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    action->model_obj->action_cancel(action);
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
      ws_parallel_action_cancel(action);
    else
      DIE_IMPOSSIBLE;
  static void ws_action_state_set(surf_action_t action,
                                  e_surf_action_state_t state)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      surf_network_model->action_state_set(action, state);
 -  else if (action->model_type == surf_cpu_model)
 -    surf_cpu_model->action_state_set(action, state);
 -  else if (action->model_type == surf_workstation_model)
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    action->model_obj->action_state_set(action, state);
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
      surf_action_state_set(action, state);
    else
      DIE_IMPOSSIBLE;
    return;
  }
  
 -static double ws_share_resources(double now)
 +
 +/* -- The callback functions at model_private -- */
 +/* These callbacks are also used for the vm workstation model. */
 +int ws_resource_used(void *resource_id)
  {
 -  return -1.0;
 +  /* This model does not implement parallel tasks */
 +  THROW_IMPOSSIBLE;
 +  return -1;
 +}
 +
 +double ws_share_resources(surf_model_t workstation_model, double now)
 +{
 +  /* Invoke the share_resources() callback of the physical cpu model object and
 +   * the network model objects. */
 +  surf_model_t cpu_model = workstation_model->extension.workstation.cpu_model;
 +  surf_model_t net_model = surf_network_model;
 +
 +  double min_by_cpu = cpu_model->model_private->share_resources(cpu_model, now);
 +  double min_by_net = net_model->model_private->share_resources(net_model, now);
 +
 + // XBT_INFO("%p %s min_by_cpu, %s %f min_by_net %f", workstation_model, cpu_model->name, min_by_cpu, net_model->name, 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 */
  }
  
 -static void ws_update_actions_state(double now, double delta)
 +void ws_update_actions_state(surf_model_t workstation_model, double now, double delta)
  {
    return;
  }
  
 -static void ws_update_resource_state(void *id,
 -                                     tmgr_trace_event_t event_type,
 -                                     double value, double date)
 +void ws_update_resource_state(void *id, tmgr_trace_event_t event_type, double value, double date)
  {
 -  THROW_IMPOSSIBLE;             /* This model does not implement parallel tasks */
 +  /* This model does not implement parallel tasks */
 +  THROW_IMPOSSIBLE;
  }
  
 -static surf_action_t ws_execute(void *workstation, double size)
 +void ws_finalize(surf_model_t workstation_model)
 +{
 +  surf_model_exit(workstation_model);
 +  workstation_model = NULL;
 +}
 +
 +
 +
 +surf_action_t ws_execute(void *workstation, double size)
  {
    surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
    return cpu->model->extension.cpu.execute(workstation, size);
  
  static surf_action_t ws_action_sleep(void *workstation, double duration)
  {
 -  return surf_cpu_model->extension.cpu.
 -      sleep(workstation, duration);
 +  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
 +  return cpu->model->extension.cpu.sleep(workstation, duration);
  }
  
  static void ws_action_suspend(surf_action_t action)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      surf_network_model->suspend(action);
 -  else if (action->model_type == surf_cpu_model)
 -    surf_cpu_model->suspend(action);
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    action->model_obj->suspend(action);
    else
      DIE_IMPOSSIBLE;
  }
  
  static void ws_action_resume(surf_action_t action)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      surf_network_model->resume(action);
 -  else if (action->model_type == surf_cpu_model)
 -    surf_cpu_model->resume(action);
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    action->model_obj->resume(action);
    else
      DIE_IMPOSSIBLE;
  }
  
  static int ws_action_is_suspended(surf_action_t action)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      return surf_network_model->is_suspended(action);
 -  if (action->model_type == surf_cpu_model)
 -    return surf_cpu_model->is_suspended(action);
 +  if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    return action->model_obj->is_suspended(action);
    DIE_IMPOSSIBLE;
    return -1;
  }
  static void ws_action_set_max_duration(surf_action_t action,
                                         double duration)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      surf_network_model->set_max_duration(action, duration);
 -  else if (action->model_type == surf_cpu_model)
 -    surf_cpu_model->set_max_duration(action, duration);
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    action->model_obj->set_max_duration(action, duration);
    else
      DIE_IMPOSSIBLE;
  }
  
 -static void ws_action_set_priority(surf_action_t action, double priority)
 +void ws_action_set_priority(surf_action_t action, double priority)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      surf_network_model->set_priority(action, priority);
 -  else if (action->model_type == surf_cpu_model)
 -    surf_cpu_model->set_priority(action, priority);
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    action->model_obj->set_priority(action, priority);
    else
      DIE_IMPOSSIBLE;
  }
  #ifdef HAVE_TRACING
  static void ws_action_set_category(surf_action_t action, const char *category)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      surf_network_model->set_category(action, category);
 -  else if (action->model_type == surf_cpu_model)
 -    surf_cpu_model->set_category(action, category);
 +  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    action->model_obj->set_category(action, category);
    else
      DIE_IMPOSSIBLE;
  }
  #ifdef HAVE_LATENCY_BOUND_TRACKING
  static int ws_get_latency_limited(surf_action_t action)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      return surf_network_model->get_latency_limited(action);
    else
      return 0;
  
  static double ws_action_get_remains(surf_action_t action)
  {
 -  if (action->model_type == surf_network_model)
 +  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
      return surf_network_model->get_remains(action);
 -  if (action->model_type == surf_cpu_model)
 -    return surf_cpu_model->get_remains(action);
 +  if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
 +    return action->model_obj->get_remains(action);
    DIE_IMPOSSIBLE;
    return -1.0;
  }
@@@ -248,22 -215,22 +248,22 @@@ static surf_action_t ws_communicate(voi
                    dst->net_elm, size, rate);
  }
  
 -static e_surf_resource_state_t ws_get_state(void *workstation)
 +e_surf_resource_state_t ws_get_state(void *workstation)
  {
 -  return surf_cpu_model->extension.cpu.
 -      get_state(workstation);
 +  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
 +  return cpu->model->extension.cpu.get_state(workstation);
  }
  
  static double ws_get_speed(void *workstation, double load)
  {
 -  return surf_cpu_model->extension.cpu.
 -      get_speed(workstation, load);
 +  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
 +  return cpu->model->extension.cpu.get_speed(workstation, load);
  }
  
  static double ws_get_available_speed(void *workstation)
  {
 -  return surf_cpu_model->extension.cpu.
 -      get_available_speed(workstation);
 +  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
 +  return cpu->model->extension.cpu.get_available_speed(workstation);
  }
  
  static surf_action_t ws_execute_parallel_task(int workstation_nb,
@@@ -327,6 -294,12 +327,6 @@@ static int ws_link_shared(const void *l
    return surf_network_model->extension.network.link_shared(link);
  }
  
 -static void ws_finalize(void)
 -{
 -  surf_model_exit(surf_workstation_model);
 -  surf_workstation_model = NULL;
 -}
 -
  static xbt_dict_t ws_get_properties(const void *ws)
  {
    return surf_resource_properties(surf_cpu_resource_priv(ws));
@@@ -411,89 -384,82 +411,87 @@@ static surf_action_t ws_action_ls(void 
  
  static void surf_workstation_model_init_internal(void)
  {
 -  surf_workstation_model = surf_model_init();
 -
 -  surf_workstation_model->name = "Workstation";
 -  surf_workstation_model->action_unref = ws_action_unref;
 -  surf_workstation_model->action_cancel = ws_action_cancel;
 -  surf_workstation_model->action_state_set = ws_action_state_set;
 -
 -  surf_workstation_model->model_private->resource_used = ws_resource_used;
 -  surf_workstation_model->model_private->share_resources =
 -      ws_share_resources;
 -  surf_workstation_model->model_private->update_actions_state =
 -      ws_update_actions_state;
 -  surf_workstation_model->model_private->update_resource_state =
 -      ws_update_resource_state;
 -  surf_workstation_model->model_private->finalize = ws_finalize;
 -
 -  surf_workstation_model->suspend = ws_action_suspend;
 -  surf_workstation_model->resume = ws_action_resume;
 -  surf_workstation_model->is_suspended = ws_action_is_suspended;
 -  surf_workstation_model->set_max_duration = ws_action_set_max_duration;
 -  surf_workstation_model->set_priority = ws_action_set_priority;
 -#ifdef HAVE_TRACING
 -  surf_workstation_model->set_category = ws_action_set_category;
 -#endif
 -  surf_workstation_model->get_remains = ws_action_get_remains;
 -#ifdef HAVE_LATENCY_BOUND_TRACKING
 -  surf_workstation_model->get_latency_limited = ws_get_latency_limited;
 -#endif
 -
 -  surf_workstation_model->extension.workstation.execute = ws_execute;
 -  surf_workstation_model->extension.workstation.sleep = ws_action_sleep;
 -  surf_workstation_model->extension.workstation.get_state = ws_get_state;
 -  surf_workstation_model->extension.workstation.get_speed = ws_get_speed;
 -  surf_workstation_model->extension.workstation.get_available_speed =
 -      ws_get_available_speed;
 -
 -  surf_workstation_model->extension.workstation.communicate =
 -      ws_communicate;
 -  surf_workstation_model->extension.workstation.get_route = ws_get_route;
 -  surf_workstation_model->extension.workstation.execute_parallel_task =
 -      ws_execute_parallel_task;
 -  surf_workstation_model->extension.workstation.get_link_bandwidth =
 -      ws_get_link_bandwidth;
 -  surf_workstation_model->extension.workstation.get_link_latency =
 -      ws_get_link_latency;
 -  surf_workstation_model->extension.workstation.link_shared =
 -      ws_link_shared;
 -  surf_workstation_model->extension.workstation.get_properties =
 -      ws_get_properties;
 -
 -  surf_workstation_model->extension.workstation.open = ws_action_open;
 -  surf_workstation_model->extension.workstation.close = ws_action_close;
 -  surf_workstation_model->extension.workstation.read = ws_action_read;
 -  surf_workstation_model->extension.workstation.write = ws_action_write;
 -  surf_workstation_model->extension.workstation.stat = ws_action_stat;
 -  surf_workstation_model->extension.workstation.unlink = ws_action_unlink;
 -  surf_workstation_model->extension.workstation.ls = ws_action_ls;
 +  surf_model_t model = surf_model_init();
 +
 +  model->name = "Workstation";
 +  model->type = SURF_MODEL_TYPE_WORKSTATION;
 +  model->action_unref     = ws_action_unref;
 +  model->action_cancel    = ws_action_cancel;
 +  model->action_state_set = ws_action_state_set;
 +
 +  model->model_private->resource_used         = ws_resource_used;
 +  model->model_private->share_resources       = ws_share_resources;
 +  model->model_private->update_actions_state  = ws_update_actions_state;
 +  model->model_private->update_resource_state = ws_update_resource_state;
 +  model->model_private->finalize              = ws_finalize;
 +
 +  model->suspend          = ws_action_suspend;
 +  model->resume           = ws_action_resume;
 +  model->is_suspended     = ws_action_is_suspended;
 +  model->set_max_duration = ws_action_set_max_duration;
 +  model->set_priority     = ws_action_set_priority;
 +  #ifdef HAVE_TRACING
 +  model->set_category     = ws_action_set_category;
 +  #endif
 +  model->get_remains      = ws_action_get_remains;
 +  #ifdef HAVE_LATENCY_BOUND_TRACKING
 +  model->get_latency_limited = ws_get_latency_limited;
 +  #endif
 +
 +  /* For VM support, we have a surf cpu model object for each workstation model
 +   * object. The physical workstation model object has the cpu model object of
 +   * the physical machine layer. */
 +  xbt_assert(surf_cpu_model_pm);
 +  model->extension.workstation.cpu_model = surf_cpu_model_pm;
 +
 +  model->extension.workstation.execute   = ws_execute;
 +  model->extension.workstation.sleep     = ws_action_sleep;
 +  model->extension.workstation.get_state = ws_get_state;
 +  model->extension.workstation.get_speed = ws_get_speed;
 +  model->extension.workstation.get_available_speed = ws_get_available_speed;
 +
 +  model->extension.workstation.communicate           = ws_communicate;
 +  model->extension.workstation.get_route             = ws_get_route;
 +  model->extension.workstation.execute_parallel_task = ws_execute_parallel_task;
 +  model->extension.workstation.get_link_bandwidth    = ws_get_link_bandwidth;
 +  model->extension.workstation.get_link_latency      = ws_get_link_latency;
 +  model->extension.workstation.link_shared           = ws_link_shared;
 +  model->extension.workstation.get_properties        = ws_get_properties;
 +
 +  model->extension.workstation.open   = ws_action_open;
 +  model->extension.workstation.close  = ws_action_close;
 +  model->extension.workstation.read   = ws_action_read;
 +  model->extension.workstation.write  = ws_action_write;
 +  model->extension.workstation.stat   = ws_action_stat;
 +  model->extension.workstation.unlink = ws_action_unlink;
 +  model->extension.workstation.ls     = ws_action_ls;
 +
 +  surf_workstation_model = model;
  }
  
  void surf_workstation_model_init_current_default(void)
  {
 -  surf_workstation_model_init_internal();
    xbt_cfg_setdefault_int(_sg_cfg_set, "network/crosstraffic", 1);
    surf_cpu_model_init_Cas01();
    surf_network_model_init_LegrandVelho();
  
 +  /* surf_cpu_mode_pm and surf_network_model must be initialized in advance. */
 +  xbt_assert(surf_cpu_model_pm);
 +  xbt_assert(surf_network_model);
 +  surf_workstation_model_init_internal();
 +
    xbt_dynar_push(model_list, &surf_workstation_model);
 +  xbt_dynar_push(model_list_invoke, &surf_workstation_model);
    sg_platf_host_add_cb(workstation_new);
- //  sg_platf_postparse_add_cb(create_workstations);
  }
  
  void surf_workstation_model_init_compound()
  {
 -
 -  xbt_assert(surf_cpu_model, "No CPU model defined yet!");
 +  xbt_assert(surf_cpu_model_pm, "No CPU model defined yet!");
    xbt_assert(surf_network_model, "No network model defined yet!");
 +
    surf_workstation_model_init_internal();
    xbt_dynar_push(model_list, &surf_workstation_model);
 +  xbt_dynar_push(model_list_invoke, &surf_workstation_model);
    sg_platf_host_add_cb(workstation_new);
- //  sg_platf_postparse_add_cb(create_workstations);
  }
@@@ -216,13 -216,13 +216,13 @@@ static int ptask_resource_used(void *re
  
  }
  
 -static double ptask_share_resources(double now)
 +static double ptask_share_resources(surf_model_t workstation_model, double now)
  {
    s_surf_action_workstation_L07_t s_action;
    surf_action_workstation_L07_t action = NULL;
  
    xbt_swag_t running_actions =
 -      surf_workstation_model->states.running_action_set;
 +      workstation_model->states.running_action_set;
    double min = generic_maxmin_share_resources(running_actions,
                                                xbt_swag_offset(s_action,
                                                                variable),
    return min;
  }
  
 -static void ptask_update_actions_state(double now, double delta)
 +static void ptask_update_actions_state(surf_model_t workstation_model, double now, double delta)
  {
    double deltap = 0.0;
    surf_action_workstation_L07_t action = NULL;
    surf_action_workstation_L07_t next_action = NULL;
    xbt_swag_t running_actions =
 -      surf_workstation_model->states.running_action_set;
 +      workstation_model->states.running_action_set;
  
    xbt_swag_foreach_safe(action, next_action, running_actions) {
      deltap = delta;
@@@ -344,8 -344,8 +344,8 @@@ static void ptask_update_resource_state
    link_L07_t nw_link = id;
  
    if (nw_link->type == SURF_WORKSTATION_RESOURCE_LINK) {
-     XBT_DEBUG("Updating link %s (%p) with value=%f",
-       surf_resource_name(nw_link), nw_link, value);
+     XBT_DEBUG("Updating link %s (%p) with value=%f for date=%g",
+       surf_resource_name(nw_link), nw_link, value, date);
      if (event_type == nw_link->bw_event) {
        nw_link->bw_current = value;
        lmm_update_constraint_bound(ptask_maxmin_system, nw_link->constraint,
    return;
  }
  
 -static void ptask_finalize(void)
 +static void ptask_finalize(surf_model_t workstation_model)
  {
    xbt_dict_free(&ptask_parallel_task_link_set);
  
 -  surf_model_exit(surf_workstation_model);
 -  surf_workstation_model = NULL;
 +  surf_model_exit(workstation_model);
 +  workstation_model = NULL;
    surf_model_exit(surf_network_model);
    surf_network_model = NULL;
  
@@@ -856,7 -856,6 +856,7 @@@ static void ptask_model_init_internal(v
    surf_workstation_model->set_priority = ptask_action_set_priority;
    surf_workstation_model->get_remains = ptask_action_get_remains;
    surf_workstation_model->name = "Workstation ptask_L07";
 +  surf_workstation_model->type = SURF_MODEL_TYPE_WORKSTATION;
  
    surf_workstation_model->model_private->resource_used =
        ptask_resource_used;
  void surf_workstation_model_init_ptask_L07(void)
  {
    XBT_INFO("surf_workstation_model_init_ptask_L07");
 -  xbt_assert(!surf_cpu_model, "CPU model type already defined");
 +  xbt_assert(!surf_cpu_model_pm, "CPU model type already defined");
    xbt_assert(!surf_network_model, "network model type already defined");
    ptask_define_callbacks();
    ptask_model_init_internal();
diff --combined src/xbt/ex.c
@@@ -46,6 -46,7 +46,7 @@@
  #include "portable.h"           /* execinfo when available */
  #include "xbt/ex.h"
  #include "xbt/str.h"
+ #include "xbt/synchro_core.h"
  #include "xbt_modinter.h"       /* backtrace initialization headers */
  
  #include "xbt/ex_interface.h"
@@@ -222,9 -223,6 +223,9 @@@ const char *xbt_ex_catname(xbt_errcat_
      return "tracing error";
    case io_error:
      return "io error";
 +  case vm_error:
 +    return "vm error";
 +
    }
    return "INVALID ERROR";
  }