diff --git a/mentos/src/drivers/ps2.c b/mentos/src/drivers/ps2.c index c10bdf0..6e649ab 100644 --- a/mentos/src/drivers/ps2.c +++ b/mentos/src/drivers/ps2.c @@ -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" diff --git a/mentos/src/io/proc_video.c b/mentos/src/io/proc_video.c index 28359d3..d319399 100644 --- a/mentos/src/io/proc_video.c +++ b/mentos/src/io/proc_video.c @@ -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" diff --git a/mentos/src/process/scheduler.c b/mentos/src/process/scheduler.c index 49dc36d..2c46bdf 100644 --- a/mentos/src/process/scheduler.c +++ b/mentos/src/process/scheduler.c @@ -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; } \ No newline at end of file