Improve human readability of the Round-Robin algorithm.
This commit is contained in:
@@ -22,78 +22,78 @@
|
||||
/// @param task the task to update.
|
||||
static void __update_task_statistics(task_struct *task);
|
||||
|
||||
/// @brief Checks if the given task is actually a periodic task.
|
||||
/// @param task the task to check.
|
||||
/// @return true if the task is periodic, false otherwise.
|
||||
static inline bool_t __is_periodic_task(task_struct *task)
|
||||
{
|
||||
// Check if the task is a periodic one and it is not under analysis.
|
||||
return task->se.is_periodic && !task->se.is_under_analysis;
|
||||
}
|
||||
|
||||
/// @brief Employs time-sharing, giving each job a timeslice, and is also
|
||||
/// preemptive since the scheduler forces the task out of the CPU once
|
||||
/// the timeslice expires.
|
||||
/// @param runqueue list of all processes.
|
||||
/// @param skip_periodic tells the algorithm if there are periodic processes
|
||||
/// in the list, and in that case it needs to skip them.
|
||||
/// @param skip_periodic tells the algorithm if there are periodic processes in
|
||||
/// the list, and in that case it needs to skip them.
|
||||
/// @return the next task on success, NULL on failure.
|
||||
static inline task_struct *__scheduler_rr(runqueue_t *runqueue, bool_t skip_periodic)
|
||||
{
|
||||
// If there is just one task, return it.
|
||||
if ((runqueue->curr->run_list.next == &runqueue->queue) &&
|
||||
(runqueue->curr->run_list.prev == &runqueue->queue)) {
|
||||
// If there is just one task, return it; no need to do anything.
|
||||
if (list_head_size(&runqueue->curr->run_list) <= 1) {
|
||||
return runqueue->curr;
|
||||
}
|
||||
// By default, the next task is the current one.
|
||||
task_struct *next = NULL, *entry = NULL;
|
||||
// Search for the next task (BEWARE: We do not start from the head, so INSIDE skip the head).
|
||||
// Search for the next task (we do not start from the head, so INSIDE, skip the head).
|
||||
list_for_each_decl(it, &runqueue->curr->run_list)
|
||||
{
|
||||
// Check if we reached the head of list_head, and skip it.
|
||||
if (it == &runqueue->queue)
|
||||
continue;
|
||||
// Get the current entry.
|
||||
entry = list_entry(it, task_struct, run_list);
|
||||
|
||||
task_struct *entry = list_entry(it, task_struct, run_list);
|
||||
// We consider only runnable processes
|
||||
if (entry->state != TASK_RUNNING)
|
||||
continue;
|
||||
|
||||
// Skip the task if it is a periodic one, we are issued to skip
|
||||
// periodic tasks, and the entry is not a periodic task under
|
||||
// analysis.
|
||||
if (entry->se.is_periodic && skip_periodic && !entry->se.is_under_analysis)
|
||||
// If entry is a periodic task, and we were asked to skip periodic tasks, skip it.
|
||||
if (__is_periodic_task(entry) && skip_periodic)
|
||||
continue;
|
||||
|
||||
// We have our next entry.
|
||||
next = entry;
|
||||
break;
|
||||
return entry;
|
||||
}
|
||||
return next;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// @brief Is a non-preemptive algorithm, where each task is assigned a
|
||||
/// priority. Processes with highest priority are executed first, while
|
||||
/// processes with same priority are executed on first-come/first-served
|
||||
/// basis. Priority can be decided based on memory requirements, time
|
||||
/// requirements or any other resource requirement.
|
||||
/// processes with same priority are executed on first-come/first-served basis.
|
||||
/// Priority can be decided based on memory requirements, time requirements or
|
||||
/// any other resource requirement.
|
||||
/// @param runqueue list of all processes.
|
||||
/// @param skip_periodic tells the algorithm if there are periodic processes
|
||||
/// in the list, and in that case it needs to skip them.
|
||||
/// @param skip_periodic tells the algorithm if there are periodic processes in
|
||||
/// the list, and in that case it needs to skip them.
|
||||
/// @return the next task on success, NULL on failure.
|
||||
static inline task_struct *__scheduler_priority(runqueue_t *runqueue, bool_t skip_periodic)
|
||||
{
|
||||
return __scheduler_rr(runqueue, skip_periodic);
|
||||
}
|
||||
|
||||
/// @brief It aims at giving a fair share of CPU time to processes, and
|
||||
/// achieves that by associating a virtual runtime to each of them. It always
|
||||
/// tries to run the task with the smallest vruntime (i.e., the task which
|
||||
/// executed least so far). It always tries to split up CPU time between
|
||||
/// runnable tasks as close to "ideal multitasking hardware" as possible.
|
||||
/// @brief It aims at giving a fair share of CPU time to processes, and achieves
|
||||
/// that by associating a virtual runtime to each of them. It always tries to
|
||||
/// run the task with the smallest vruntime (i.e., the task which executed least
|
||||
/// so far). It always tries to split up CPU time between runnable tasks as
|
||||
/// close to "ideal multitasking hardware" as possible.
|
||||
/// @param runqueue list of all processes.
|
||||
/// @param skip_periodic tells the algorithm if there are periodic processes
|
||||
/// in the list, and in that case it needs to skip them.
|
||||
/// @param skip_periodic tells the algorithm if there are periodic processes in
|
||||
/// the list, and in that case it needs to skip them.
|
||||
/// @return the next task on success, NULL on failure.
|
||||
static inline task_struct *__scheduler_cfs(runqueue_t *runqueue, bool_t skip_periodic)
|
||||
{
|
||||
return __scheduler_rr(runqueue, skip_periodic);
|
||||
}
|
||||
|
||||
/// @brief Executes the task with the earliest absolute deadline among all
|
||||
/// the ready tasks.
|
||||
/// @brief Executes the task with the earliest absolute deadline among all the
|
||||
/// ready tasks.
|
||||
/// @param runqueue list of all processes.
|
||||
/// @return the next task on success, NULL on failure.
|
||||
static inline task_struct *__scheduler_aedf(runqueue_t *runqueue)
|
||||
@@ -101,10 +101,10 @@ static inline task_struct *__scheduler_aedf(runqueue_t *runqueue)
|
||||
return __scheduler_rr(runqueue, false);
|
||||
}
|
||||
|
||||
/// @brief Executes the task with the earliest absolute DEADLINE among all
|
||||
/// the ready tasks. When a task was executed, and its period is starting
|
||||
/// again, it must be set as 'executable again', and its deadline and next_period
|
||||
/// must be updated.
|
||||
/// @brief Executes the task with the earliest absolute DEADLINE among all the
|
||||
/// ready tasks. When a task was executed, and its period is starting again, it
|
||||
/// must be set as 'executable again', and its deadline and next_period must be
|
||||
/// updated.
|
||||
/// @param runqueue list of all processes.
|
||||
/// @return the next task on success, NULL on failure.
|
||||
static inline task_struct *__scheduler_edf(runqueue_t *runqueue)
|
||||
@@ -112,11 +112,11 @@ static inline task_struct *__scheduler_edf(runqueue_t *runqueue)
|
||||
return __scheduler_rr(runqueue, false);
|
||||
}
|
||||
|
||||
/// @brief Executes the task with the earliest next PERIOD among all the
|
||||
/// ready tasks.
|
||||
/// @details When a task was executed, and its period is starting again, it
|
||||
/// must be set as 'executable again', and its deadline and next_period must
|
||||
/// be updated.
|
||||
/// @brief Executes the task with the earliest next PERIOD among all the ready
|
||||
/// tasks.
|
||||
/// @details When a task was executed, and its period is starting again, it must
|
||||
/// be set as 'executable again', and its deadline and next_period must be
|
||||
/// updated.
|
||||
/// @param runqueue list of all processes.
|
||||
/// @return the next task on success, NULL on failure.
|
||||
static inline task_struct *__scheduler_rm(runqueue_t *runqueue)
|
||||
|
||||
Reference in New Issue
Block a user