+
+/* Tries to run a task. This function is called by SD_simulate() when a scheduled task becomes SD_RUNNABLE
+ * (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_assert(task != NULL, "Invalid parameter");
+ xbt_assert(__SD_task_is_runnable(task),
+ "Task '%s' is not runnable! Task state: %d",
+ SD_task_get_name(task), SD_task_get_state(task));
+
+
+ for (i = 0; i < task->workstation_nb; i++) {
+ can_start = can_start &&
+ !__SD_workstation_is_busy(task->workstation_list[i]);
+ }
+
+ XBT_DEBUG("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) {
+ XBT_DEBUG("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_assert(__SD_task_is_in_fifo(task), "Bad state of task '%s': %d",
+ SD_task_get_name(task), SD_task_get_state(task));
+ XBT_DEBUG("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_assert(task != NULL, "Invalid parameter");
+ xbt_assert(__SD_task_is_running(task),
+ "The task must be running! Task state: %d",
+ SD_task_get_state(task));
+ xbt_assert(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->action_unref(task->surf_action);
+ task->surf_action = NULL;
+
+ XBT_DEBUG("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];
+ XBT_DEBUG("Workstation '%s': access_mode = %d",
+ SD_workstation_get_name(workstation), workstation->access_mode);
+ if (workstation->access_mode == SD_WORKSTATION_SEQUENTIAL_ACCESS) {
+ xbt_assert(workstation->task_fifo != NULL,
+ "Workstation '%s' has sequential access but no fifo!",
+ SD_workstation_get_name(workstation));
+ xbt_assert(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;
+
+ XBT_DEBUG("Getting candidate in fifo");
+ candidate =
+ xbt_fifo_get_item_content(xbt_fifo_get_first_item
+ (workstation->task_fifo));
+
+ if (candidate != NULL) {
+ XBT_DEBUG("Candidate: '%s'", SD_task_get_name(candidate));
+ xbt_assert(__SD_task_is_in_fifo(candidate),
+ "Bad state of candidate '%s': %d",
+ SD_task_get_name(candidate),
+ SD_task_get_state(candidate));
+ }
+
+ XBT_DEBUG("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;
+ }
+ }
+ }
+
+ XBT_DEBUG("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_assert(__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];
+
+ /* I can start on this workstation if the workstation is shared
+ or if I am the first task in the fifo */
+ can_start = workstation->access_mode == SD_WORKSTATION_SHARED_ACCESS
+ || candidate ==
+ xbt_fifo_get_item_content(xbt_fifo_get_first_item
+ (workstation->task_fifo));
+ }
+
+ XBT_DEBUG("Candidate '%s' can start: %d", SD_task_get_name(candidate),
+ can_start);
+
+ /* now we are sure that I can start! */
+ if (can_start) {
+ for (j = 0; j < candidate->workstation_nb && can_start; j++) {
+ workstation = candidate->workstation_list[j];
+
+ /* update the fifo */
+ if (workstation->access_mode == SD_WORKSTATION_SEQUENTIAL_ACCESS) {
+ candidate = xbt_fifo_shift(workstation->task_fifo); /* the return value is stored just for debugging */
+ XBT_DEBUG("Head of the fifo: '%s'",
+ (candidate !=
+ NULL) ? SD_task_get_name(candidate) : "NULL");
+ xbt_assert(candidate == candidates[i],
+ "Error in __SD_task_just_done: bad first task in the fifo");
+ }
+ } /* for each workstation */
+
+ /* finally execute the task */
+ XBT_DEBUG("Task '%s' state: %d", SD_task_get_name(candidate),
+ SD_task_get_state(candidate));
+ __SD_task_really_run(candidate);
+
+ XBT_DEBUG
+ ("Calling __SD_task_is_running: task '%s', state set: %p, running_task_set: %p, is running: %d",
+ SD_task_get_name(candidate), candidate->state_set,
+ sd_global->running_task_set, __SD_task_is_running(candidate));
+ xbt_assert(__SD_task_is_running(candidate),
+ "Bad state of task '%s': %d",
+ SD_task_get_name(candidate),
+ SD_task_get_state(candidate));
+ XBT_DEBUG("Okay, the task is running.");
+
+ } /* can start */
+ candidate->fifo_checked = 1;
+ } /* for each candidate */
+
+ xbt_free(candidates);
+}
+