#include "task_scheduler.hh" #include "file_io.hh" #include "ask.hh" #include "tcb.hh" #include "time_io.hh" #include "be.hh" #include "llc.hh" #include "options.hh" #include #include #include #include #include #include const std::string Task_Scheduler::scheduling_algorithms[] = { "EDF" }; Task_Scheduler::Task_Scheduler(std::ifstream& f) { set_scheduler_parameters(f); set_scheduling_algorithm(f); set_tasks(f); } Task_Scheduler::~Task_Scheduler() { for (int i = 0; i < number_of_tasks; i++) { delete tasks[i]; } free(tasks); } void Task_Scheduler::set_scheduler_parameters(std::ifstream& f) { selected = false; // critical level file_goto_next_colon(f); f >> critical_level; assert(critical_level > 0); // CPU budget file_goto_next_colon(f); f >> cpu_budget; assert(cpu_budget > ms_t(0)); cpu_budget_left = cpu_budget; // memory budget (memory_budget_add_on is zero unless -m MEMBUD) file_goto_next_colon(f); long long stated_max_BE_accesses; f >> stated_max_BE_accesses; max_BE_accesses = stated_max_BE_accesses + memory_budget_add_on; assert(max_BE_accesses >= 0); } void Task_Scheduler::set_scheduling_algorithm(std::ifstream& f) { bool found_algorithm = false; file_goto_next_colon(f); f >> scheduling_algorithm; for (int i = 0, num_scheduling_algorithms = sizeof(scheduling_algorithms)/ sizeof(scheduling_algorithms[0]); i < num_scheduling_algorithms; i++) { if (scheduling_algorithm == scheduling_algorithms[i]) { found_algorithm = true; break; } } if (!found_algorithm) { std::cerr << " Couldn't find global scheduler algorithm: " << scheduling_algorithm << std::endl; exit(EXIT_FAILURE); } } void Task_Scheduler::set_tasks(std::ifstream& f) { number_of_tasks = 0; std::streampos pos = f.tellg(); file_goto_next_newline(f); while (f.good() and (f.peek() != EOF)) { char c = f.get(); if (c == 't') { number_of_tasks++; } else { break; } file_goto_next_newline(f); } assert(number_of_tasks > 0); f.seekg(pos); assert(f.good()); size_t tcbs_size = number_of_tasks*sizeof(tcb *); tasks = (tcb **)malloc(tcbs_size); assert(tasks); for (int i = 0; i < number_of_tasks; i++) { tasks[i] = new tcb(f); } } void Task_Scheduler::check_tasks() { ms_t test_budget = cpu_budget; int max_instances; ms_t max_c; for (int i = 0; i < number_of_tasks; i++) { max_instances = cpu_budget/tasks[i]->get_t(); max_c = tasks[i]->get_c()*max_instances; test_budget -= max_c; } if (test_budget < ms_t(0)) { std::string Bi = "B" + std::to_string(critical_level); std::cout << "Warning: sum((" << Bi << "/Ti)*Ci) > " << Bi << std::endl; } } void Task_Scheduler::store() { std::cout << "Critical level: " << critical_level << std::endl << "Budget: " << cpu_budget << std::endl << "Task scheduling algorithm: " << scheduling_algorithm << std::endl << "Max BE accesses: " << max_BE_accesses << std::endl; for (int i = 0; i < number_of_tasks; i++) { tasks[i]->store(); } } Task_Scheduler::Task_Scheduler() { selected = false; std::cout << "Critical level: "; std::cin >> critical_level; assert(critical_level > 0); std::cout << "Budget: "; std::cin >> cpu_budget; assert(cpu_budget > ms_t(0)); cpu_budget_left = cpu_budget; std::cout << "Max BE accesses: "; std::cin >> max_BE_accesses; assert(max_BE_accesses >= 0); scheduling_algorithm = scheduling_algorithms[0]; std::cout << "Task scheduling algorithm: " << scheduling_algorithm << std::endl; number_of_tasks = ask_how_many("tasks"); size_t tcbs_size = number_of_tasks*sizeof(tcb *); tasks = (tcb **)malloc(tcbs_size); assert(tasks); for (int i = 0; i < number_of_tasks; i++) { tasks[i] = new tcb(); } } void Task_Scheduler::resupply() { cpu_budget_left = cpu_budget; memory_budget_left = max_BE_accesses; } void Task_Scheduler::schedule() { if (scheduling_algorithm == "EDF") { schedule_EDF(); } else { std::cerr << "Can't schedule. Unknown algorithm: " << scheduling_algorithm << std::endl; } } tp_t Task_Scheduler::earliest_deadline() { assert(hp_task); return hp_task->get_rt_c(); } void Task_Scheduler::schedule_EDF() { int ED_task_index; std::chrono::system_clock::time_point earliest_deadline; std::chrono::system_clock::time_point candidate_deadline; bool is_data = false; for (int i = 0; i < number_of_tasks; i++) { tasks[i]->stop(); if (tasks[i]->is_employed()) { candidate_deadline = tasks[i]->get_rt_c(); if ((!is_data) or (candidate_deadline < earliest_deadline)) { is_data = true; earliest_deadline = candidate_deadline; ED_task_index = i; } } } hp_task = (is_data ? tasks[ED_task_index] : NULL); } void Task_Scheduler::run() { assert(hp_task); selected = true; } bool Task_Scheduler::is_ready() { return ((cpu_budget_left > ms_t(0)) and hp_task); } void Task_Scheduler::check_memory_budget(long long current_BE_accesses, int fd) { static long long last_number_of_BE_accesses = 0; if (poll_llc) { memory_budget_left -= current_BE_accesses - last_number_of_BE_accesses; last_number_of_BE_accesses = current_BE_accesses; if (debug and (memory_budget_left < 0) ) { std::cout << "Memory budget remaining: " << memory_budget_left << std::endl; } if (do_freeze_BE_core) { if (memory_budget_left < 0) { freeze_BE_core(fd); } else { unfreeze_BE_core(); } } } } void Task_Scheduler::tick(ms_t tick_time, long long current_BE_accesses, int fd) { if (selected) { hp_task->run(); cpu_budget_left -= tick_time; check_memory_budget(current_BE_accesses, fd); } for (int i = 0; i < number_of_tasks; i++) { tasks[i]->tick(tick_time); } selected = false; } std::ostream& operator<<(std::ostream& os, Task_Scheduler* ts) { os << "== scheduler " << ts->critical_level << " ==" << std::endl << "Critical level: " << ts->critical_level << std::endl << "Max BE accesses: " << ts->max_BE_accesses << std::endl << "CPU-budget: " << ts->cpu_budget << " (left: " << ts->cpu_budget_left << ")" << std::endl << "Algorithm: " << ts->scheduling_algorithm << std::endl << "Tasks: " << ts->number_of_tasks << std::endl; for (int i = 0; i < ts->number_of_tasks; i++) { std::cout << ts->tasks[i]; } os << std::endl; return os; } long long Task_Scheduler::get_max_BE_accesses() { return max_BE_accesses; }