Update readme. Add SCHEDULER_AEDF to cmake options. Add exercise template inside the scheduler_algorithm.c file.

This commit is contained in:
Enrico Fraccaroli
2022-12-09 10:58:09 -05:00
parent b61655b9de
commit 79f150a3d5
3 changed files with 95 additions and 20 deletions
+27 -15
View File
@@ -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>
+1 -1
View File
@@ -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.
+67 -4
View File
@@ -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
}