-/* Copyright (c) 2007-2009 Da SimGrid Team. All rights reserved. */
+/* Copyright (c) 2006, 2007, 2008, 2009, 2010. The SimGrid Team.
+ * All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
/* 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;
*
* \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)
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;
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 */
}
return task->name;
}
+/** @brief Allows to change the name of a task */
+void SD_task_set_name(SD_task_t task, const char *name) {
+ xbt_free(task->name);
+ task->name = xbt_strdup(name);
+}
+
/** @brief Returns the dynar of the parents of a task
*
* \param task a 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":""),
}
}
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) {
* \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)
"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),
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);
}
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;
}
}
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); */
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),
}
return max_time;
}
-static inline void SD_task_do_schedule(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);
}
const double *computation_amount,
const double *communication_amount, double rate)
{
- xbt_assert0(workstation_count > 0, "workstation_nb must be positive");
-
int communication_nb;
+ task->workstation_nb = 0;
+ task->rate = 0;
+ xbt_assert0(workstation_count > 0, "workstation_nb must be positive");
task->workstation_nb = workstation_count;
task->rate = rate;
/**
* \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.
*
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);
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));
}
-/* 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.
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));
for (i = 0; i < task->workstation_nb; i++) {
- can_start = !__SD_workstation_is_busy(task->workstation_list[i]);
+ can_start = can_start &&
+ !__SD_workstation_is_busy(task->workstation_list[i]);
}
DEBUG2("Task '%s' can start: %d", SD_task_get_name(task), can_start);
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);
}
-static inline SD_task_t SD_task_create_sized(const char*name,void*data,double amount,int ws_count) {
+static XBT_INLINE SD_task_t SD_task_create_sized(const char*name,void*data,double amount,int ws_count) {
SD_task_t task = SD_task_create(name,data,amount);
task->communication_amount = xbt_new0(double,ws_count*ws_count);
task->computation_amount = xbt_new0(double,ws_count);
*/
void SD_task_schedulev(SD_task_t task, int count, const SD_workstation_t*list) {
int i;
+ SD_dependency_t dep;
+ unsigned int cpt;
xbt_assert1(task->kind != 0,"Task %s is not typed. Cannot automatically schedule it.",SD_task_get_name(task));
switch(task->kind) {
case SD_TASK_COMM_E2E:
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]),
task->computation_amount[0]);
- SD_dependency_t dep;
- unsigned int cpt;
+
xbt_dynar_foreach(task->tasks_before,cpt,dep) {
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),
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)) {
- SD_task_do_schedule(after);
- VERB4("Auto-Schedule comm task %s between %s -> %s. It costs %.f bytes",
- SD_task_get_name(after),
- SD_workstation_get_name(after->workstation_list[0]),SD_workstation_get_name(after->workstation_list[1]),
- after->communication_amount[2]);
-
- }
+// 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),
+// SD_workstation_get_name(after->workstation_list[0]),SD_workstation_get_name(after->workstation_list[1]),
+// after->communication_amount[2]);
+//
+// }
}
}
}