+ xbt_assert2(__SD_task_is_running(task), "Bad state of task '%s': %d",
+ SD_task_get_name(task), SD_task_get_state(task));
+
+}
+
+/* Tries to run a task. This function is called by SD_simulate() when a scheduled task becomes SD_READY
+ * (ie when its dependencies are satisfied).
+ * If one of the workstations where the task is scheduled on is busy (in sequential mode),
+ * the task doesn't start.
+ * Returns whether the task has started.
+ */
+int __SD_task_try_to_run(SD_task_t task) {
+
+ int can_start = 1;
+ int i;
+ SD_workstation_t workstation;
+
+ 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));
+
+
+ for (i = 0; i < task->workstation_nb; i++) {
+ can_start = !__SD_workstation_is_busy(task->workstation_list[i]);
+ }
+
+ DEBUG2("Task '%s' can start: %d", SD_task_get_name(task), can_start);
+
+ if (!can_start) { /* if the task cannot start and is not in the fifos yet*/
+ for (i = 0; i < task->workstation_nb; i++) {
+ workstation = task->workstation_list[i];
+ if (workstation->access_mode == SD_WORKSTATION_SEQUENTIAL_ACCESS) {
+ DEBUG2("Pushing task '%s' in the fifo of workstation '%s'", SD_task_get_name(task),
+ SD_workstation_get_name(workstation));
+ xbt_fifo_push(workstation->task_fifo, task);
+ }
+ }
+ __SD_task_set_state(task, SD_IN_FIFO);
+ xbt_assert2(__SD_task_is_in_fifo(task), "Bad state of task '%s': %d",
+ SD_task_get_name(task), SD_task_get_state(task));
+ DEBUG1("Task '%s' state is now SD_IN_FIFO", SD_task_get_name(task));
+ }
+ else {
+ __SD_task_really_run(task);
+ }
+
+ return can_start;
+}
+
+/* This function is called by SD_simulate when a task is done.
+ * It updates task->state and task->action and executes if necessary the tasks
+ * which were waiting in fifos for the end of `task'
+ */
+void __SD_task_just_done(SD_task_t task) {
+ int i, j;
+ SD_workstation_t workstation;
+
+ SD_task_t candidate;
+ int candidate_nb = 0;
+ int candidate_capacity = 8;
+ SD_task_t *candidates;
+ int can_start = 1;
+
+ SD_CHECK_INIT_DONE();
+ xbt_assert0(task != NULL, "Invalid parameter");
+ xbt_assert1(__SD_task_is_running(task), "The task must be running! Task state: %d", SD_task_get_state(task));
+ xbt_assert1(task->workstation_list != NULL, "Task '%s': workstation_list is NULL!", SD_task_get_name(task));
+
+
+ candidates = xbt_new(SD_task_t, 8);
+
+ __SD_task_set_state(task, SD_DONE);
+ surf_workstation_model->common_public->action_free(task->surf_action);
+ task->surf_action = NULL;
+
+ DEBUG0("Looking for candidates");
+
+ /* if the task was executed on sequential workstations,
+ maybe we can execute the next task of the fifo for each workstation */
+ for (i = 0; i < task->workstation_nb; i++) {
+ workstation = task->workstation_list[i];
+ DEBUG2("Workstation '%s': access_mode = %d", SD_workstation_get_name(workstation), workstation->access_mode);
+ if (workstation->access_mode == SD_WORKSTATION_SEQUENTIAL_ACCESS) {
+ xbt_assert1(workstation->task_fifo != NULL, "Workstation '%s' has sequential access but no fifo!",
+ SD_workstation_get_name(workstation));
+ xbt_assert2(workstation->current_task = task, "Workstation '%s': current task should be '%s'",
+ SD_workstation_get_name(workstation), SD_task_get_name(task));
+
+ /* the task is over so we can release the workstation */
+ workstation->current_task = NULL;
+
+ DEBUG0("Getting candidate in fifo");
+ candidate = xbt_fifo_get_item_content(xbt_fifo_get_first_item(workstation->task_fifo));
+
+ if (candidate != NULL) {
+ DEBUG1("Candidate: '%s'", SD_task_get_name(candidate));
+ xbt_assert2(__SD_task_is_in_fifo(candidate), "Bad state of candidate '%s': %d",
+ SD_task_get_name(candidate), SD_task_get_state(candidate));
+ }
+
+ DEBUG1("Candidate in fifo: %p", candidate);
+
+ /* if there was a task waiting for my place */
+ if (candidate != NULL) {
+ /* Unfortunately, we are not sure yet that we can execute the task now,
+ because the task can be waiting more deeply in some other workstation's fifos...
+ So we memorize all candidate tasks, and then we will check for each candidate
+ whether or not all its workstations are available. */
+
+ /* realloc if necessary */
+ if (candidate_nb == candidate_capacity) {
+ candidate_capacity *= 2;
+ candidates = xbt_realloc(candidates, sizeof(SD_task_t) * candidate_capacity);
+ }
+
+ /* register the candidate */
+ candidates[candidate_nb++] = candidate;
+ candidate->fifo_checked = 0;
+ }
+ }
+ }
+
+ DEBUG1("Candidates found: %d", candidate_nb);
+
+ /* now we check every candidate task */
+ for (i = 0; i < candidate_nb; i++) {
+ candidate = candidates[i];
+
+ if (candidate->fifo_checked) {
+ continue; /* we have already evaluated that task*/
+ }
+
+ xbt_assert2(__SD_task_is_in_fifo(candidate), "Bad state of candidate '%s': %d",
+ SD_task_get_name(candidate), SD_task_get_state(candidate));
+
+ for (j = 0; j < candidate->workstation_nb && can_start; j++) {
+ workstation = candidate->workstation_list[j];