Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
the comment of some lines add a bug in the execution of dags.
[simgrid.git] / src / simdag / sd_task.c
index 0de83bb..0b0c4cb 100644 (file)
@@ -52,6 +52,8 @@ SD_task_t SD_task_create(const char *name, void *data, double amount)
   /* dependencies */
   task->tasks_before = xbt_dynar_new(sizeof(SD_dependency_t), NULL);
   task->tasks_after = xbt_dynar_new(sizeof(SD_dependency_t), NULL);
+  task->unsatisfied_dependencies=0;
+  task->is_not_ready=0;
 
   /* scheduling parameters */
   task->workstation_nb = 0;
@@ -101,7 +103,7 @@ void SD_task_set_data(SD_task_t task, void *data)
  *
  * \param task a task
  * \return the current \ref e_SD_task_state_t "state" of this task:
- * #SD_NOT_SCHEDULED, #SD_SCHEDULED, #SD_READY, #SD_RUNNING, #SD_DONE or #SD_FAILED
+ * #SD_NOT_SCHEDULED, #SD_SCHEDULED, #SD_RUNNABLE, #SD_RUNNING, #SD_DONE or #SD_FAILED
  * \see e_SD_task_state_t
  */
 e_SD_task_state_t SD_task_get_state(SD_task_t task)
@@ -120,11 +122,14 @@ void __SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state)
   case SD_NOT_SCHEDULED:
     task->state_set = sd_global->not_scheduled_task_set;
     break;
+  case SD_SCHEDULABLE:
+    task->state_set = sd_global->schedulable_task_set;
+    break;
   case SD_SCHEDULED:
     task->state_set = sd_global->scheduled_task_set;
     break;
-  case SD_READY:
-    task->state_set = sd_global->ready_task_set;
+  case SD_RUNNABLE:
+    task->state_set = sd_global->runnable_task_set;
     break;
   case SD_IN_FIFO:
     task->state_set = sd_global->in_fifo_task_set;
@@ -150,7 +155,7 @@ void __SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state)
   task->state = new_state;
 
   if (task->watch_points & new_state) {
-    INFO1("Watch point reached with task '%s'!", SD_task_get_name(task));
+    VERB1("Watch point reached with task '%s'!", SD_task_get_name(task));
     sd_global->watch_point_reached = 1;
     SD_task_unwatch(task, new_state);   /* remove the watch point */
   }
@@ -290,10 +295,11 @@ void SD_task_dump(SD_task_t task)
   char *statename;
 
   INFO1("Displaying task %s",SD_task_get_name(task));
-  statename=bprintf("%s %s %s %s %s %s %s",
+  statename=bprintf("%s %s %s %s %s %s %s %s",
       (task->state&SD_NOT_SCHEDULED?"not scheduled":""),
+      (task->state&SD_SCHEDULABLE?"schedulable":""),
       (task->state&SD_SCHEDULED?"scheduled":""),
-      (task->state&SD_READY?"ready":"not ready"),
+      (task->state&SD_RUNNABLE?"runnable":"not runnable"),
       (task->state&SD_IN_FIFO?"in fifo":""),
       (task->state&SD_RUNNING?"running":""),
       (task->state&SD_DONE?"done":""),
@@ -314,6 +320,7 @@ void SD_task_dump(SD_task_t task)
     }
   }
   INFO1("  - amount: %.0f",SD_task_get_amount(task));
+  INFO1("  - Dependencies to satisfy: %d", task->unsatisfied_dependencies);
   if (xbt_dynar_length(task->tasks_before)) {
     INFO0("  - pre-dependencies:");
     xbt_dynar_foreach(task->tasks_before,counter,dependency) {
@@ -361,7 +368,7 @@ static void __SD_task_dependency_destroy(void *dependency)
  * \brief Adds a dependency between two tasks
  *
  * \a dst will depend on \a src, ie \a dst will not start before \a src is finished.
- * Their \ref e_SD_task_state_t "state" must be #SD_NOT_SCHEDULED, #SD_SCHEDULED or #SD_READY.
+ * Their \ref e_SD_task_state_t "state" must be #SD_NOT_SCHEDULED, #SD_SCHEDULED or #SD_RUNNABLE.
  *
  * \param name the name of the new dependency (can be \c NULL)
  * \param data the user data you want to associate with this dependency (can be \c NULL)
@@ -389,16 +396,16 @@ void SD_task_dependency_add(const char *name, void *data, SD_task_t src,
            "Cannot add a dependency between task '%s' and itself",
            SD_task_get_name(src));
 
-  if (!__SD_task_is_not_scheduled(src)
-      && !__SD_task_is_scheduled_or_ready(src))
+  if (!__SD_task_is_not_scheduled(src) && !__SD_task_is_schedulable(src)
+      && !__SD_task_is_scheduled_or_runnable(src))
     THROW1(arg_error, 0,
-           "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULED or SD_READY",
+           "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULABLE, SD_SCHEDULED or SD_RUNNABLE",
            SD_task_get_name(src));
 
-  if (!__SD_task_is_not_scheduled(dst)
-      && !__SD_task_is_scheduled_or_ready(dst))
+  if (!__SD_task_is_not_scheduled(dst) && !__SD_task_is_schedulable(dst)
+      && !__SD_task_is_scheduled_or_runnable(dst))
     THROW1(arg_error, 0,
-           "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULED or SD_READY",
+           "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULABLE, SD_SCHEDULED or SD_RUNNABLE",
            SD_task_get_name(dst));
 
   DEBUG2("SD_task_dependency_add: src = %s, dst = %s", SD_task_get_name(src),
@@ -426,10 +433,13 @@ void SD_task_dependency_add(const char *name, void *data, SD_task_t src,
   xbt_dynar_push(src->tasks_after, &dependency);
   xbt_dynar_push(dst->tasks_before, &dependency);
 
-  /* if the task was ready, then dst->tasks_before is not empty anymore,
+  dst->unsatisfied_dependencies++;
+  dst->is_not_ready++;
+
+  /* if the task was runnable, then dst->tasks_before is not empty anymore,
      so we must go back to state SD_SCHEDULED */
-  if (__SD_task_is_ready(dst)) {
-    DEBUG1("SD_task_dependency_add: %s was ready and becomes scheduled!",
+  if (__SD_task_is_runnable(dst)) {
+    DEBUG1("SD_task_dependency_add: %s was runnable and becomes scheduled!",
            SD_task_get_name(dst));
     __SD_task_set_state(dst, SD_SCHEDULED);
   }
@@ -516,6 +526,8 @@ void SD_task_dependency_remove(SD_task_t src, SD_task_t dst)
     if (dependency->src == src) {
       xbt_dynar_remove_at(dynar, i, NULL);
       __SD_task_dependency_destroy(dependency);
+      dst->unsatisfied_dependencies--;
+      dst->is_not_ready--;
       found = 1;
     }
   }
@@ -525,9 +537,17 @@ void SD_task_dependency_remove(SD_task_t src, SD_task_t dst)
               SD_task_get_name(dst), SD_task_get_name(src),
               SD_task_get_name(src), SD_task_get_name(dst));
 
-  /* if the task was scheduled and dst->tasks_before is empty now, we can make it ready */
-  if (xbt_dynar_length(dst->tasks_before) == 0 && __SD_task_is_scheduled(dst))
-    __SD_task_set_state(dst, SD_READY);
+  /* if the task was scheduled and dst->tasks_before is empty now, we can make it runnable */
+
+   if (dst->unsatisfied_dependencies == 0){
+          if (__SD_task_is_scheduled(dst))
+                  __SD_task_set_state(dst, SD_RUNNABLE);
+          else
+                  __SD_task_set_state(dst, SD_SCHEDULABLE);
+   }
+
+   if (dst->is_not_ready == 0)
+          __SD_task_set_state(dst, SD_SCHEDULABLE);
 
   /*  __SD_print_dependencies(src);
      __SD_print_dependencies(dst); */
@@ -571,9 +591,9 @@ void *SD_task_dependency_get_data(SD_task_t src, SD_task_t dst)
 static void __SD_print_watch_points(SD_task_t task)
 {
   static const int state_masks[] =
-    { SD_SCHEDULED, SD_RUNNING, SD_READY, SD_DONE, SD_FAILED };
+    { SD_SCHEDULABLE, SD_SCHEDULED, SD_RUNNING, SD_RUNNABLE, SD_DONE, SD_FAILED };
   static const char *state_names[] =
-    { "scheduled", "running", "ready", "done", "failed" };
+    { "schedulable", "scheduled", "running", "runnable", "done", "failed" };
   int i;
 
   INFO2("Task '%s' watch points (%x): ", SD_task_get_name(task),
@@ -682,13 +702,13 @@ double SD_task_get_execution_time(SD_task_t task,
 static XBT_INLINE void SD_task_do_schedule(SD_task_t task) {
   SD_CHECK_INIT_DONE();
 
-   if (!__SD_task_is_not_scheduled(task))
+   if (!__SD_task_is_not_scheduled(task) && !__SD_task_is_schedulable(task) )
      THROW1(arg_error, 0, "Task '%s' has already been scheduled",
             SD_task_get_name(task));
 
  /* update the task state */
-  if (xbt_dynar_length(task->tasks_before) == 0)
-    __SD_task_set_state(task, SD_READY);
+  if (task->unsatisfied_dependencies == 0)
+    __SD_task_set_state(task, SD_RUNNABLE);
   else
     __SD_task_set_state(task, SD_SCHEDULED);
 }
@@ -747,7 +767,7 @@ void SD_task_schedule(SD_task_t task, int workstation_count,
 /**
  * \brief Unschedules a task
  *
- * The task state must be #SD_SCHEDULED, #SD_READY, #SD_RUNNING or #SD_FAILED.
+ * The task state must be #SD_SCHEDULED, #SD_RUNNABLE, #SD_RUNNING or #SD_FAILED.
  * If you call this function, the task state becomes #SD_NOT_SCHEDULED.
  * Call SD_task_schedule() to schedule it again.
  *
@@ -760,33 +780,37 @@ void SD_task_unschedule(SD_task_t task)
   xbt_assert0(task != NULL, "Invalid parameter");
 
   if (task->state_set != sd_global->scheduled_task_set &&
-      task->state_set != sd_global->ready_task_set &&
+      task->state_set != sd_global->runnable_task_set &&
       task->state_set != sd_global->running_task_set &&
       task->state_set != sd_global->failed_task_set)
     THROW1(arg_error, 0,
-           "Task %s: the state must be SD_SCHEDULED, SD_READY, SD_RUNNING or SD_FAILED",
+           "Task %s: the state must be SD_SCHEDULED, SD_RUNNABLE, 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 */
+  if (__SD_task_is_scheduled_or_runnable(task) /* if the task is scheduled or runnable */
       && task->kind == SD_TASK_NOT_TYPED) /* Don't free scheduling data for typed tasks */
     __SD_task_destroy_scheduling_data(task);
 
   if (__SD_task_is_running(task))       /* the task should become SD_FAILED */
     surf_workstation_model->action_cancel(task->surf_action);
-  else
-    __SD_task_set_state(task, SD_NOT_SCHEDULED);
+  else {
+         if (task->unsatisfied_dependencies == 0)
+                 __SD_task_set_state(task, SD_SCHEDULABLE);
+         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.
+/* Destroys the data memorized by SD_task_schedule. Task state must be SD_SCHEDULED or SD_RUNNABLE.
  */
 static void __SD_task_destroy_scheduling_data(SD_task_t task)
 {
   SD_CHECK_INIT_DONE();
-  if (!__SD_task_is_scheduled_or_ready(task) && !__SD_task_is_in_fifo(task))
+  if (!__SD_task_is_scheduled_or_runnable(task) && !__SD_task_is_in_fifo(task))
     THROW1(arg_error, 0,
-           "Task '%s' must be SD_SCHEDULED, SD_READY or SD_IN_FIFO",
+           "Task '%s' must be SD_SCHEDULED, SD_RUNNABLE or SD_IN_FIFO",
            SD_task_get_name(task));
 
   xbt_free(task->computation_amount);
@@ -806,8 +830,8 @@ void __SD_task_really_run(SD_task_t task)
 
   SD_CHECK_INIT_DONE();
   xbt_assert0(task != NULL, "Invalid parameter");
-  xbt_assert2(__SD_task_is_ready_or_in_fifo(task),
-              "Task '%s' is not ready or in a fifo! Task state: %d",
+  xbt_assert2(__SD_task_is_runnable_or_in_fifo(task),
+              "Task '%s' is not runnable or in a fifo! Task state: %d",
               SD_task_get_name(task), SD_task_get_state(task));
   xbt_assert1(task->workstation_list != NULL,
               "Task '%s': workstation_list is NULL!", SD_task_get_name(task));
@@ -904,7 +928,7 @@ void __SD_task_really_run(SD_task_t task)
 
 }
 
-/* Tries to run a task. This function is called by SD_simulate() when a scheduled task becomes SD_READY
+/* 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.
@@ -919,8 +943,8 @@ int __SD_task_try_to_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",
+  xbt_assert2(__SD_task_is_runnable(task),
+              "Task '%s' is not runnable! Task state: %d",
               SD_task_get_name(task), SD_task_get_state(task));
 
 
@@ -1175,8 +1199,8 @@ void SD_task_destroy(SD_task_t task)
   DEBUG1("Destroying task %s...", SD_task_get_name(task));
 
   __SD_task_remove_dependencies(task);
-  /* if the task was scheduled or ready we have to free the scheduling parameters */
-  if (__SD_task_is_scheduled_or_ready(task))
+  /* if the task was scheduled or runnable we have to free the scheduling parameters */
+  if (__SD_task_is_scheduled_or_runnable(task))
     __SD_task_destroy_scheduling_data(task);
   xbt_swag_remove(task,task->state_set);
 
@@ -1289,7 +1313,7 @@ void SD_task_schedulev(SD_task_t task, int count, const SD_workstation_t*list) {
         task->communication_amount[2]);
 
   }
-  /* Iterate over all childs and parent being COMM_E2E to say where I am located (and start them if ready) */
+  /* Iterate over all childs and parent being COMM_E2E to say where I am located (and start them if runnable) */
   if (task->kind == SD_TASK_COMP_SEQ) {
     VERB3("Schedule computation task %s on %s. It costs %.f flops",
         SD_task_get_name(task),SD_workstation_get_name(task->workstation_list[0]),
@@ -1299,7 +1323,9 @@ void SD_task_schedulev(SD_task_t task, int count, const SD_workstation_t*list) {
       SD_task_t before = dep->src;
       if (before->kind == SD_TASK_COMM_E2E) {
         before->workstation_list[1] = task->workstation_list[0];
-        if (before->workstation_list[0] && __SD_task_is_not_scheduled(before)) {
+
+        if (before->workstation_list[0] &&
+                       (__SD_task_is_schedulable(before) || __SD_task_is_not_scheduled(before))) {
           SD_task_do_schedule(before);
           VERB4("Auto-Schedule comm task %s between %s -> %s. It costs %.f bytes",
               SD_task_get_name(before),
@@ -1312,7 +1338,9 @@ void SD_task_schedulev(SD_task_t task, int count, const SD_workstation_t*list) {
       SD_task_t after = dep->dst;
       if (after->kind == SD_TASK_COMM_E2E) {
         after->workstation_list[0] = task->workstation_list[0];
-        if (after->workstation_list[1] && __SD_task_is_not_scheduled(after)) {
+                               //J-N : Why did you comment on these line (this comment add a bug I think)?
+        if (after->workstation_list[1] && (__SD_task_is_not_scheduled(after) ||
+                       __SD_task_is_schedulable(after))) {
           SD_task_do_schedule(after);
           VERB4("Auto-Schedule comm task %s between %s -> %s. It costs %.f bytes",
               SD_task_get_name(after),