Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Starting simix mecanism for io.
[simgrid.git] / src / simix / smx_process.c
index f3096b9..bf04014 100644 (file)
@@ -8,20 +8,94 @@
 #include "xbt/sysdep.h"
 #include "xbt/log.h"
 #include "xbt/dict.h"
-#include "msg/mailbox.h"
+#include "mc/mc.h"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
                                 "Logging specific to SIMIX (process)");
 
+unsigned long simix_process_maxpid = 0;
+
 /**
- * \brief Move a process to the list of process to destroy. *
+ * \brief Returns the current agent.
+ *
+ * This functions returns the currently running SIMIX process.
+ *
+ * \return The SIMIX process
  */
-void SIMIX_process_cleanup(void *arg)
+XBT_INLINE smx_process_t SIMIX_process_self(void)
 {
-  xbt_swag_remove(arg, simix_global->process_to_run);
-  xbt_swag_remove(arg, simix_global->process_list);
-  xbt_swag_remove(arg, ((smx_process_t) arg)->smx_host->process_list);
-  xbt_swag_insert(arg, simix_global->process_to_destroy);
+  smx_context_t self_context = SIMIX_context_self();
+
+  return self_context ? SIMIX_context_get_data(self_context) : NULL;
+}
+
+/**
+ * \brief Returns whether a process has pending asynchronous communications.
+ * \return true if there are asynchronous communications in this process
+ */
+int SIMIX_process_has_pending_comms(smx_process_t process) {
+
+  return xbt_fifo_size(process->comms) > 0;
+}
+
+/**
+ * \brief Moves a process to the list of processes to destroy.
+ */
+void SIMIX_process_cleanup(smx_process_t process)
+{
+  XBT_DEBUG("Cleanup process %s (%p), waiting action %p",
+      process->name, process, process->waiting_action);
+
+  /* cancel non-blocking communications */
+  smx_action_t action;
+  while ((action = xbt_fifo_pop(process->comms))) {
+
+    /* make sure no one will finish the comm after this process is destroyed,
+     * because src_proc or dst_proc would be an invalid pointer */
+    SIMIX_comm_cancel(action);
+
+    if (action->comm.src_proc == process) {
+      XBT_DEBUG("Found an unfinished send comm %p (detached = %d), state %d, src = %p, dst = %p",
+          action, action->comm.detached, action->state, action->comm.src_proc, action->comm.dst_proc);
+      action->comm.src_proc = NULL;
+
+      if (action->comm.detached) {
+         if (action->comm.refcount == 0) {
+           XBT_DEBUG("Increase the refcount before destroying it since it's detached");
+           /* I'm not supposed to destroy a detached comm from the sender side,
+            * unless there is no receiver matching the rdv */
+           action->comm.refcount++;
+           SIMIX_comm_destroy(action);
+         }
+         else {
+           XBT_DEBUG("Don't destroy it since its refcount is %d", action->comm.refcount);
+         }
+      } else {
+        SIMIX_comm_destroy(action);
+      }
+    }
+    else if (action->comm.dst_proc == process){
+      XBT_DEBUG("Found an unfinished recv comm %p, state %d, src = %p, dst = %p",
+          action, action->state, action->comm.src_proc, action->comm.dst_proc);
+      action->comm.dst_proc = NULL;
+
+      if (action->comm.detached && action->comm.refcount == 1
+          && action->comm.src_proc != NULL) {
+        /* the comm will be freed right now, remove it from the sender */
+        xbt_fifo_remove(action->comm.src_proc->comms, action);
+      }
+      SIMIX_comm_destroy(action);
+    }
+    else {
+      xbt_die("Communication action %p is in my list but I'm not the sender "
+          "or the receiver", action);
+    }
+  }
+
+  /*xbt_swag_remove(process, simix_global->process_to_run);*/
+  xbt_swag_remove(process, simix_global->process_list);
+  xbt_swag_remove(process, process->smx_host->process_list);
+  xbt_swag_insert(process, simix_global->process_to_destroy);
 }
 
 /** 
@@ -38,13 +112,12 @@ void SIMIX_process_empty_trash(void)
     SIMIX_context_free(process->context);
 
     /* Free the exception allocated at creation time */
-    if (process->exception)
-      free(process->exception);
-    if (process->properties)
-      xbt_dict_free(&process->properties);
+    free(process->running_ctx);
+    xbt_dict_free(&process->properties);
+
+    xbt_fifo_free(process->comms);
 
     free(process->name);
-    process->name = NULL;
     free(process);
   }
 }
@@ -54,450 +127,503 @@ void SIMIX_process_empty_trash(void)
  */
 void SIMIX_create_maestro_process()
 {
-  smx_process_t process = NULL;
-  process = xbt_new0(s_smx_process_t, 1);
-
-  /* Process data */
-  process->name = (char *) "";
-
-  process->exception = xbt_new(ex_ctx_t, 1);
-  XBT_CTX_INITIALIZE(process->exception);
-
-  /* Create a dummy context for maestro */
-  process->context = SIMIX_context_new(NULL, 0, NULL, NULL, NULL);
+  smx_process_t maestro = NULL;
+
+  /* Create maestro process and intilialize it */
+  maestro = xbt_new0(s_smx_process_t, 1);
+  maestro->pid = simix_process_maxpid++;
+  maestro->name = (char *) "";
+  maestro->running_ctx = xbt_new(xbt_running_ctx_t, 1);
+  XBT_RUNNING_CTX_INITIALIZE(maestro->running_ctx);
+  maestro->context = SIMIX_context_new(NULL, 0, NULL, NULL, maestro);
+  maestro->request.issuer = maestro;
+
+  simix_global->maestro_process = maestro;
+  return;
+}
 
-  /* Set it as the maestro process */
-  simix_global->maestro_process = process;
-  simix_global->current_process = process;
+/**
+ * \brief Same as SIMIX_process_create() but with only one argument (used by timers).
+ * \return the process created
+ */
+smx_process_t SIMIX_process_create_from_wrapper(smx_process_arg_t args) {
+
+  smx_process_t process;
+  simix_global->create_process_function(
+      &process,
+      args->name,
+      args->code,
+      args->data,
+      args->hostname,
+      args->argc,
+      args->argv,
+      args->properties);
 
-  return;
+  return process;
 }
 
 /**
- * \brief Creates and runs a new #smx_process_t.
+ * \brief Internal function to create a process.
  *
- * A constructor for #m_process_t taking four arguments and returning the corresponding object. The structure (and the corresponding thread) is created, and put in the list of ready process.
+ * This function actually creates the process.
+ * It may be called when a REQ_PROCESS_CREATE request occurs,
+ * or directly for SIMIX internal purposes.
  *
- * \param name a name for the object. It is for user-level information and can be NULL.
- * \param data a pointer to any data one may want to attach to the new object.  It is for user-level information and can be NULL. It can be retrieved with the function \ref MSG_process_get_data.
- * \param host the location where the new agent is executed.
- * \param argc first argument passed to \a code
- * \param argv second argument passed to \a code
- * \param clean_process_function The cleanup function of user process. It will be called when the process finish. This function have to call the SIMIX_process_cleanup.
- * \see smx_process_t
- * \return The new corresponding object.
+ * \return the process created
  */
-smx_process_t SIMIX_process_create(const char *name,
-                                   xbt_main_func_t code, void *data,
-                                   const char *hostname, int argc,
-                                   char **argv, xbt_dict_t properties)
-{
-  smx_process_t process = NULL;
+void SIMIX_process_create(smx_process_t *process,
+                          const char *name,
+                          xbt_main_func_t code,
+                          void *data,
+                          const char *hostname,
+                          int argc, char **argv,
+                          xbt_dict_t properties) {
+
+  *process = NULL;
   smx_host_t host = SIMIX_host_get_by_name(hostname);
 
-  DEBUG2("Start process %s on host %s", name, hostname);
+  XBT_DEBUG("Start process %s on host %s", name, hostname);
 
   if (!SIMIX_host_get_state(host)) {
-    WARN2("Cannot launch process '%s' on failed host '%s'", name, hostname);
-    return NULL;
+    XBT_WARN("Cannot launch process '%s' on failed host '%s'", name,
+          hostname);
   }
-  process = xbt_new0(s_smx_process_t, 1);
+  else {
+    *process = xbt_new0(s_smx_process_t, 1);
 
-  xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
+    xbt_assert(((code != NULL) && (host != NULL)), "Invalid parameters");
 
-  /* Process data */
-  process->name = xbt_strdup(name);
-  process->smx_host = host;
-  process->mutex = NULL;
-  process->cond = NULL;
-  process->iwannadie = 0;
-  process->data = data;
+    /* Process data */
+    (*process)->pid = simix_process_maxpid++;
+    (*process)->name = xbt_strdup(name);
+    (*process)->smx_host = host;
+    (*process)->data = data;
+    (*process)->comms = xbt_fifo_new();
+    (*process)->request.issuer = *process;
+
+    XBT_VERB("Create context %s", (*process)->name);
+    (*process)->context = SIMIX_context_new(code, argc, argv,
+       simix_global->cleanup_process_function, *process);
 
-  VERB1("Create context %s", process->name);
-  process->context = SIMIX_context_new(code, argc, argv,
-                                       simix_global->cleanup_process_function,
-                                       process);
+    (*process)->running_ctx = xbt_new(xbt_running_ctx_t, 1);
+    XBT_RUNNING_CTX_INITIALIZE((*process)->running_ctx);
 
-  process->exception = xbt_new(ex_ctx_t, 1);
-  XBT_CTX_INITIALIZE(process->exception);
+    /* Add properties */
+    (*process)->properties = properties;
 
-  /* Add properties */
-  process->properties = properties;
+    /* Add the process to it's host process list */
+    xbt_swag_insert(*process, host->process_list);
 
-  /* Add the process to it's host process list */
-  xbt_swag_insert(process, host->process_list);
+    XBT_DEBUG("Start context '%s'", (*process)->name);
 
-  DEBUG1("Start context '%s'", process->name);
+    /* Now insert it in the global process list and in the process to run list */
+    xbt_swag_insert(*process, simix_global->process_list);
+    XBT_DEBUG("Inserting %s(%s) in the to_run list", (*process)->name, host->name);
+    xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, *process);
+  }
+}
 
-  /* Now insert it in the global process list and in the process to run list */
-  xbt_swag_insert(process, simix_global->process_list);
-  DEBUG2("Inserting %s(%s) in the to_run list", process->name, host->name);
-  xbt_swag_insert(process, simix_global->process_to_run);
+/**
+ * \brief Executes the processes from simix_global->process_to_run.
+ *
+ * The processes of simix_global->process_to_run are run (in parallel if
+ * possible).  On exit, simix_global->process_to_run is empty, and
+ * simix_global->process_that_ran contains the list of processes that just ran.
+ * The two lists are swapped so, be careful when using them before and after a
+ * call to this function.
+ */
+void SIMIX_process_runall(void)
+{
+  SIMIX_context_runall();
 
-  return process;
+  xbt_dynar_t tmp = simix_global->process_that_ran;
+  simix_global->process_that_ran = simix_global->process_to_run;
+  simix_global->process_to_run = tmp;
+  xbt_dynar_reset(simix_global->process_to_run);
 }
 
-/** \brief Kill a SIMIX process
+/**
+ * \brief Internal function to kill a SIMIX process.
  *
- * This function simply kills a \a process... scarry isn't it ? :).
- * \param process poor victim
+ * This function may be called when a REQ_PROCESS_KILL request occurs,
+ * or directly for SIMIX internal purposes.
  *
+ * \param process poor victim
  */
-void SIMIX_process_kill(smx_process_t process)
-{
-  DEBUG2("Killing process %s on %s", process->name, process->smx_host->name);
+void SIMIX_process_kill(smx_process_t process) {
 
-  process->iwannadie = 1;
+  XBT_DEBUG("Killing process %s on %s", process->name, process->smx_host->name);
 
-  /* If I'm killing myself then stop otherwise schedule the process to kill
-   * Two different behaviors, if I'm killing my self, remove from mutex and condition and stop. Otherwise, first we must schedule the process, wait its ending and after remove it from mutex and condition */
-  if (process == SIMIX_process_self()) {
-    /* Cleanup if we were waiting for something */
-    if (process->mutex)
-      xbt_swag_remove(process, process->mutex->sleeping);
+  process->context->iwannadie = 1;
+  process->blocked = 0;
+  process->suspended = 0;
+  /* FIXME: set doexception to 0 also? */
 
-    if (process->cond)
-      xbt_swag_remove(process, process->cond->sleeping);
-    if (process->waiting_action) {
-      SIMIX_unregister_action_to_condition(process->waiting_action, process->cond);
-      SIMIX_action_destroy(process->waiting_action);
-    }
+  /* destroy the blocking action if any */
+  if (process->waiting_action) {
 
-    if (process->sem) {
-      xbt_swag_remove(process, process->sem->sleeping);
+    switch (process->waiting_action->type) {
 
-      if (process->waiting_action) {
-        SIMIX_unregister_action_to_semaphore(process->waiting_action, process->sem);
-        SIMIX_action_destroy(process->waiting_action);
-      }
+      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_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->request);
+       SIMIX_synchro_destroy(process->waiting_action);
+       break;
+
+      case SIMIX_ACTION_IO:
+    SIMIX_io_destroy(process->waiting_action);
+    break;
     }
+  }
 
-    SIMIX_context_stop(process->context);
+  xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
+}
 
-  } else {
-    DEBUG4("%s(%p) here! killing %s(%p)",
-        simix_global->current_process->name,simix_global->current_process,
-        process->name,process);
+/**
+ * \brief Kills all running processes.
+ * \param issuer this one will not be killed
+ */
+void SIMIX_process_killall(smx_process_t issuer)
+{
+  smx_process_t p = NULL;
 
-    /* Cleanup if it were waiting for something */
-    if (process->mutex) {
-      xbt_swag_remove(process, process->mutex->sleeping);
-      process->mutex = NULL;
+  while ((p = xbt_swag_extract(simix_global->process_list))) {
+    if (p != issuer) {
+      SIMIX_process_kill(p);
     }
+  }
+
+  SIMIX_context_runall(simix_global->process_to_run);
+
+  SIMIX_process_empty_trash();
+}
+
+void SIMIX_process_change_host(smx_process_t process,
+                              smx_host_t dest)
+{
+  xbt_assert((process != NULL), "Invalid parameters");
+  xbt_swag_remove(process, process->smx_host->process_list);
+  process->smx_host = dest;
+  xbt_swag_insert(process, dest->process_list);
+}
+
+void SIMIX_pre_process_change_host(smx_process_t process, smx_host_t dest)
+{
+  process->new_host = dest;
+}
+
+void SIMIX_pre_process_suspend(smx_req_t req)
+{
+  smx_process_t process = req->process_suspend.process;
+  SIMIX_process_suspend(process, req->issuer);
+
+  if (process != req->issuer) {
+    SIMIX_request_answer(req);
+  }
+  /* If we are suspending ourselves, then just do not replay the request. */
+}
+
+void SIMIX_process_suspend(smx_process_t process, smx_process_t issuer)
+{
+  xbt_assert((process != NULL), "Invalid parameters");
 
-    if (process->cond) {
-      xbt_swag_remove(process, process->cond->sleeping);
+  if (process->suspended) {
+    XBT_DEBUG("Process '%s' is already suspended", process->name);
+    return;
+  }
+
+  process->suspended = 1;
+
+  /* If we are suspending another process, and it is waiting on an action,
+     suspend its action. */
+  if (process != issuer) {
+
+    if (process->waiting_action) {
+
+      switch (process->waiting_action->type) {
 
-      if (process->waiting_action) {
-        SIMIX_unregister_action_to_condition(process->waiting_action, process->cond);
-        SIMIX_action_destroy(process->waiting_action);
+        case SIMIX_ACTION_EXECUTE:
+        case SIMIX_ACTION_PARALLEL_EXECUTE:
+          SIMIX_host_execution_suspend(process->waiting_action);
+          break;
+
+        case SIMIX_ACTION_COMMUNICATE:
+          SIMIX_comm_suspend(process->waiting_action);
+          break;
+
+        case SIMIX_ACTION_SLEEP:
+          SIMIX_process_sleep_suspend(process->waiting_action);
+          break;
+
+        default:
+          xbt_die("Internal error in SIMIX_process_suspend: unexpected action type %d",
+              process->waiting_action->type);
       }
-      process->cond = NULL;
     }
+  }
+}
+
+void SIMIX_process_resume(smx_process_t process, smx_process_t issuer)
+{
+  xbt_assert((process != NULL), "Invalid parameters");
+
+  if (!process->suspended) {
+    XBT_DEBUG("Process '%s' is not suspended", process->name);
+    return;
+  }
 
-    if (process->sem) {
-       xbt_swag_remove(process, process->sem->sleeping);
+  process->suspended = 0;
+
+  /* If we are resuming another process, resume the action it was waiting for
+     if any. Otherwise add it to the list of process to run in the next round. */
+  if (process != issuer) {
+
+    if (process->waiting_action) {
 
-      if (process->waiting_action) {
-       SIMIX_unregister_action_to_semaphore(process->waiting_action, process->sem);
-       SIMIX_action_destroy(process->waiting_action);
+      switch (process->waiting_action->type) {
+
+        case SIMIX_ACTION_EXECUTE:          
+        case SIMIX_ACTION_PARALLEL_EXECUTE:
+          SIMIX_host_execution_resume(process->waiting_action);
+          break;
+
+        case SIMIX_ACTION_COMMUNICATE:
+          SIMIX_comm_resume(process->waiting_action);
+          break;
+
+        case SIMIX_ACTION_SLEEP:
+          SIMIX_process_sleep_resume(process->waiting_action);
+          break;
+
+        default:
+          xbt_die("Internal error in SIMIX_process_resume: unexpected action type %d",
+              process->waiting_action->type);
       }
-      process->sem = NULL;
     }
+    else {
+      xbt_dynar_push_as(simix_global->process_to_run, smx_process_t, process);
+    }
+  }
+}
+
+int SIMIX_process_get_maxpid(void) {
+  return simix_process_maxpid;
+}
+
+int SIMIX_process_count(void)
+{
+  return xbt_swag_size(simix_global->process_list);
+}
 
-    /* make sure that the process gets awake soon enough, now that we've set its iwannadie to 1 */
-    process->blocked = 0;
-    process->suspended = 0;
-    xbt_swag_insert(process, simix_global->process_to_run);
+void* SIMIX_process_self_get_data(smx_process_t self)
+{
+  xbt_assert(self == SIMIX_process_self(), "This is not the current process");
+
+  if (!self) {
+    return NULL;
   }
+  return SIMIX_process_get_data(self);
 }
 
-/**
- * \brief Return the user data of a #smx_process_t.
- *
- * This functions checks whether \a process is a valid pointer or not and return the user data associated to \a process if it is possible.
- * \param process SIMIX process
- * \return A void pointer to the user data
- */
-XBT_INLINE void *SIMIX_process_get_data(smx_process_t process)
+void SIMIX_process_self_set_data(smx_process_t self, void *data)
 {
-  xbt_assert0((process != NULL), "Invalid parameters");
-  return (process->data);
+  xbt_assert(self == SIMIX_process_self(), "This is not the current process");
+
+  SIMIX_process_set_data(self, data);
 }
 
-/**
- * \brief Set the user data of a #m_process_t.
- *
- * This functions checks whether \a process is a valid pointer or not and set the user data associated to \a process if it is possible.
- * \param process SIMIX process
- * \param data User data
- */
-XBT_INLINE void SIMIX_process_set_data(smx_process_t process, void *data)
+void* SIMIX_process_get_data(smx_process_t process)
 {
-  xbt_assert0((process != NULL), "Invalid parameters");
+  return process->data;
+}
 
+void SIMIX_process_set_data(smx_process_t process, void *data)
+{
   process->data = data;
-  return;
 }
 
-/**
- * \brief Return the location on which an agent is running.
- *
- * This functions checks whether \a process is a valid pointer or not and return the m_host_t corresponding to the location on which \a process is running.
- * \param process SIMIX process
- * \return SIMIX host
- */
-XBT_INLINE smx_host_t SIMIX_process_get_host(smx_process_t process)
+smx_host_t SIMIX_process_get_host(smx_process_t process)
 {
-  xbt_assert0((process != NULL), "Invalid parameters");
-  return (process->smx_host);
+  return process->smx_host;
 }
 
-/**
- * \brief Return the name of an agent.
- *
- * This functions checks whether \a process is a valid pointer or not and return its name.
- * \param process SIMIX process
- * \return The process name
- */
-XBT_INLINE const char *SIMIX_process_get_name(smx_process_t process)
+/* needs to be public and without request because it is called
+   by exceptions and logging events */
+const char* SIMIX_process_self_get_name(void) {
+
+  smx_process_t process = SIMIX_process_self();
+  if (process == NULL || process == simix_global->maestro_process)
+    return "";
+
+  return SIMIX_process_get_name(process);
+}
+
+const char* SIMIX_process_get_name(smx_process_t process)
 {
-  xbt_assert0((process != NULL), "Invalid parameters");
-  return (process->name);
+  return process->name;
 }
 
-/**
- * \brief Changes the name of an agent.
- *
- * This functions checks whether \a process is a valid pointer or not and return its name.
- * \param process SIMIX process
- * \param name The new process name
- */
-XBT_INLINE void SIMIX_process_set_name(smx_process_t process, char *name)
+smx_process_t SIMIX_process_get_by_name(const char* name)
 {
-  xbt_assert0((process != NULL), "Invalid parameters");
-  process->name = name;
+  smx_process_t proc;
+
+  xbt_swag_foreach(proc, simix_global->process_list)
+  {
+    if(!strcmp(name, proc->name))
+      return proc;
+  }
+  return NULL;
 }
 
-/** \ingroup m_process_management
- * \brief Return the properties
- *
- * This functions returns the properties associated with this process
- */
-XBT_INLINE xbt_dict_t SIMIX_process_get_properties(smx_process_t process)
+int SIMIX_process_is_suspended(smx_process_t process)
+{
+  return process->suspended;
+}
+
+xbt_dict_t SIMIX_process_get_properties(smx_process_t process)
 {
   return process->properties;
 }
 
-/**
- * \brief Return the current agent.
- *
- * This functions returns the currently running #smx_process_t.
- * \return The SIMIX process
- */
-XBT_INLINE smx_process_t SIMIX_process_self(void)
+void SIMIX_pre_process_sleep(smx_req_t req)
 {
-  return simix_global ? simix_global->current_process : NULL;
+  if (MC_IS_ENABLED) {
+    MC_process_clock_add(req->issuer, req->process_sleep.duration);
+    req->process_sleep.result = SIMIX_DONE;
+    SIMIX_request_answer(req);
+    return;
+  }
+  smx_action_t action = SIMIX_process_sleep(req->issuer, req->process_sleep.duration);
+  xbt_fifo_push(action->request_list, req);
+  req->issuer->waiting_action = action;
 }
 
-/**
- * \brief Suspend the process.
- *
- * This functions suspend the process by suspending the action on
- * which it was waiting for the completion.
- *
- * \param process SIMIX process
- */
-void SIMIX_process_suspend(smx_process_t process)
+smx_action_t SIMIX_process_sleep(smx_process_t process, double duration)
 {
-  xbt_assert0(process, "Invalid parameters");
+  smx_action_t action;
+  smx_host_t host = process->smx_host;
+
+  /* check if the host is active */
+  if (surf_workstation_model->extension.
+      workstation.get_state(host->host) != SURF_RESOURCE_ON) {
+    THROWF(host_error, 0, "Host %s failed, you cannot call this function",
+           host->name);
+  }
 
-  if (process != SIMIX_process_self()) {
+  action = xbt_mallocator_get(simix_global->action_mallocator);
+  action->type = SIMIX_ACTION_SLEEP;
+  action->name = NULL;
+#ifdef HAVE_TRACING
+  action->category = NULL;
+#endif
 
-    if (process->mutex) {
-      /* process blocked on a mutex or sem, only set suspend=1 */
-      process->suspended = 1;
-    } else if (process->cond) {
-      /* process blocked cond, suspend all actions */
+  action->sleep.host = host;
+  action->sleep.surf_sleep =
+      surf_workstation_model->extension.workstation.sleep(host->host, duration);
 
-      /* temporaries variables */
-      smx_cond_t c;
-      xbt_fifo_item_t i;
-      smx_action_t act;
+  surf_workstation_model->action_data_set(action->sleep.surf_sleep, action);
+  XBT_DEBUG("Create sleep action %p", action);
 
-      process->suspended = 1;
-      c = process->cond;
-      xbt_fifo_foreach(c->actions, i, act, smx_action_t) {
-        SIMIX_action_suspend(act);
-      }
-    } else if (process->sem) {
-      smx_sem_t s;
-      xbt_fifo_item_t i;
-      smx_action_t act;
-
-      process->suspended = 1;
-      s = process->sem;
-      xbt_fifo_foreach(s->actions, i, act, smx_action_t) {
-        SIMIX_action_suspend(act);
-      }
-    } else {
-      process->suspended = 1;
-    }
-  } else {
-    /* process executing, I can create an action and suspend it */
-    smx_action_t dummy;
-    smx_cond_t cond;
-    char name[] = "dummy";
-    process->suspended = 1;
-
-    cond = SIMIX_cond_init();
-    dummy = SIMIX_action_execute(SIMIX_process_get_host(process), name, 0);
-    SIMIX_process_self()->waiting_action = dummy;
-    SIMIX_action_suspend(dummy);
-    SIMIX_register_action_to_condition(dummy, cond);
-    __SIMIX_cond_wait(cond);
-    SIMIX_process_self()->waiting_action = NULL;
-    SIMIX_unregister_action_to_condition(dummy, cond);
-    SIMIX_action_destroy(dummy);
-    SIMIX_cond_destroy(cond);
-  }
-  return;
+  return action;
 }
 
-/**
- * \brief Resume a suspended process.
- *
- * This functions resume a suspended process by resuming the task on which it was waiting for the completion.
- * \param process SIMIX process
- */
-void SIMIX_process_resume(smx_process_t process)
+void SIMIX_post_process_sleep(smx_action_t action)
 {
-  xbt_assert0((process != NULL), "Invalid parameters");
-  SIMIX_CHECK_HOST();
+  smx_req_t req;
+  e_smx_state_t state;
 
-  if (process == SIMIX_process_self())
-    return;
+  while ((req = xbt_fifo_shift(action->request_list))) {
 
-  if (process->mutex) {
-    DEBUG0("Resume process blocked on a mutex or semaphore");
-    process->suspended = 0;     /* It'll wake up by itself when mutex releases */
-    return;
-  } else if (process->cond) {
-    /* temporaries variables */
-    smx_cond_t c;
-    xbt_fifo_item_t i;
-    smx_action_t act;
-    DEBUG0("Resume process blocked on a conditional");
-    process->suspended = 0;
-    c = process->cond;
-    xbt_fifo_foreach(c->actions, i, act, smx_action_t) {
-      SIMIX_action_resume(act);
-    }
-    SIMIX_cond_signal(c);
-    return;
-  } else if (process->sem) {
-    /* temporaries variables */
-    smx_sem_t s;
-    xbt_fifo_item_t i;
-    smx_action_t act;
-    DEBUG0("Resume process blocked on a semaphore");
-    process->suspended = 0;
-    s = process->sem;
-    xbt_fifo_foreach(s->actions, i, act, smx_action_t) {
-      SIMIX_action_resume(act);
+    switch(surf_workstation_model->action_state_get(action->sleep.surf_sleep)){
+      case SURF_ACTION_FAILED:
+        state = SIMIX_SRC_HOST_FAILURE;
+        break;
+
+      case SURF_ACTION_DONE:
+        state = SIMIX_DONE;
+        break;
+
+      default:
+        THROW_IMPOSSIBLE;
+        break;
     }
-    return;
-  } else {
-    process->suspended = 0;
-    xbt_swag_insert(process, simix_global->process_to_run);
+    req->process_sleep.result = state;
+    req->issuer->waiting_action = NULL;
+    SIMIX_request_answer(req);
   }
+  SIMIX_process_sleep_destroy(action);
 }
 
-/**
- * \brief Migrates an agent to another location.
- *
- * This function changes the value of the host on which \a process is running.
- */
-void SIMIX_process_change_host(smx_process_t process, char *source,
-                               char *dest)
+void SIMIX_process_sleep_destroy(smx_action_t action)
 {
-  xbt_assert0((process != NULL), "Invalid parameters");
-  smx_host_t h1 = SIMIX_host_get_by_name(source);
-  smx_host_t h2 = SIMIX_host_get_by_name(dest);
-  process->smx_host = h2;
-  xbt_swag_remove(process, h1->process_list);
-  xbt_swag_insert(process, h2->process_list);
+  XBT_DEBUG("Destroy action %p", action);
+  if (action->sleep.surf_sleep)
+    action->sleep.surf_sleep->model_type->action_unref(action->sleep.surf_sleep);
+  xbt_mallocator_release(simix_global->action_mallocator, action);
 }
 
-/**
- * \brief Returns true if the process is suspended .
- *
- * This checks whether a process is suspended or not by inspecting the task on which it was waiting for the completion.
- * \param process SIMIX process
- * \return 1, if the process is suspended, else 0.
- */
-XBT_INLINE int SIMIX_process_is_suspended(smx_process_t process)
+void SIMIX_process_sleep_suspend(smx_action_t action)
 {
-  xbt_assert0((process != NULL), "Invalid parameters");
-
-  return (process->suspended);
+  surf_workstation_model->suspend(action->sleep.surf_sleep);
 }
 
-/**
- * \brief Returns the amount of SIMIX processes in the system
- *
- * Maestro internal process is not counted, only user code processes are
- */
-XBT_INLINE int SIMIX_process_count()
+void SIMIX_process_sleep_resume(smx_action_t action)
 {
-  return xbt_swag_size(simix_global->process_list);
+  surf_workstation_model->resume(action->sleep.surf_sleep);
 }
 
 /** 
- * Calling this function makes the process process to yield. The process
- * that scheduled it returns from __SIMIX_process_schedule as if nothing
- * had happened.
- * 
- * Only the processes can call this function, giving back the control
- * to the maestro
+ * \brief Calling this function makes the process to yield.
+ *
+ * Only the current process can call this function, giving back the control to
+ * maestro.
+ *
+ * \param self the current process
  */
-void SIMIX_process_yield(void)
+void SIMIX_process_yield(smx_process_t self)
 {
-  DEBUG1("Yield process '%s'", simix_global->current_process->name);
-  xbt_assert0((simix_global->current_process !=
-               simix_global->maestro_process),
-              "You are not supposed to run this function in maestro context!");
-
+  XBT_DEBUG("Yield process '%s'", self->name);
 
   /* Go into sleep and return control to maestro */
-  SIMIX_context_suspend(simix_global->current_process->context);
-  /* Ok, maestro returned control to us */
+  SIMIX_context_suspend(self->context);
 
-  if (simix_global->current_process->iwannadie)
-    SIMIX_context_stop(simix_global->current_process->context);
-}
-
-void SIMIX_process_schedule(smx_process_t new_process)
-{
-  xbt_assert0(simix_global->current_process == simix_global->maestro_process,
-      "This function can only be called from maestro context");
-  DEBUG1("Scheduling context: '%s'", new_process->name);
-
-  /* update the current process */
-  simix_global->current_process = new_process;
+  /* Ok, maestro returned control to us */
+  XBT_DEBUG("Control returned to me: '%s'", self->name);
 
-  /* schedule the context */
-  SIMIX_context_resume(new_process->context);
-  DEBUG1("Resumed from scheduling context: '%s'", new_process->name);
+  if (self->context->iwannadie){
+    XBT_DEBUG("I wanna die!");
+    SIMIX_context_stop(self->context);
+  }
 
-  /* restore the current process to the previously saved process */
-  simix_global->current_process = simix_global->maestro_process;
+  if (self->doexception) {
+    XBT_DEBUG("Wait, maestro left me an exception");
+    self->doexception = 0;
+    RETHROW;
+  }
+  
+  if (self->new_host) {
+    SIMIX_process_change_host(self, self->new_host);
+    self->new_host = NULL;
+  }
 }
 
 /* callback: context fetching */
-ex_ctx_t *SIMIX_process_get_exception(void)
+xbt_running_ctx_t *SIMIX_process_get_running_context(void)
 {
-  return simix_global->current_process->exception;
+  return SIMIX_process_self()->running_ctx;
 }
 
 /* callback: termination */
@@ -506,3 +632,33 @@ void SIMIX_process_exception_terminate(xbt_ex_t * e)
   xbt_ex_display(e);
   abort();
 }
+
+smx_context_t SIMIX_process_get_context(smx_process_t p) {
+  return p->context;
+}
+
+void SIMIX_process_set_context(smx_process_t p,smx_context_t c) {
+  p->context = c;
+}
+
+/**
+ * \brief Returns the list of processes to run.
+ */
+xbt_dynar_t SIMIX_process_get_runnable(void)
+{
+  return simix_global->process_to_run;
+}
+
+/**
+ * \brief Returns the process from PID.
+ */
+smx_process_t SIMIX_process_from_PID(int PID)
+{
+       smx_process_t proc;
+       xbt_swag_foreach(proc, simix_global->process_list)
+       {
+        if(proc->pid == PID)
+        return proc;
+       }
+       return NULL;
+}