/* initialisation of SD */
SD_init(&argc, argv);
- /* xbt_log_control_set("sd.thres=debug"); */
+ /* xbt_log_control_set("sd.thres=debug");*/
if (argc < 2) {
INFO1("Usage: %s platform_file", argv[0]);
const SD_workstation_t *workstations = SD_workstation_get_list();
SD_workstation_t w1 = workstations[0];
SD_workstation_t w2 = workstations[1];
+ SD_workstation_set_access_mode(w2, SD_WORKSTATION_SEQUENTIAL_ACCESS);
const char *name1 = SD_workstation_get_name(w1);
const char *name2 = SD_workstation_get_name(w2);
const double computation_amount1 = 2000000;
SD_task_t *changed_tasks;
changed_tasks = SD_simulate(-1.0);
- xbt_assert0(changed_tasks[0] == taskD &&
- changed_tasks[1] == taskB &&
- changed_tasks[2] == taskC &&
- changed_tasks[3] == NULL,
- "Unexpected simulation results");
-
for (i = 0; changed_tasks[i] != NULL; i++) {
INFO3("Task '%s' start time: %f, finish time: %f",
SD_task_get_name(changed_tasks[i]),
SD_task_get_finish_time(changed_tasks[i]));
}
+ xbt_assert0(changed_tasks[0] == taskD &&
+ changed_tasks[1] == taskB &&
+ changed_tasks[2] == NULL,
+ "Unexpected simulation results");
+
xbt_free(changed_tasks);
DEBUG0("Destroying tasks...");
@see SD_workstation_management */
typedef struct SD_workstation *SD_workstation_t;
+/** @brief Workstation access mode
+ @ingroup SD_datatypes_management
+
+ By default, a workstation resource is shared, i.e. several tasks
+ can be executed at the same time on a workstation. The CPU power of
+ the workstation is shared between the running tasks on the workstation.
+ In sequential mode, only one task can use the workstation, and the other
+ tasks wait in a FIFO.
+
+ @see SD_workstation_get_access_mode(), SD_workstation_set_access_mode() */
+typedef enum {
+ SD_WORKSTATION_SHARED_ACCESS, /**< @brief Several tasks can be executed at the same time */
+ SD_WORKSTATION_SEQUENTIAL_ACCESS /**< @brief Only one task can be executed, the others wait in a FIFO. */
+} e_SD_workstation_access_mode_t;
+
/** @brief Link datatype
@ingroup SD_datatypes_management
SD_NOT_SCHEDULED = 0, /**< @brief Initial state (not valid for SD_watch and SD_unwatch). */
SD_SCHEDULED = 0x0001, /**< @brief A task becomes SD_SCHEDULED when you call function
SD_task_schedule. SD_simulate will execute it when it becomes SD_READY. */
- SD_READY = 0x0002, /**< @brief A scheduled task becomes ready as soon as its dependencies are satisfied. */
- SD_RUNNING = 0x0004, /**< @brief When a task is ready, it is launched in the function SD_simulate and becomes SD_RUNNING. */
- SD_DONE = 0x0008, /**< @brief The task is successfuly finished. */
- SD_FAILED = 0x0010 /**< @brief A problem occured during the execution of the task. */
+ SD_READY = 0x0002, /**< @brief A scheduled task becomes ready is SD_simulate as soon as its dependencies are satisfied. */
+ SD_IN_FIFO = 0x0004, /**< @brief A ready task can have to wait in a workstation fifo if the workstation is sequential */
+ SD_RUNNING = 0x0008, /**< @brief An SD_READY or SD_IN_FIFO becomes SD_RUNNING when it is launched. */
+ SD_DONE = 0x0010, /**< @brief The task is successfuly finished. */
+ SD_FAILED = 0x0020 /**< @brief A problem occured during the execution of the task. */
} e_SD_task_state_t;
#endif
int SD_route_get_size(SD_workstation_t src, SD_workstation_t dst);
double SD_workstation_get_power(SD_workstation_t workstation);
double SD_workstation_get_available_power(SD_workstation_t workstation);
+e_SD_workstation_access_mode_t SD_workstation_get_access_mode(SD_workstation_t workstation);
+void SD_workstation_set_access_mode(SD_workstation_t workstation,
+ e_SD_workstation_access_mode_t access_mode);
double SD_workstation_get_computation_time(SD_workstation_t workstation, double computation_amount);
double SD_route_get_current_latency(SD_workstation_t src, SD_workstation_t dst);
#include "xbt/dict.h"
#include "xbt/dynar.h"
+#include "xbt/fifo.h"
#include "simdag/simdag.h"
#include "simdag/datatypes.h"
#include "surf/surf.h"
xbt_swag_t not_scheduled_task_set;
xbt_swag_t scheduled_task_set;
xbt_swag_t ready_task_set;
+ xbt_swag_t in_fifo_task_set;
xbt_swag_t running_task_set;
xbt_swag_t done_task_set;
xbt_swag_t failed_task_set;
typedef struct SD_workstation {
void *surf_workstation; /* surf object */
void *data; /* user data */
+ e_SD_workstation_access_mode_t access_mode;
+
+ xbt_fifo_t task_fifo; /* only used in sequential mode */
+ SD_task_t current_task; /* only used in sequential mode */
} s_SD_workstation_t;
/* Task */
double finish_time;
surf_action_t surf_action;
unsigned short watch_points;
+
int state_changed; /* used only by SD_simulate, to make sure we put
the task only once in the returning array */
+ int fifo_checked; /* used by SD_task_just_done to make sure we evaluate
+ the task only once */
/* dependencies */
xbt_dynar_t tasks_before;
/* scheduling parameters (only exist in state SD_SCHEDULED) */
int workstation_nb;
- void **workstation_list; /* surf workstations */
+ SD_workstation_t *workstation_list; /* surf workstations */
double *computation_amount;
double *communication_amount;
double rate;
SD_workstation_t __SD_workstation_create(void *surf_workstation, void *data);
void __SD_workstation_destroy(void *workstation);
+int __SD_workstation_is_busy(SD_workstation_t workstation);
void __SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state);
-surf_action_t __SD_task_run(SD_task_t task);
+void __SD_task_really_run(SD_task_t task);
+int __SD_task_try_to_run(SD_task_t task);
+void __SD_task_just_done(SD_task_t task);
/* Functions to test if the task is in a given state.
These functions are faster than using SD_task_get_state() */
return task->state_set == sd_global->ready_task_set;
}
+/* Returns whether the state of the given task is SD_IN_FIFO. */
+static _XBT_INLINE int __SD_task_is_in_fifo(SD_task_t task) {
+ return task->state_set == sd_global->in_fifo_task_set;
+}
+
+/* Returns whether the state of the given task is SD_READY or SD_IN_FIFO. */
+static _XBT_INLINE int __SD_task_is_ready_or_in_fifo(SD_task_t task) {
+ return task->state_set == sd_global->ready_task_set ||
+ task->state_set == sd_global->in_fifo_task_set;
+}
+
/* Returns whether the state of the given task is SD_RUNNING. */
static _XBT_INLINE int __SD_task_is_running(SD_task_t task) {
return task->state_set == sd_global->running_task_set;
sd_global->not_scheduled_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
sd_global->scheduled_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
sd_global->ready_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
+ sd_global->in_fifo_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
sd_global->running_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
sd_global->done_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
sd_global->failed_task_set = xbt_swag_new(xbt_swag_offset(task, state_hookup));
surf_timer_resource_init(platform_file); /* tell Surf to create the environnement */
+ DEBUG0("Calling surf_workstation_resource_init");
surf_workstation_resource_init_KCCFLN05(platform_file);
-/* surf_workstation_resource_init_CLM03(platform_file); */
+ /* surf_workstation_resource_init_CLM03(platform_file); */
/* now let's create the SD wrappers for workstations and links */
+ DEBUG0("Creating SimDags hosts and links");
xbt_dict_foreach(workstation_set, cursor, name, surf_workstation) {
__SD_workstation_create(surf_workstation, NULL);
}
/* explore the ready tasks */
xbt_swag_foreach(task, sd_global->ready_task_set) {
INFO1("Executing task '%s'", SD_task_get_name(task));
- __SD_task_run(task);
- surf_workstation_resource->common_public->action_set_data(task->surf_action, task);
- task->state_changed = 1;
-
- changed_tasks[changed_task_number++] = task; /* replace NULL by the task */
- if (changed_task_number == changed_task_capacity) {
- changed_task_capacity *= 2;
- changed_tasks = xbt_realloc(changed_tasks, sizeof(SD_task_t) * changed_task_capacity);
+ if ((task->state_changed = __SD_task_try_to_run(task))) {
+ changed_tasks[changed_task_number++] = task; /* replace NULL by the task */
+ if (changed_task_number == changed_task_capacity) {
+ changed_task_capacity *= 2;
+ changed_tasks = xbt_realloc(changed_tasks, sizeof(SD_task_t) * changed_task_capacity);
+ }
+ changed_tasks[changed_task_number] = NULL;
}
- changed_tasks[changed_task_number] = NULL;
}
/* main loop */
while ((action = xbt_swag_extract(surf_workstation_resource->common_public->states.done_action_set))) {
task = action->data;
INFO1("Task '%s' done", SD_task_get_name(task));
- __SD_task_set_state(task, SD_DONE);
- surf_workstation_resource->common_public->action_free(action);
- task->surf_action = NULL;
+ DEBUG0("Calling __SD_task_just_done");
+ __SD_task_just_done(task);
+ INFO1("__SD_task_just_done called on task '%s'", SD_task_get_name(task));
/* the state has changed */
if (!task->state_changed) {
/* is dst ready now? */
if (__SD_task_is_ready(dst) && !sd_global->watch_point_reached) {
INFO1("Executing task '%s'", SD_task_get_name(dst));
- dst->surf_action = __SD_task_run(dst);
- surf_workstation_resource->common_public->action_set_data(dst->surf_action, dst);
- dst->state_changed = 1;
-
- changed_tasks[changed_task_number++] = dst;
- if (changed_task_number == changed_task_capacity) {
- changed_task_capacity *= 2;
- changed_tasks = xbt_realloc(changed_tasks, sizeof(SD_task_t) * changed_task_capacity);
+ if (__SD_task_try_to_run(dst)) {
+ changed_tasks[changed_task_number++] = dst;
+ if (changed_task_number == changed_task_capacity) {
+ changed_task_capacity *= 2;
+ changed_tasks = xbt_realloc(changed_tasks, sizeof(SD_task_t) * changed_task_capacity);
+ }
+ changed_tasks[changed_task_number] = NULL;
}
- changed_tasks[changed_task_number] = NULL;
}
}
}
xbt_swag_free(sd_global->not_scheduled_task_set);
xbt_swag_free(sd_global->scheduled_task_set);
xbt_swag_free(sd_global->ready_task_set);
+ xbt_swag_free(sd_global->in_fifo_task_set);
xbt_swag_free(sd_global->running_task_set);
xbt_swag_free(sd_global->done_task_set);
xbt_swag_free(sd_global->failed_task_set);
return SD_RUNNING;
if (task->state_set == sd_global->ready_task_set)
return SD_READY;
+ if (task->state_set == sd_global->in_fifo_task_set)
+ return SD_IN_FIFO;
if (task->state_set == sd_global->not_scheduled_task_set)
return SD_NOT_SCHEDULED;
return SD_FAILED;
case SD_READY:
task->state_set = sd_global->ready_task_set;
break;
+ case SD_IN_FIFO:
+ task->state_set = sd_global->in_fifo_task_set;
+ break;
case SD_RUNNING:
task->state_set = sd_global->running_task_set;
task->start_time = surf_workstation_resource->common_public->
task->communication_amount = xbt_new0(double, communication_nb);
memcpy(task->communication_amount, communication_amount, sizeof(double) * communication_nb);
- /* we have to create a Surf workstation array instead of the SimDag workstation array */
- task->workstation_list = xbt_new0(void*, workstation_nb);
- int i;
- for (i = 0; i < workstation_nb; i++) {
- task->workstation_list[i] = workstation_list[i]->surf_workstation;
- }
+ task->workstation_list = xbt_new0(SD_workstation_t, workstation_nb);
+ memcpy(task->workstation_list, workstation_list, sizeof(SD_workstation_t) * workstation_nb);
/* update the task state */
if (xbt_dynar_length(task->tasks_before) == 0)
*/
static void __SD_task_destroy_scheduling_data(SD_task_t task) {
SD_CHECK_INIT_DONE();
- if (!__SD_task_is_scheduled_or_ready(task))
- THROW1(arg_error, 0, "Task '%s' must be SD_SCHEDULED or SD_READY", SD_task_get_name(task));
+ if (!__SD_task_is_scheduled_or_ready(task) && !__SD_task_is_in_fifo(task))
+ THROW1(arg_error, 0, "Task '%s' must be SD_SCHEDULED, SD_READY or SD_IN_FIFO", 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).
+/* Runs a task. This function is directly called by __SD_task_try_to_run if the task
+ * doesn't have to wait in fifos. Otherwise, it is called by __SD_task_just_done when
+ * the task gets out of its fifos.
*/
-surf_action_t __SD_task_run(SD_task_t task) {
+void __SD_task_really_run(SD_task_t task) {
SD_CHECK_INIT_DONE();
xbt_assert0(task != NULL, "Invalid parameter");
-
- if (!__SD_task_is_ready(task))
- THROW2(arg_error, 0, "Task '%s' is not ready! Task state: %d",
+ xbt_assert2(__SD_task_is_ready_or_in_fifo(task), "Task '%s' is not ready 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));
+
+ int i;
+ void **surf_workstations;
+
+ DEBUG1("Really running task '%s'", SD_task_get_name(task));
+
+ /* set this task as current task for the workstations in sequential mode */
+ for (i = 0; i < task->workstation_nb; i++) {
+ if (SD_workstation_get_access_mode(task->workstation_list[i]) == SD_WORKSTATION_SEQUENTIAL_ACCESS) {
+ task->workstation_list[i]->current_task = task;
+ xbt_assert0(__SD_workstation_is_busy(task->workstation_list[i]), "The workstation should be busy now");
+ }
+ }
+
+ DEBUG1("Task '%s' set as current task for its workstations", SD_task_get_name(task));
+ /* start the task */
+
+ /* we have to create a Surf workstation array instead of the SimDag workstation array */
+ surf_workstations = xbt_new0(void*, task->workstation_nb);
+
+ for (i = 0; i < task->workstation_nb; i++) {
+ surf_workstations[i] = task->workstation_list[i]->surf_workstation;
+ }
+
task->surf_action = surf_workstation_resource->extension_public->
execute_parallel_task(task->workstation_nb,
- task->workstation_list,
+ surf_workstations,
task->computation_amount,
task->communication_amount,
task->amount,
task->rate);
+ surf_workstation_resource->common_public->action_set_data(task->surf_action, task);
+ task->state_changed = 1;
DEBUG1("surf_action = %p", task->surf_action);
+ xbt_free(surf_workstations);
__SD_task_destroy_scheduling_data(task); /* now the scheduling data are not useful anymore */
__SD_task_set_state(task, SD_RUNNING);
+ xbt_assert2(__SD_task_is_running(task), "Bad state of task '%s': %d",
+ SD_task_get_name(task), SD_task_get_state(task));
- return task->surf_action;
}
+
+/* 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) {
+ 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));
+
+ int can_start = 1;
+ int i;
+ SD_workstation_t workstation;
+
+ 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) {
+ 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));
+
+ int i, j;
+ SD_workstation_t workstation;
+
+ SD_task_t candidate;
+ int candidate_nb = 0;
+ int candidate_capacity = 8;
+ SD_task_t *candidates = xbt_new0(SD_task_t, 8);
+ int can_start = 1;
+
+ __SD_task_set_state(task, SD_DONE);
+ surf_workstation_resource->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];
+
+ /* 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));
+ }
+
+ DEBUG2("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 */
+ DEBUG1("Head of the fifo: '%s'", (candidate != NULL) ? SD_task_get_name(candidate) : "NULL");
+ xbt_assert0(candidate == candidates[i], "Error in __SD_task_just_done: bad first task in the fifo");
+ }
+ } /* for each workstation */
+
+ /* finally execute the task */
+ DEBUG2("Task '%s' state: %d", SD_task_get_name(candidate), SD_task_get_state(candidate));
+ __SD_task_really_run(candidate);
+
+ DEBUG4("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_assert2(__SD_task_is_running(candidate), "Bad state of task '%s': %d",
+ SD_task_get_name(candidate), SD_task_get_state(candidate));
+ DEBUG0("Okay, the task is running.");
+
+ } /* can start */
+ candidate->fifo_checked = 1;
+ } /* for each candidate */
+
+ xbt_free(candidates);
+}
+
/* 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) {
if (task->surf_action != NULL)
surf_workstation_resource->common_public->action_free(task->surf_action);
+ if (task->workstation_list != NULL)
+ xbt_free(task->workstation_list);
+
xbt_dynar_free(&task->tasks_before);
xbt_dynar_free(&task->tasks_after);
xbt_free(task);
SD_workstation_t workstation = xbt_new0(s_SD_workstation_t, 1);
workstation->surf_workstation = surf_workstation;
workstation->data = data; /* user data */
+ SD_workstation_set_access_mode(workstation, SD_WORKSTATION_SHARED_ACCESS); /* default mode is shared */
+ workstation->task_fifo = NULL;
const char *name = SD_workstation_get_name(workstation);
xbt_dict_set(sd_global->workstations, name, workstation, __SD_workstation_destroy); /* add the workstation to the dictionary */
* \return an array of \ref SD_workstation_t containing all workstations
* \see SD_workstation_get_number()
*/
-const SD_workstation_t* SD_workstation_get_list(void) {
+const SD_workstation_t* SD_workstation_get_list(void) {
SD_CHECK_INIT_DONE();
xbt_assert0(SD_workstation_get_number() > 0, "There is no workstation!");
return latency + (communication_amount / min_bandwidth);
}
+/**
+ * \brief Returns the access mode of this workstation.
+ *
+ * \param workstation a workstation
+ * \return the access mode for the tasks running on this workstation:
+ * SD_WORKSTATION_SHARED_ACCESS or SD_WORKSTATION_SEQUENTIAL_ACCESS
+ *
+ * \see SD_workstation_set_access_mode(), e_SD_workstation_access_mode_t
+ */
+ e_SD_workstation_access_mode_t SD_workstation_get_access_mode(SD_workstation_t workstation) {
+ SD_CHECK_INIT_DONE();
+ xbt_assert0(workstation != NULL, "Invalid parameter");
+ return workstation->access_mode;
+}
+
+/**
+ * \brief Sets the access mode for the tasks that will be executed on a workstation
+ *
+ * By default, a workstation resource is shared, i.e. several tasks
+ * can be executed at the same time on a workstation. The CPU power of
+ * the workstation is shared between the running tasks on the workstation.
+ * In sequential mode, only one task can use the workstation, and the other
+ * tasks wait in a FIFO.
+ *
+ * \param workstation a workstation
+ * \param access_mode the access mode you want to set to this workstation:
+ * SD_WORKSTATION_SHARED_ACCESS or SD_WORKSTATION_SEQUENTIAL_ACCESS
+ *
+ * \see SD_workstation_get_access_mode(), e_SD_workstation_access_mode_t
+ */
+void SD_workstation_set_access_mode(SD_workstation_t workstation, e_SD_workstation_access_mode_t access_mode) {
+ SD_CHECK_INIT_DONE();
+ xbt_assert0(workstation != NULL, "Invalid parameter");
+
+ if (access_mode == workstation->access_mode) {
+ return; // nothing is changed
+ }
+
+ workstation->access_mode = access_mode;
+
+ if (access_mode == SD_WORKSTATION_SHARED_ACCESS) {
+ xbt_fifo_free(workstation->task_fifo);
+ workstation->task_fifo = NULL;
+ }
+ else {
+ workstation->task_fifo = xbt_fifo_new();
+ }
+}
+
+/* Returns whether a task can start now on a workstation.
+ *//*
+int __SD_workstation_can_start(SD_workstation_t workstation, SD_task_t task) {
+ SD_CHECK_INIT_DONE();
+ xbt_assert0(workstation != NULL && task != NULL, "Invalid parameter");
+
+ return !__SD_workstation_is_busy(workstation) &&
+ (xbt_fifo_size(workstation->task_fifo) == 0) || xbt_fifo_get_first_item(workstation->task_fifo) == task);
+}
+*/
+
+/* Returns whether a workstation is busy. A workstation is busy is it is
+ * in sequential mode and a task is running on it or the fifo is not empty.
+ */
+int __SD_workstation_is_busy(SD_workstation_t workstation) {
+ SD_CHECK_INIT_DONE();
+ xbt_assert0(workstation != NULL, "Invalid parameter");
+
+ return workstation->access_mode == SD_WORKSTATION_SEQUENTIAL_ACCESS &&
+ (workstation->current_task != NULL || xbt_fifo_size(workstation->task_fifo) > 0);
+}
+
/* Destroys a workstation.
*/
void __SD_workstation_destroy(void *workstation) {
SD_CHECK_INIT_DONE();
xbt_assert0(workstation != NULL, "Invalid parameter");
/* workstation->surf_workstation is freed by surf_exit and workstation->data is freed by the user */
- xbt_free(workstation);
+
+ SD_workstation_t w = (SD_workstation_t) workstation;
+
+ if (w->access_mode == SD_WORKSTATION_SEQUENTIAL_ACCESS) {
+ xbt_fifo_free(w->task_fifo);
+ }
+ xbt_free(w);
}