Set logging for PS/2 and proc_video to Notice. Improve comments of response_time_analysis.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
/// Change the header.
|
||||
#define __DEBUG_HEADER__ "[PS/2 ]"
|
||||
/// Set the log level.
|
||||
#define __DEBUG_LEVEL__ LOGLEVEL_DEBUG
|
||||
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE
|
||||
|
||||
#include "drivers/ps2.h"
|
||||
#include "proc_access.h"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/// Change the header.
|
||||
#define __DEBUG_HEADER__ "[PROCV ]"
|
||||
/// Set the log level.
|
||||
#define __DEBUG_LEVEL__ LOGLEVEL_DEBUG
|
||||
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE
|
||||
|
||||
#include "bits/termios-struct.h"
|
||||
#include "drivers/keyboard/keyboard.h"
|
||||
|
||||
+125
-96
@@ -596,117 +596,146 @@ int sys_sched_getparam(pid_t pid, sched_param_t *param)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// @brief Performs the response time analysis for the current list
|
||||
/// of periodic processes.
|
||||
/// @return 1 if scheduling periodic processes is feasable, 0 otherwise.
|
||||
/// @brief Performs the response time analysis for the current list of periodic
|
||||
/// processes.
|
||||
/// @return 1 if scheduling periodic processes is feasible, 0 otherwise.
|
||||
static int __response_time_analysis()
|
||||
{
|
||||
task_struct *entry, *previous;
|
||||
time_t r, previous_r = 0;
|
||||
list_for_each_decl(it, &runqueue.queue)
|
||||
{
|
||||
// Get the curent entry in the list.
|
||||
entry = list_entry(it, task_struct, run_list);
|
||||
if (entry->se.is_periodic) {
|
||||
// Put r equal to worst case exec because is the first point in time that the task could possibly complete
|
||||
r = entry->se.worst_case_exec;
|
||||
previous_r = 0;
|
||||
// The analysis can be completed either missing the deadline or reaching a fixed point
|
||||
while (r < entry->se.deadline && r != previous_r) {
|
||||
previous_r = r;
|
||||
r = entry->se.worst_case_exec;
|
||||
list_for_each_decl(it2, &runqueue.queue)
|
||||
{
|
||||
previous = list_entry(it2, task_struct, run_list);
|
||||
// Check the interferences of higher priority processes
|
||||
if (previous->se.is_periodic && previous->se.period < entry->se.period) {
|
||||
r += (int)ceil((double)previous_r / (double)previous->se.period) * previous->se.worst_case_exec;
|
||||
pr_debug("%d += (%.2f / %.2f) * %d\n", r, (double)previous_r, (double)previous->se.period, previous->se.worst_case_exec);
|
||||
pr_debug("Response Time Analysis -> [%s]vs[%s] R = %d\n\n", entry->name, previous->name, r);
|
||||
}
|
||||
// If the process is not periodic we skip it.
|
||||
if (!entry->se.is_periodic)
|
||||
continue;
|
||||
// Put r equal to worst case exec because is the first point in time
|
||||
// that the task could possibly complete.
|
||||
r = entry->se.worst_case_exec, previous_r = 0;
|
||||
// The analysis can be completed either missing the deadline or reaching
|
||||
// a fixed point.
|
||||
while ((r < entry->se.deadline) && (r != previous_r)) {
|
||||
// Save the previous response time.
|
||||
previous_r = r;
|
||||
// Initialize response time.
|
||||
r = entry->se.worst_case_exec;
|
||||
list_for_each_decl(it2, &runqueue.queue)
|
||||
{
|
||||
previous = list_entry(it2, task_struct, run_list);
|
||||
// Check the interferences of higher priority processes.
|
||||
if (previous->se.is_periodic && (previous->se.period < entry->se.period)) {
|
||||
pr_debug("%d += (%.2f / %.2f) * %d\n",
|
||||
r,
|
||||
(double)previous_r,
|
||||
(double)previous->se.period,
|
||||
previous->se.worst_case_exec);
|
||||
|
||||
// Update the response time.
|
||||
r += (int)ceil((double)previous_r / (double)previous->se.period) * previous->se.worst_case_exec;
|
||||
|
||||
pr_debug("Response Time Analysis -> [%s] vs [%s] R = %d\n\n", entry->name, previous->name, r);
|
||||
}
|
||||
}
|
||||
// Feasibility of scheduler is guaranteed if and only if response time analysis is lower than deadline.
|
||||
if (r > entry->se.deadline)
|
||||
return 1;
|
||||
}
|
||||
// Feasibility of scheduler is guaranteed if and only if response time
|
||||
// analysis is lower than deadline.
|
||||
if (r > entry->se.deadline)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Computes the total utilization factor.
|
||||
/// @return the utilization factor.
|
||||
static inline double __compute_utilization_factor()
|
||||
{
|
||||
task_struct *entry;
|
||||
double U = 0;
|
||||
list_for_each_decl(it, &runqueue.queue)
|
||||
{
|
||||
// Get the entry.
|
||||
entry = list_entry(it, task_struct, run_list);
|
||||
// Sum the utilization factor of all periodic tasks.
|
||||
if (entry->se.is_periodic)
|
||||
U += entry->se.utilization_factor;
|
||||
}
|
||||
return U;
|
||||
}
|
||||
|
||||
int sys_waitperiod()
|
||||
{
|
||||
if (runqueue.curr) {
|
||||
if (runqueue.curr->se.is_periodic) {
|
||||
// Update the Worst Case Execution Time (WCET).
|
||||
time_t wcet = timer_get_ticks() - runqueue.curr->se.exec_start;
|
||||
if (runqueue.curr->se.worst_case_exec < wcet)
|
||||
runqueue.curr->se.worst_case_exec = wcet;
|
||||
// Update thye utilization factor.
|
||||
runqueue.curr->se.utilization_factor = ((double)runqueue.curr->se.worst_case_exec / (double)runqueue.curr->se.period);
|
||||
|
||||
// If the task is under analysis, we need to test if the process can be
|
||||
// placed with the other periodic tasks.
|
||||
if (runqueue.curr->se.is_under_analysis) {
|
||||
runqueue.curr->se.worst_case_exec = runqueue.curr->se.sum_exec_runtime;
|
||||
bool_t is_not_schedulable = false;
|
||||
#if defined(SCHEDULER_EDF)
|
||||
double u = 0;
|
||||
task_struct *entry;
|
||||
list_for_each_decl(it, &runqueue.queue)
|
||||
{
|
||||
entry = list_entry(it, task_struct, run_list);
|
||||
// Sum the utilization factor of all periodic tasks.
|
||||
if (entry->se.is_periodic)
|
||||
u += entry->se.utilization_factor;
|
||||
}
|
||||
if (u > 1) {
|
||||
is_not_schedulable = true;
|
||||
}
|
||||
pr_debug("utilization factor = %f\n", u);
|
||||
#elif defined(SCHEDULER_RM)
|
||||
// Calculating least upper bound of utilization factor.
|
||||
// For large amount of processes ulub asymptotically should reach ln(2).
|
||||
double ulub = (runqueue.num_periodic * (pow(2, (1.0 / runqueue.num_periodic)) - 1));
|
||||
double u = 0;
|
||||
task_struct *entry;
|
||||
list_for_each_decl(it, &runqueue.queue)
|
||||
{
|
||||
entry = list_entry(it, task_struct, run_list);
|
||||
// Sum the utilization factor of all periodic tasks.
|
||||
if (entry->se.is_periodic)
|
||||
u += entry->se.utilization_factor;
|
||||
}
|
||||
// If the sum of utilization factor is bounded between ulub and 1 we need to calculate
|
||||
// the response time analysis for each process.
|
||||
if (u > 1) {
|
||||
is_not_schedulable = true;
|
||||
} else if (u <= ulub)
|
||||
is_not_schedulable = false;
|
||||
else
|
||||
is_not_schedulable = __response_time_analysis();
|
||||
#endif
|
||||
// If it is not schedulable, we need to tell it to the process.
|
||||
if (is_not_schedulable)
|
||||
return -ENOTSCHEDULABLE;
|
||||
|
||||
// Otherwise, it is schedulable.
|
||||
runqueue.curr->se.is_under_analysis = false;
|
||||
|
||||
// The task has been executed as non-periodic process so that his deadline is not been updated
|
||||
// by the scheduling algorithm of periodic tasks. We need to update it manually.
|
||||
runqueue.curr->se.next_period = timer_get_ticks();
|
||||
runqueue.curr->se.deadline = timer_get_ticks() + runqueue.curr->se.period;
|
||||
}
|
||||
|
||||
if (timer_get_ticks() > runqueue.curr->se.deadline)
|
||||
pr_warning("%d > %d Missing deadline...\n", timer_get_ticks(), runqueue.curr->se.deadline);
|
||||
|
||||
// Tell the scheduler that we have executed the periodic process.
|
||||
runqueue.curr->se.executed = true;
|
||||
|
||||
} else
|
||||
pr_warning("An aperiodic task is calling `waitperiod`, ignoring...\n");
|
||||
return 0;
|
||||
// Get the current process.
|
||||
task_struct *current = scheduler_get_current_process();
|
||||
// Check if there is actually a process running.
|
||||
if (current == NULL) {
|
||||
pr_emerg("There is no current process.\n");
|
||||
return -ESRCH;
|
||||
}
|
||||
return -ESRCH;
|
||||
// Check if the process calling the waitperiod function is a periodic process.
|
||||
if (!current->se.is_periodic) {
|
||||
pr_warning("An aperiodic task is calling `waitperiod`, ignoring...\n");
|
||||
return -EPERM;
|
||||
}
|
||||
// Get the current time.
|
||||
time_t current_time = timer_get_ticks();
|
||||
|
||||
// Update the Worst Case Execution Time (WCET).
|
||||
time_t wcet = current_time - current->se.exec_start;
|
||||
if (current->se.worst_case_exec < wcet)
|
||||
current->se.worst_case_exec = wcet;
|
||||
// Update the utilization factor.
|
||||
current->se.utilization_factor = ((double)current->se.worst_case_exec / (double)current->se.period);
|
||||
// If the task is under analysis, we need to test if the process can be
|
||||
// placed with the other periodic tasks.
|
||||
if (current->se.is_under_analysis) {
|
||||
// Set the WCET as the total execution time of the process.
|
||||
current->se.worst_case_exec = current->se.sum_exec_runtime;
|
||||
// This will keep track if the process can be scheduled.
|
||||
bool_t is_not_schedulable = false;
|
||||
#if defined(SCHEDULER_EDF)
|
||||
// Compute the total utilization factor.
|
||||
double u = __compute_utilization_factor();
|
||||
// If the utilization factor is above 1, the process cannot be placed
|
||||
// with the other periodic processes.
|
||||
if (u > 1) {
|
||||
is_not_schedulable = true;
|
||||
}
|
||||
pr_warning("Utilization factor is : %.2f\n", u);
|
||||
#elif defined(SCHEDULER_RM)
|
||||
// Compute the total utilization factor.
|
||||
double u = __compute_utilization_factor();
|
||||
// Calculating Least Upper Bound of utilization factor. For large amount
|
||||
// of processes ulub asymptotically should reach ln(2).
|
||||
double ulub = (runqueue.num_periodic * (pow(2, (1.0 / runqueue.num_periodic)) - 1));
|
||||
// If the sum of utilization factor is bounded between ulub and 1 we
|
||||
// need to calculate the response time analysis for each process.
|
||||
if (u > 1) {
|
||||
is_not_schedulable = true;
|
||||
} else if (u <= ulub) {
|
||||
is_not_schedulable = false;
|
||||
} else {
|
||||
is_not_schedulable = __response_time_analysis();
|
||||
}
|
||||
pr_warning("Utilization factor is : %.2f, Least Upper Bound: %.2f\n", u, ulub);
|
||||
#endif
|
||||
// If it is not schedulable, we need to tell it to the process.
|
||||
if (is_not_schedulable)
|
||||
return -ENOTSCHEDULABLE;
|
||||
// Otherwise, it is schedulable and thus it is not under analysis
|
||||
// anymore.
|
||||
current->se.is_under_analysis = false;
|
||||
// The task has been executed as non-periodic process so that his
|
||||
// deadline is not been updated by the scheduling algorithm of periodic
|
||||
// tasks. We need to update it manually.
|
||||
current->se.next_period = current_time;
|
||||
current->se.deadline = current_time + current->se.period;
|
||||
}
|
||||
// If the current time is ahead of the deadline, we need to print a warning.
|
||||
if (current_time > current->se.deadline) {
|
||||
pr_warning("%d > %d Missing deadline...\n", current_time, current->se.deadline);
|
||||
}
|
||||
// Tell the scheduler that we have executed the periodic process.
|
||||
current->se.executed = true;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user