+ simdata_task_t simdata = NULL;
+ m_process_t self = MSG_process_self();
+ CHECK_HOST();
+
+ simdata = task->simdata;
+ xbt_assert0((!simdata->compute) && (task->simdata->using == 1),"This task is executed somewhere else. Go fix your code!");
+
+ DEBUG1("Computing on %s", MSG_process_self()->simdata->m_host->name);
+
+ simdata->using++;
+ SIMIX_mutex_lock(simdata->mutex);
+ simdata->compute = SIMIX_action_execute(SIMIX_host_self(), task->name, simdata->computation_amount);
+ SIMIX_action_set_priority(simdata->compute, simdata->priority);
+
+ self->simdata->waiting_task = task;
+ SIMIX_register_action_to_condition(simdata->compute, simdata->cond);
+ SIMIX_cond_wait(simdata->cond, simdata->mutex);
+ SIMIX_unregister_action_to_condition(simdata->compute, simdata->cond);
+ self->simdata->waiting_task = NULL;
+
+ SIMIX_mutex_unlock(simdata->mutex);
+ simdata->using--;
+
+ if (SIMIX_action_get_state(task->simdata->compute) == SURF_ACTION_DONE)
+ {
+ /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
+ SIMIX_action_destroy(task->simdata->compute);
+ simdata->computation_amount = 0.0;
+ simdata->comm = NULL;
+ simdata->compute = NULL;
+ MSG_RETURN(MSG_OK);
+ }
+ else if(SIMIX_host_get_state(SIMIX_host_self()) == 0)
+ {
+ /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
+ SIMIX_action_destroy(task->simdata->compute);
+ simdata->comm = NULL;
+ simdata->compute = NULL;
+ MSG_RETURN(MSG_HOST_FAILURE);
+ }
+ else
+ {
+ /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
+ SIMIX_action_destroy(task->simdata->compute);
+ simdata->comm = NULL;
+ simdata->compute = NULL;
+ MSG_RETURN(MSG_TASK_CANCELLED);
+ }
+}
+
+/** \ingroup m_task_management
+ * \brief Creates a new #m_task_t (a parallel one....).
+ *
+ * A constructor for #m_task_t taking six arguments and returning the
+ corresponding object.
+ * \param name a name for the object. It is for user-level information
+ and can be NULL.
+ * \param host_nb the number of hosts implied in the parallel task.
+ * \param host_list an array of \p host_nb m_host_t.
+ * \param computation_amount an array of \p host_nb
+ doubles. computation_amount[i] is the total number of operations
+ that have to be performed on host_list[i].
+ * \param communication_amount an array of \p host_nb* \p host_nb doubles.
+ * \param data a pointer to any data 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_task_get_data.
+ * \see m_task_t
+ * \return The new corresponding object.
+ */
+m_task_t
+MSG_parallel_task_create(const char *name,int host_nb, const m_host_t * host_list, double *computation_amount, double *communication_amount, void *data)
+{
+ int i;
+ simdata_task_t simdata = xbt_new0(s_simdata_task_t, 1);
+ m_task_t task = xbt_new0(s_m_task_t, 1);
+ task->simdata = simdata;
+
+ /* Task structure */
+ task->name = xbt_strdup(name);
+ task->data = data;
+
+ /* Simulator Data */
+ simdata->computation_amount = 0;
+ simdata->message_size = 0;
+ simdata->cond = SIMIX_cond_init();
+ simdata->mutex = SIMIX_mutex_init();
+ simdata->compute = NULL;
+ simdata->comm = NULL;
+ simdata->rate = -1.0;
+ simdata->using = 1;
+ simdata->sender = NULL;
+ simdata->receiver = NULL;
+ simdata->source = NULL;
+
+ simdata->host_nb = host_nb;
+ simdata->host_list = xbt_new0(smx_host_t, host_nb);
+ simdata->comp_amount = computation_amount;
+ simdata->comm_amount = communication_amount;
+
+ for (i = 0; i < host_nb; i++)
+ simdata->host_list[i] = host_list[i]->simdata->smx_host;
+
+ return task;
+}
+
+MSG_error_t
+MSG_parallel_task_execute(m_task_t task)
+{
+ simdata_task_t simdata = NULL;
+ m_process_t self = MSG_process_self();
+ CHECK_HOST();
+
+ simdata = task->simdata;
+
+ xbt_assert0((!simdata->compute) && (task->simdata->using == 1),"This task is executed somewhere else. Go fix your code!");
+
+ xbt_assert0(simdata->host_nb,"This is not a parallel task. Go to hell.");
+
+ DEBUG1("Computing on %s", MSG_process_self()->simdata->m_host->name);
+
+ simdata->using++;
+
+ SIMIX_mutex_lock(simdata->mutex);
+ simdata->compute =
+ SIMIX_action_parallel_execute(task->name, simdata->host_nb, simdata->host_list, simdata->comp_amount, simdata->comm_amount, 1.0, -1.0);
+
+ self->simdata->waiting_task = task;
+ SIMIX_register_action_to_condition(simdata->compute, simdata->cond);
+ SIMIX_cond_wait(simdata->cond, simdata->mutex);
+ SIMIX_unregister_action_to_condition(simdata->compute, simdata->cond);
+ self->simdata->waiting_task = NULL;
+
+
+ SIMIX_mutex_unlock(simdata->mutex);
+ simdata->using--;
+
+ if (SIMIX_action_get_state(task->simdata->compute) == SURF_ACTION_DONE)
+ {
+ /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
+ SIMIX_action_destroy(task->simdata->compute);
+ simdata->computation_amount = 0.0;
+ simdata->comm = NULL;
+ simdata->compute = NULL;
+ MSG_RETURN(MSG_OK);
+ }
+ else if(SIMIX_host_get_state(SIMIX_host_self()) == 0)
+ {
+ /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
+ SIMIX_action_destroy(task->simdata->compute);
+ simdata->comm = NULL;
+ simdata->compute = NULL;
+ MSG_RETURN(MSG_HOST_FAILURE);
+ }
+ else
+ {
+ /* action ended, set comm and compute = NULL, the actions is already destroyed in the main function */
+ SIMIX_action_destroy(task->simdata->compute);
+ simdata->comm = NULL;
+ simdata->compute = NULL;
+ MSG_RETURN(MSG_TASK_CANCELLED);
+ }
+
+}
+
+
+/** \ingroup msg_gos_functions
+ * \brief Sleep for the specified number of seconds
+ *
+ * Makes the current process sleep until \a time seconds have elapsed.
+ *
+ * \param nb_sec a number of second
+ */
+MSG_error_t
+MSG_process_sleep(double nb_sec)
+{
+ smx_action_t act_sleep;
+ m_process_t proc = MSG_process_self();
+ smx_mutex_t mutex;
+ smx_cond_t cond;
+
+ /* create action to sleep */
+ act_sleep = SIMIX_action_sleep(SIMIX_process_get_host(proc->simdata->s_process), nb_sec);
+
+ mutex = SIMIX_mutex_init();
+ SIMIX_mutex_lock(mutex);
+
+ /* create conditional and register action to it */
+ cond = SIMIX_cond_init();
+
+ SIMIX_register_action_to_condition(act_sleep, cond);
+ SIMIX_cond_wait(cond, mutex);
+ SIMIX_unregister_action_to_condition(act_sleep, cond);
+ SIMIX_mutex_unlock(mutex);
+
+ /* remove variables */
+ SIMIX_cond_destroy(cond);
+ SIMIX_mutex_destroy(mutex);
+
+ if (SIMIX_action_get_state(act_sleep) == SURF_ACTION_DONE)
+ {
+ if (SIMIX_host_get_state(SIMIX_host_self()) == SURF_CPU_OFF)
+ {
+ SIMIX_action_destroy(act_sleep);
+ MSG_RETURN(MSG_HOST_FAILURE);
+ }
+ }
+ else
+ {
+ SIMIX_action_destroy(act_sleep);
+ MSG_RETURN(MSG_HOST_FAILURE);
+ }
+
+ MSG_RETURN(MSG_OK);
+}
+
+/** \ingroup msg_gos_functions
+ * \brief Return the number of MSG tasks currently running on
+ * the host of the current running process.
+ */
+static int
+MSG_get_msgload(void)
+{
+ xbt_die("not implemented yet");
+ return 0;
+}
+
+
+
+/** \ingroup msg_gos_functions
+ * \brief Listen on \a channel and waits for receiving a task from \a host.
+ *
+ * It takes three parameters.
+ * \param task a memory location for storing a #m_task_t. It will
+ hold a task when this function will return. Thus \a task should not
+ be equal to \c NULL and \a *task should be equal to \c NULL. If one of
+ those two condition does not hold, there will be a warning message.
+ * \param channel the channel on which the agent should be
+ listening. This value has to be >=0 and < than the maximal
+ number of channels fixed with MSG_set_channel_number().
+ * \param host the host that is to be watched.
+ * \return #MSG_FATAL if \a task is equal to \c NULL, #MSG_WARNING
+ if \a *task is not equal to \c NULL, and #MSG_OK otherwise.
+ */
+MSG_error_t
+MSG_task_get_from_host(m_task_t * task, m_channel_t channel, m_host_t host)
+{
+ return MSG_task_get_ext(task, channel, -1, host);