#include #include #include "Kernel.h" #include "MMU.h" static int MAX_PROC = 10; static int PAGE_N = 100; static int PROC_CREATION_INTERVAL = 100; static int WORKING_SET_SIZE = 15; int main() { std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution page_table_distribution(500, 1000), lifetime_distribution(50, 500), access_type_distr(1, 10); Kernel kernel = Kernel(List(), List()); unsigned int elapsed_time = 0, new_proc_time = 0, new_ppn; for (new_ppn = 1; new_ppn <= PAGE_N; ++new_ppn) { kernel.free_pages.insert_head(new PhysicalPage(new_ppn)); } for (int i = 0; i < MAX_PROC; ++i) { kernel.RunQ.insert_head(new Process(i, std::vector(page_table_distribution(gen), PTE()), WORKING_SET_SIZE, lifetime_distribution(gen))); } for (int i = 0; i < 10'000; ++i) { Process *current_process = kernel.RunQ.get_head(); std::uniform_int_distribution index_distribution; for (int j = 0; j < 30; ++j) { const AccessType type = access_type_distr(gen) == 1 ? WRITE : READ; if (access_type_distr(gen) == 1) { index_distribution = std::uniform_int_distribution(0, current_process->page_table.size() - 1); const unsigned int table_index = index_distribution(gen); MMU::access(kernel, ¤t_process->page_table, table_index, type); } else { index_distribution = std::uniform_int_distribution(0, current_process->working_set.size() - 1); const unsigned int table_index = index_distribution(gen); MMU::access(kernel, ¤t_process->page_table, current_process->working_set[table_index], type); } } ++current_process->elapsed_time; ++new_proc_time; kernel.stat_update(); if (current_process->is_finished()) { std::cout << std::format("[kernel:remove_current_process] Cleaning up process id {}", current_process->id) << std::endl; PhysicalPage *curr, *cached_next; unsigned int j; const unsigned int cached_len = kernel.busy_pages.get_num(); for (curr = kernel.busy_pages.get_head(), j = 0; curr && j < cached_len; curr = cached_next, ++j) { cached_next = curr->next; if (curr->PT == ¤t_process->page_table) { std::cout << std::format("[kernel:remove_current_process] Found ppn #{}, freeing it", curr->PPN) << std::endl; kernel.busy_pages.remove(curr); kernel.free_pages.insert_tail(curr); } } kernel.RunQ.set_head(current_process->next); kernel.RunQ.remove(current_process); if (new_proc_time >= PROC_CREATION_INTERVAL) { kernel.RunQ.insert_tail(new Process(new_ppn, std::vector(page_table_distribution(gen), PTE()), WORKING_SET_SIZE, lifetime_distribution(gen))); ++new_ppn; new_proc_time = 0; } } { unsigned int busy_stat = kernel.busy_pages.get_num(), free_stat = kernel.free_pages.get_num(); std::cout << std::format("[main:metrics] Memory usage stats: busy {}, free {}, total {}", busy_stat, free_stat, free_stat + busy_stat) << std::endl; } if (kernel.RunQ.is_empty()) { std::cout << "[main:scheduling] No processes left to execute!" << std::endl; break; } } std::cout << "[main:scheduling] Simulation finished." << std::endl; return 0; }