Update readme. Add SCHEDULER_AEDF to cmake options. Add exercise template inside the scheduler_algorithm.c file.
This commit is contained in:
@@ -202,29 +202,42 @@ This example sets the `__DEBUG_LEVEL__`, so that all the messages from `INFO` an
|
||||
|
||||
## 7. Change the scheduling algorithm
|
||||
|
||||
MentOS provides three different scheduling algorithms:
|
||||
MentOS supports scheduling algorithms for aperiodic:
|
||||
|
||||
- Round-Robin
|
||||
- Priority
|
||||
- Completely Fair Scheduling
|
||||
- Round-Robin (RR)
|
||||
- Highest Priority
|
||||
- Completely Fair Scheduling (CFS)
|
||||
- Aperiodic Earliest Deadline First (AEDF)
|
||||
|
||||
If you want to change the scheduling algorithm:
|
||||
It also supports periodic algorithms:
|
||||
|
||||
- Earliest Deadline First (EDF)
|
||||
- Rate Monotonic (RM)
|
||||
|
||||
If you want to change the scheduling algorithm, to Round-Robin (RR) for instance:
|
||||
|
||||
```bash
|
||||
|
||||
cd build
|
||||
|
||||
# Round Robin scheduling algorithm
|
||||
cmake -DSCHEDULER_TYPE=SCHEDULER_RR ..
|
||||
# Priority scheduling algorithm
|
||||
cmake -DSCHEDULER_TYPE=SCHEDULER_PRIORITY ..
|
||||
# Completely Fair Scheduling algorithm
|
||||
cmake -DSCHEDULER_TYPE=SCHEDULER_CFS ..
|
||||
|
||||
make
|
||||
make qemu
|
||||
```
|
||||
|
||||
or you can activate one of the others:
|
||||
|
||||
```bash
|
||||
# Highest Priority
|
||||
cmake -DSCHEDULER_TYPE=SCHEDULER_PRIORITY ..
|
||||
# Completely Fair Scheduling (CFS)
|
||||
cmake -DSCHEDULER_TYPE=SCHEDULER_CFS ..
|
||||
# Earliest Deadline First (EDF)
|
||||
cmake -DSCHEDULER_TYPE=SCHEDULER_EDF ..
|
||||
# Rate Monotonic (RM)
|
||||
cmake -DSCHEDULER_TYPE=SCHEDULER_RM ..
|
||||
# Aperiodic Earliest Deadline First (AEDF)
|
||||
cmake -DSCHEDULER_TYPE=SCHEDULER_AEDF ..
|
||||
```
|
||||
|
||||
Otherwise you can use `ccmake`:
|
||||
|
||||
```bash
|
||||
@@ -244,8 +257,7 @@ ENABLE_BUDDY_SYSTEM OFF
|
||||
SCHEDULER_TYPE SCHEDULER_RR
|
||||
```
|
||||
|
||||
Select SCHEDULER_TYPE, and type Enter to scroll the three available algorithms
|
||||
(SCHEDULER_RR, SCHEDULER_PRIORITY, SCHEDULER_CFS). Afterwards,
|
||||
Select SCHEDULER_TYPE, and type Enter to scroll the three available algorithms (SCHEDULER_RR, SCHEDULER_PRIORITY, SCHEDULER_CFS, SCHEDULER_EDF, SCHEDULER_RM, SCHEDULER_AEDF). Afterwards, you need to
|
||||
|
||||
```bash
|
||||
<press c>
|
||||
|
||||
@@ -216,7 +216,7 @@ endif(ENABLE_ALLOC_TRACE)
|
||||
|
||||
# =============================================================================
|
||||
# Set the list of valid scheduling options.
|
||||
set(SCHEDULER_TYPES SCHEDULER_RR SCHEDULER_PRIORITY SCHEDULER_CFS SCHEDULER_EDF SCHEDULER_RM)
|
||||
set(SCHEDULER_TYPES SCHEDULER_RR SCHEDULER_PRIORITY SCHEDULER_CFS SCHEDULER_EDF SCHEDULER_RM SCHEDULER_AEDF)
|
||||
# Add the scheduling option.
|
||||
set(SCHEDULER_TYPE "SCHEDULER_RR" CACHE STRING "Chose the type of scheduler: ${SCHEDULER_TYPES}")
|
||||
# List of schedulers.
|
||||
|
||||
@@ -75,7 +75,37 @@ static inline task_struct *__scheduler_rr(runqueue_t *runqueue, bool_t skip_peri
|
||||
/// @return the next task on success, NULL on failure.
|
||||
static inline task_struct *__scheduler_priority(runqueue_t *runqueue, bool_t skip_periodic)
|
||||
{
|
||||
#ifdef SCHEDULER_PRIORITY
|
||||
// Get the first element of the list.
|
||||
task_struct *next = list_entry(runqueue->curr, task_struct, run_list);
|
||||
|
||||
// Get its static priority.
|
||||
time_t min = /*...*/;
|
||||
|
||||
// Search for the task with the smallest static priority.
|
||||
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.
|
||||
task_struct *entry = list_entry(it, task_struct, run_list);
|
||||
// We consider only runnable processes
|
||||
if (entry->state != TASK_RUNNING)
|
||||
continue;
|
||||
// If entry is a periodic task, and we were asked to skip periodic tasks, skip it.
|
||||
if (__is_periodic_task(entry) && skip_periodic)
|
||||
continue;
|
||||
// Check if the entry has a lower priority.
|
||||
if (/*...*/) {
|
||||
// Chose the `entry` as the `next` task.
|
||||
/*...*/
|
||||
}
|
||||
}
|
||||
return next;
|
||||
#else
|
||||
return __scheduler_rr(runqueue, skip_periodic);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @brief It aims at giving a fair share of CPU time to processes, and achieves
|
||||
@@ -89,7 +119,35 @@ static inline task_struct *__scheduler_priority(runqueue_t *runqueue, bool_t ski
|
||||
/// @return the next task on success, NULL on failure.
|
||||
static inline task_struct *__scheduler_cfs(runqueue_t *runqueue, bool_t skip_periodic)
|
||||
{
|
||||
#ifdef SCHEDULER_CFS
|
||||
// Get the first element of the list.
|
||||
task_struct *next = list_entry(runqueue->curr, task_struct, run_list);
|
||||
|
||||
// Get its virtual runtime.
|
||||
time_t min = /* ... */;
|
||||
|
||||
// Search for the task with the smallest vruntime value.
|
||||
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.
|
||||
task_struct *entry = list_entry(it, task_struct, run_list);
|
||||
// We consider only runnable processes
|
||||
if (entry->state != TASK_RUNNING)
|
||||
continue;
|
||||
// If entry is a periodic task, and we were asked to skip periodic tasks, skip it.
|
||||
if (__is_periodic_task(entry) && skip_periodic)
|
||||
continue;
|
||||
|
||||
// Check if the element in the list has a smaller vruntime value.
|
||||
/* ... */
|
||||
}
|
||||
return next;
|
||||
#else
|
||||
return __scheduler_rr(runqueue, skip_periodic);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @brief Executes the task with the earliest absolute deadline among all the
|
||||
@@ -157,6 +215,8 @@ task_struct *scheduler_pick_next_task(runqueue_t *runqueue)
|
||||
|
||||
static void __update_task_statistics(task_struct *task)
|
||||
{
|
||||
// See `prio.h` for more support functions.
|
||||
#if defined(SCHEDULER_CFS) || defined(SCHEDULER_EDF) || defined(SCHEDULER_RM) || defined(SCHEDULER_AEDF)
|
||||
assert(task && "Current task is not valid.");
|
||||
|
||||
// While periodic task is under analysis is executed with aperiodic
|
||||
@@ -165,6 +225,8 @@ static void __update_task_statistics(task_struct *task)
|
||||
// if is a more pessimistic evaluation.
|
||||
// Update the delta exec.
|
||||
task->se.exec_runtime = timer_get_ticks() - task->se.exec_start;
|
||||
|
||||
// Perform timer-related checks.
|
||||
update_process_profiling_timer(task);
|
||||
|
||||
// Set the sum_exec_runtime.
|
||||
@@ -173,15 +235,16 @@ static void __update_task_statistics(task_struct *task)
|
||||
// If the task is not a periodic task we have to update the virtual runtime.
|
||||
if (!task->se.is_periodic) {
|
||||
// Get the weight of the current task.
|
||||
time_t weight = GET_WEIGHT(task->se.prio);
|
||||
time_t weight = /* ... */;
|
||||
// If the weight is different from the default load, compute it.
|
||||
if (weight != NICE_0_LOAD) {
|
||||
// Get the multiplicative factor for its delta_exec.
|
||||
double factor = ((double)NICE_0_LOAD) / ((double)weight);
|
||||
double factor = /* ... */;
|
||||
// Weight the delta_exec with the multiplicative factor.
|
||||
task->se.exec_runtime = (int)(((double)task->se.exec_runtime) * factor);
|
||||
task->se.exec_runtime = /* ... */;
|
||||
}
|
||||
// Update vruntime of the current task.
|
||||
task->se.vruntime += task->se.exec_runtime;
|
||||
task->se.vruntime += /* ... */;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user