+ SD_CHECK_INIT_DONE();
+ xbt_assert0(task != NULL, "Invalid parameter");
+ xbt_assert1(task->state_set == sd_global->scheduled_task_set ||
+ task->state_set == sd_global->ready_task_set ||
+ task->state_set == sd_global->running_task_set ||
+ task->state_set == sd_global->failed_task_set,
+ "Task %s: the state must be SD_SCHEDULED, SD_READY, SD_RUNNING or SD_FAILED",
+ SD_task_get_name(task));
+
+ if (__SD_task_is_scheduled_or_ready(task)) /* if the task is scheduled or ready */
+ __SD_task_destroy_scheduling_data(task);
+
+ if (__SD_task_is_running(task)) /* the task should become SD_FAILED */
+ surf_workstation_resource->common_public->action_cancel(task->surf_action);
+ else
+ __SD_task_set_state(task, SD_NOT_SCHEDULED);
+ task->remains = task->amount;
+ task->start_time = -1.0;
+}
+
+/* Destroys the data memorised by SD_task_schedule. Task state must be SD_SCHEDULED or SD_READY.
+ */
+static void __SD_task_destroy_scheduling_data(SD_task_t task) {
+ SD_CHECK_INIT_DONE();
+ xbt_assert1(__SD_task_is_scheduled_or_ready(task),
+ "Task '%s' must be SD_SCHEDULED or SD_READY", SD_task_get_name(task));
+ xbt_free(task->workstation_list);
+ xbt_free(task->computation_amount);
+ xbt_free(task->communication_amount);
+}
+
+/* Runs a task. This function is called by SD_simulate() when a scheduled task can start
+ * (ie when its dependencies are satisfied).
+ */
+surf_action_t __SD_task_run(SD_task_t task) {
+ SD_CHECK_INIT_DONE();
+ xbt_assert0(task != NULL, "Invalid parameter");
+ xbt_assert2(__SD_task_is_ready(task), "Task '%s' is not ready! Task state: %d",
+ SD_task_get_name(task), SD_task_get_state(task));
+
+ task->surf_action = surf_workstation_resource->extension_public->
+ execute_parallel_task(task->workstation_nb,
+ task->workstation_list,
+ task->computation_amount,
+ task->communication_amount,
+ task->amount,
+ task->rate);
+
+ DEBUG1("surf_action = %p", task->surf_action);
+
+ __SD_task_destroy_scheduling_data(task); /* now the scheduling data are not useful anymore */
+ __SD_task_set_state(task, SD_RUNNING);
+
+ return task->surf_action;
+}
+/* Remove all dependencies associated with a task. This function is called when the task is destroyed.
+ */
+static void __SD_task_remove_dependencies(SD_task_t task) {
+ /* we must destroy the dependencies carefuly (with SD_dependency_remove)
+ because each one is stored twice */
+ SD_dependency_t dependency;
+ while (xbt_dynar_length(task->tasks_before) > 0) {
+ xbt_dynar_get_cpy(task->tasks_before, 0, &dependency);
+ SD_task_dependency_remove(dependency->src, dependency->dst);
+ }
+
+ while (xbt_dynar_length(task->tasks_after) > 0) {
+ xbt_dynar_get_cpy(task->tasks_after, 0, &dependency);
+ SD_task_dependency_remove(dependency->src, dependency->dst);
+ }
+}
+
+/**
+ * \brief Returns the start time of a task
+ *
+ * The task state must be SD_RUNNING, SD_DONE or SD_FAILED.
+ *
+ * \task a task
+ * \return the start time of this task
+ */
+double SD_task_get_start_time(SD_task_t task) {
+ SD_CHECK_INIT_DONE();
+ xbt_assert0(task != NULL, "Invalid parameter");
+ if(task->surf_action)
+ return surf_workstation_resource->common_public->action_get_start_time(task->surf_action);
+ else
+ return task->start_time;
+}
+
+/**
+ * \brief Returns the finish time of a task
+ *
+ * The task state must be SD_RUNNING, SD_DONE or SD_FAILED.
+ * If the state is not completed yet, the returned value is an
+ * estimation of the task finish time. This value can fluctuate
+ * until the task is completed.
+ *
+ * \task a task
+ * \return the start time of this task
+ */
+double SD_task_get_finish_time(SD_task_t task) {
+ SD_CHECK_INIT_DONE();
+ xbt_assert0(task != NULL, "Invalid parameter");
+
+ if(task->surf_action)
+ return surf_workstation_resource->common_public->action_get_finish_time(task->surf_action); /* should never happen as actions are destroyed right after their completion */
+ else
+ return task->finish_time;