From 2c8bf9b0818dd21021519b2a7f087a8daf12c312 Mon Sep 17 00:00:00 2001 From: rhinemann Date: Tue, 1 Apr 2025 16:29:33 +0300 Subject: [PATCH] Finished lab. --- Kernel.cpp | 36 ++++++++++++++++++++++++------------ Kernel.h | 2 +- MMU.cpp | 20 +++++++++++++++----- MMU.h | 2 +- PageTable.cpp | 20 ++++++++++---------- PageTable.h | 14 +++++++------- PhysicalPage.cpp | 4 ++-- PhysicalPage.h | 4 ++-- Process.cpp | 6 ++++-- Process.h | 6 +++--- main.cpp | 40 ++++++++++++++++++++++++++-------------- 11 files changed, 95 insertions(+), 59 deletions(-) diff --git a/Kernel.cpp b/Kernel.cpp index 5aaf416..ae34101 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -1,5 +1,7 @@ #include "Kernel.h" +#include + using std::next; Kernel::Kernel(const unsigned int RunQ_max_length, const List &free_pages, const List &busy_pages) @@ -7,39 +9,49 @@ Kernel::Kernel(const unsigned int RunQ_max_length, const List &fre RunQ.reserve(RunQ_max_length); } -void Kernel::page_fault(PageTable *page_table, const unsigned int idx) { - PhysicalPage *page = nullptr; +void Kernel::page_fault(std::vector *page_table, const unsigned int idx) { + std::cout << std::format("[kernel:page_fault] Handling {} started", idx) << std::endl; + + PhysicalPage *page; if (!this->free_pages.is_empty()) { page = free_pages.get_head()->prev; free_pages.remove(page); busy_pages.insert_tail(page); + + std::cout << std::format("[kernel:page_fault:free] Found free page #{}, using it", page->PPN) << std::endl; } else { + std::cout << "[kernel:page_fault] No free pages available, trying to swap..." << std::endl; for (PhysicalPage *curr = busy_pages.get_head();; curr = curr->next) { if ((*curr->PT)[curr->idx].R) (*curr->PT)[curr->idx].R = false; else { - curr->PT->entries.erase(next(curr->PT->entries.begin(), curr->idx)); + std::cout << std::format("[kernel:page_fault:random] Selected physical page #{} for replacement", curr->PPN) << std::endl; + + curr->PT->erase(next(curr->PT->begin(), curr->idx)); page = curr; busy_pages.set_head(curr->next); + + std::cout << std::format("[kernel:page_fault:random] Auto-advanced the list of busy pages to ppn {}", busy_pages.get_head()->PPN) << std::endl; break; } } } - if (page) { - page->take_up(page_table, idx); - (*page_table)[idx].PPN = page->PPN; - (*page_table)[idx].P = true; - (*page_table)[idx].R = false; - (*page_table)[idx].M = false; - } + page->take_up(page_table, idx); + (*page_table)[idx].PPN = page->PPN; + (*page_table)[idx].P = true; + (*page_table)[idx].R = false; + (*page_table)[idx].M = false; } void Kernel::stat_update() { int i; PhysicalPage *curr; - for (i = 0, curr = busy_pages.get_head(); i < 10; ++i, curr = curr->next) { - if ((*curr->PT)[curr->idx].R) + for (i = 0, curr = busy_pages.get_head(); curr && i < 10; ++i, curr = curr->next) { + if ((*curr->PT)[curr->idx].R) { (*curr->PT)[curr->idx].R = false; + + std::cout << std::format("[kernel:update_job] Updating ppn {} status", curr->PPN) << std::endl; + } } } diff --git a/Kernel.h b/Kernel.h index 0784bf5..6b47396 100644 --- a/Kernel.h +++ b/Kernel.h @@ -14,7 +14,7 @@ public: PhysicalPage *swapped_page; std::vector RunQ; Kernel(unsigned int RunQ_max_length, const List &free_pages, const List &busy_pages); - void page_fault(PageTable *page_table, unsigned int idx); + void page_fault(std::vector *page_table, unsigned int idx); void stat_update(); }; diff --git a/MMU.cpp b/MMU.cpp index e175a86..01cc331 100644 --- a/MMU.cpp +++ b/MMU.cpp @@ -1,10 +1,20 @@ #include "MMU.h" -void MMU::access(Kernel *kernel, PageTable *table, const unsigned int index, const AccessType type) { - if ((*table)[index].P) - kernel->page_fault(table, index); - (*table)[index].R = true; +#include + +void MMU::access(Kernel &kernel, std::vector *page_table, const unsigned int index, const AccessType type) { + if (!(*page_table)[index].P) + kernel.page_fault(page_table, index); + (*page_table)[index].R = true; if (type == WRITE) - (*table)[index].M = true; + (*page_table)[index].M = true; + + switch (type) { + case READ: + std::cout << std::format("[mmu:read] pt[{}] -> ppn {}", index, (*page_table)[index].PPN) << std::endl; + break; + case WRITE: + std::cout << std::format("[mmu:write] pt[{}] -> ppn {}", index, (*page_table)[index].PPN) << std::endl; + } } diff --git a/MMU.h b/MMU.h index c9973fa..c634bb5 100644 --- a/MMU.h +++ b/MMU.h @@ -11,7 +11,7 @@ enum AccessType { class MMU { public: - static void access(Kernel *kernel, PageTable *table, unsigned int index, AccessType type); + static void access(Kernel &kernel, std::vector *page_table, unsigned int index, AccessType type); }; diff --git a/PageTable.cpp b/PageTable.cpp index b454138..b654b33 100644 --- a/PageTable.cpp +++ b/PageTable.cpp @@ -1,12 +1,12 @@ #include "PageTable.h" -PageTable::PageTable(const unsigned int entry_num) { - entries.reserve(entry_num); - for (int i = 0; i < entry_num; ++i) { - entries.emplace_back(); - } -} - -PTE &PageTable::operator[](const unsigned int index) { - return this->entries.at(index); -} +// PageTable::PageTable(const unsigned int entry_num) { +// entries.reserve(entry_num); +// for (int i = 0; i < entry_num; ++i) { +// entries.emplace_back(); +// } +// } +// +// PTE &PageTable::operator[](const unsigned int index) { +// return this->entries.at(index); +// } diff --git a/PageTable.h b/PageTable.h index 6ba9170..ece3b1b 100644 --- a/PageTable.h +++ b/PageTable.h @@ -5,12 +5,12 @@ #include "PTE.h" -class PageTable { -public: - std::vector entries; - PTE &operator[](unsigned int index); - explicit PageTable(unsigned int entry_num); - -}; +// class PageTable { +// public: +// std::vector entries; +// PTE &operator[](unsigned int index); +// explicit PageTable(unsigned int entry_num); +// +// }; #endif //PAGETABLE_H diff --git a/PhysicalPage.cpp b/PhysicalPage.cpp index a1e09d1..761f656 100644 --- a/PhysicalPage.cpp +++ b/PhysicalPage.cpp @@ -1,10 +1,10 @@ #include "PhysicalPage.h" PhysicalPage::PhysicalPage(const unsigned int PPN) -: PPN(PPN), idx(0), PT{nullptr}, next{nullptr}, prev(nullptr) { +: PPN(PPN), idx(0), PT{nullptr}, next(nullptr), prev(nullptr) { } -void PhysicalPage::take_up(PageTable *PT, const unsigned int idx) { +void PhysicalPage::take_up(std::vector *PT, const unsigned int idx) { this->idx = idx; this->PT = PT; } diff --git a/PhysicalPage.h b/PhysicalPage.h index 2c4935a..40ec943 100644 --- a/PhysicalPage.h +++ b/PhysicalPage.h @@ -6,12 +6,12 @@ class PhysicalPage { public: unsigned int PPN, idx; - PageTable *PT; + std::vector *PT; PhysicalPage *next, *prev; explicit PhysicalPage(unsigned int PPN); - void take_up(PageTable *PT, unsigned int idx); + void take_up(std::vector *PT, unsigned int idx); }; #endif //PHYSICALPAGE_H diff --git a/Process.cpp b/Process.cpp index 6ea1286..8f110d3 100644 --- a/Process.cpp +++ b/Process.cpp @@ -1,7 +1,9 @@ #include "Process.h" -Process::Process(PageTable *pageTable, const unsigned int executionTime) -: pageTable(pageTable), executionTime(executionTime) { +#include + +Process::Process(const unsigned int id, std::vector pageTable, const unsigned int executionTime) +: pageTable(std::move(pageTable)), executionTime(executionTime), id(id) { } bool Process::is_finished(const unsigned int elapsedTime) const { diff --git a/Process.h b/Process.h index 691db55..f87a440 100644 --- a/Process.h +++ b/Process.h @@ -5,9 +5,9 @@ class Process { public: - PageTable *pageTable; - unsigned int executionTime; - Process(PageTable *pageTable, unsigned int executionTime); + std::vector pageTable; + unsigned int executionTime, id; + Process(unsigned int id, std::vector pageTable, unsigned int executionTime); [[nodiscard]] bool is_finished(unsigned int elapsedTime) const; }; diff --git a/main.cpp b/main.cpp index 9a9158f..4094f32 100644 --- a/main.cpp +++ b/main.cpp @@ -1,27 +1,27 @@ #include -#include #include #include "Kernel.h" #include "MMU.h" static int MAX_PROC = 10; -static int PAGE_N = 10; +static int PAGE_N = 100; +static int PROC_CREATION_INTERVAL = 100; int main() { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution distribution(500, 600), access_type_distr(1, 10); + std::uniform_int_distribution page_table_distribution(500, 1000), lifetime_distribution(50, 500), access_type_distr(1, 10); Kernel kernel(MAX_PROC, List(), List()); - unsigned int elapsed_time = 0; + unsigned int elapsed_time = 0, new_proc_time = 0, new_ppn; - for (int i = 1; i <= PAGE_N; ++i) { - kernel.free_pages.insert_head(new PhysicalPage(i)); + for (new_ppn = 1; new_ppn <= PAGE_N; ++new_ppn) { + kernel.free_pages.insert_head(new PhysicalPage(new_ppn)); } for (int i = 0; i < kernel.RunQ.capacity(); ++i) { - kernel.RunQ.emplace_back(new PageTable(distribution(gen)), distribution(gen)); + kernel.RunQ.emplace_back(i, std::vector(page_table_distribution(gen), PTE()), lifetime_distribution(gen)); } for (int i = 0; i < 10000; ++i) { @@ -29,40 +29,52 @@ int main() { break; } - std::uniform_int_distribution index_distribution(0, kernel.RunQ.at(0).pageTable->entries.size() - 1); + std::uniform_int_distribution index_distribution(0, kernel.RunQ.at(0).pageTable.size() - 1); for (int j = 0; j < 30; ++j) { const AccessType type = access_type_distr(gen) == 1 ? WRITE : READ; const unsigned int index = index_distribution(gen); - MMU::access(&kernel, kernel.RunQ.at(0).pageTable, index, type); + MMU::access(kernel, &kernel.RunQ.at(0).pageTable, index, type); } ++elapsed_time; + ++new_proc_time; - // kernel.stat_update(); + kernel.stat_update(); if (kernel.RunQ.at(0).is_finished(elapsed_time)) { + std::cout << std::format("[kernel:remove_current_process] Cleaning up process id {}", kernel.RunQ.at(0).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 && curr->next && j < cached_len; + curr && j < cached_len; curr = cached_next, ++j) { cached_next = curr->next; - if (curr->PT == kernel.RunQ.at(0).pageTable) { + if (curr->PT == &kernel.RunQ.at(0).pageTable) { + 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); } } - delete kernel.RunQ.at(0).pageTable; kernel.RunQ.erase(kernel.RunQ.begin()); - kernel.RunQ.emplace_back(new PageTable(distribution(gen)), distribution(gen)); + if (new_proc_time >= PROC_CREATION_INTERVAL) { + kernel.RunQ.emplace_back(new_ppn, std::vector(page_table_distribution(gen), PTE()), 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.empty()) { + std::cout << "[main:scheduling] No processes left to execute!" << std::endl; + } } return 0;