From 359ffa755c3396a42d0b777d35de37a0c76e1c8a Mon Sep 17 00:00:00 2001 From: rhinemann Date: Mon, 31 Mar 2025 17:19:43 +0300 Subject: [PATCH] First commit. --- CMakeLists.txt | 20 +++++++++ Kernel.cpp | 29 +++++++++++++ Kernel.h | 22 ++++++++++ List.cpp | 1 + List.h | 109 +++++++++++++++++++++++++++++++++++++++++++++++ MMU.cpp | 10 +++++ MMU.h | 20 +++++++++ PTE.cpp | 5 +++ PTE.h | 14 ++++++ PageTable.cpp | 5 +++ PageTable.h | 18 ++++++++ PhysicalPage.cpp | 9 ++++ PhysicalPage.h | 21 +++++++++ Process.cpp | 9 ++++ Process.h | 16 +++++++ main.cpp | 31 ++++++++++++++ 16 files changed, 339 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 Kernel.cpp create mode 100644 Kernel.h create mode 100644 List.cpp create mode 100644 List.h create mode 100644 MMU.cpp create mode 100644 MMU.h create mode 100644 PTE.cpp create mode 100644 PTE.h create mode 100644 PageTable.cpp create mode 100644 PageTable.h create mode 100644 PhysicalPage.cpp create mode 100644 PhysicalPage.h create mode 100644 Process.cpp create mode 100644 Process.h create mode 100644 main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1523f8f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.30) +project(code) + +set(CMAKE_CXX_STANDARD 23) + +add_executable(code main.cpp + List.cpp + List.h + Kernel.cpp + Kernel.h + MMU.cpp + MMU.h + PhysicalPage.cpp + PhysicalPage.h + PageTable.cpp + PageTable.h + PTE.cpp + PTE.h + Process.cpp + Process.h) diff --git a/Kernel.cpp b/Kernel.cpp new file mode 100644 index 0000000..91b5000 --- /dev/null +++ b/Kernel.cpp @@ -0,0 +1,29 @@ +#include "Kernel.h" + +Kernel::Kernel(const List &free_pages, const List &busy_pages) +: free_pages(free_pages), busy_pages(busy_pages) { +} + + +void Kernel::page_fault(PageTable page_table, const int idx) { + PhysicalPage *page; + if (!this->free_pages.is_empty()) { + page = free_pages.last(); + free_pages.remove(page); + busy_pages.insert_tail(page); + } else { + page = nullptr; // TODO: page replacement algorithm + } + if (page) { + 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() { + for (int i = 0; i < 10; ++i) { + // TODO: update busy page stats + } +} diff --git a/Kernel.h b/Kernel.h new file mode 100644 index 0000000..8eb63ee --- /dev/null +++ b/Kernel.h @@ -0,0 +1,22 @@ +#ifndef KERNEL_H +#define KERNEL_H + +#include + +#include "PhysicalPage.h" +#include "PageTable.h" +#include "List.h" +#include "Process.h" + +class Kernel { +public: + List free_pages, busy_pages; + // TODO: RunQ + std::vector RunQ; + Kernel(const List &free_pages, const List &busy_pages); + void page_fault(PageTable page_table, int idx); + void stat_update(); + +}; + +#endif //KERNEL_H diff --git a/List.cpp b/List.cpp new file mode 100644 index 0000000..04a7e82 --- /dev/null +++ b/List.cpp @@ -0,0 +1 @@ +#include "List.h" diff --git a/List.h b/List.h new file mode 100644 index 0000000..e9c11fa --- /dev/null +++ b/List.h @@ -0,0 +1,109 @@ +#ifndef LIST_H +#define LIST_H + +template +class List { + T *head, *tail; + unsigned int num; + const unsigned int idx; + public: + explicit List(unsigned int idx); + T *first(); + T *last(); + void insert_head(T *elem); + void insert_tail(T *elem); + void insert_before(T *elem1, T *elem2); + void remove(T *elem); + bool is_empty(); + [[nodiscard]] unsigned int get_num() const; +}; + +#define for_each_in_list(elem, list) \ + for ( \ + (elem) = (list)->first(); \ + (elem) != nullptr; \ + (elem) = (list)->next(elem) \ + ) + +template +List::List(const unsigned int idx) : head{nullptr}, tail{nullptr}, num{0}, idx{idx} { +} + +template +T * List::first() { + return this->head; +} + +template +T * List::last() { + return this->tail; +} + +template +void List::insert_head(T *elem) { + const unsigned int idx{this->idx}; + + elem->next[idx] = this->head; + elem->prev[idx] = nullptr; + if (this->head != nullptr) + this->head->prev[idx] = elem; + if (this->tail == nullptr) + this->tail = elem; + this->head = elem; + ++this->num; +} + +template +void List::insert_tail(T *elem) { + const unsigned int idx{this->idx}; + + elem->next[idx] = nullptr; + elem->prev[idx] = this->tail; + if (this->tail != nullptr) + this->tail->next[idx] = elem; + if (this->head == nullptr) + this->head = elem; + this->tail = elem; + ++this->num; +} + +template +void List::insert_before(T *elem1, T *elem2) { + const unsigned int idx{this->idx}; + + elem1->next[idx] = elem2; + elem1->prev[idx] = elem2->prev[idx]; + elem2->prev[idx] = elem1; + if (elem1->prev[idx] == nullptr) + this->head = elem1; + else + elem1->prev[idx]->next[idx] = elem1; + ++this->num; +} + +template +void List::remove(T *elem) { + const unsigned int idx{this->idx}; + + if (elem->next[idx] != nullptr) + elem->next[idx]->prev[idx] = elem->prev[idx]; + if (elem->prev[idx] != nullptr) + elem->prev[idx]->next[idx] = elem->next[idx]; + if (this->head == elem) + this->head = elem->next[idx]; + if (this->tail == elem) + this->tail = elem->prev[idx]; + --this->num; +} + +template +bool List::is_empty() { + return this->num == 0; +} + +template +unsigned int List::get_num() const { + return this->num; +} + +#endif //LIST_H diff --git a/MMU.cpp b/MMU.cpp new file mode 100644 index 0000000..8cbe660 --- /dev/null +++ b/MMU.cpp @@ -0,0 +1,10 @@ +#include "MMU.h" + +void MMU::access(Kernel kernel, PageTable table, const int index, const AccessType type) { + if (!table[index].P) + kernel.page_fault(table, index); + table[index].R = true; + + if (type == WRITE) + table[index].M = true; +} diff --git a/MMU.h b/MMU.h new file mode 100644 index 0000000..b389a92 --- /dev/null +++ b/MMU.h @@ -0,0 +1,20 @@ +#ifndef MMU_H +#define MMU_H + +#include "Kernel.h" +#include "PageTable.h" + +enum AccessType { + READ, + WRITE, +}; + +class MMU { + public: + static void access(Kernel kernel, PageTable table, int index, AccessType type); + // TODO type of access +}; + + + +#endif //MMU_H diff --git a/PTE.cpp b/PTE.cpp new file mode 100644 index 0000000..a9c4f0f --- /dev/null +++ b/PTE.cpp @@ -0,0 +1,5 @@ +// +// Created by rhinemann on 10.03.25. +// + +#include "PTE.h" diff --git a/PTE.h b/PTE.h new file mode 100644 index 0000000..1c7e7bb --- /dev/null +++ b/PTE.h @@ -0,0 +1,14 @@ +// +// Created by rhinemann on 10.03.25. +// + +#ifndef PTE_H +#define PTE_H + +class PTE { + public: + bool P, R, M; + unsigned int PPN; +}; + +#endif //PTE_H diff --git a/PageTable.cpp b/PageTable.cpp new file mode 100644 index 0000000..84789a1 --- /dev/null +++ b/PageTable.cpp @@ -0,0 +1,5 @@ +#include "PageTable.h" + +PTE & PageTable::operator[](const int index) { + return this->entries.at(index); +} diff --git a/PageTable.h b/PageTable.h new file mode 100644 index 0000000..f6293fd --- /dev/null +++ b/PageTable.h @@ -0,0 +1,18 @@ +// +// Created by rhinemann on 10.03.25. +// + +#ifndef PAGETABLE_H +#define PAGETABLE_H + +#include + +#include "PTE.h" + +class PageTable { + public: + std::vector entries; + PTE &operator[](int index); +}; + +#endif //PAGETABLE_H diff --git a/PhysicalPage.cpp b/PhysicalPage.cpp new file mode 100644 index 0000000..1f576dc --- /dev/null +++ b/PhysicalPage.cpp @@ -0,0 +1,9 @@ +#include "PhysicalPage.h" + +PhysicalPage::PhysicalPage(const unsigned int PPN): PPN(PPN) { +} + +void PhysicalPage::take_up(PageTable *PT, const unsigned int idx) { + this->idx = idx; + this->PT = PT; +} diff --git a/PhysicalPage.h b/PhysicalPage.h new file mode 100644 index 0000000..bf06c0b --- /dev/null +++ b/PhysicalPage.h @@ -0,0 +1,21 @@ +// +// Created by rhinemann on 10.03.25. +// + +#ifndef PHYSICALPAGE_H +#define PHYSICALPAGE_H + +#include "PageTable.h" + +class PhysicalPage { + public: + unsigned int PPN, idx; + PageTable *PT; + PhysicalPage *next[2], *prev[2]; + + explicit PhysicalPage(unsigned int PPN); + + void take_up(PageTable *PT, unsigned int idx); +}; + +#endif //PHYSICALPAGE_H diff --git a/Process.cpp b/Process.cpp new file mode 100644 index 0000000..e20e0d5 --- /dev/null +++ b/Process.cpp @@ -0,0 +1,9 @@ +#include "Process.h" + +Process::Process(PageTable *pageTable, const unsigned int executionTime) +: pageTable(pageTable), executionTime(executionTime), elapsedTime(0) { +} + +bool Process::is_finished() { + return elapsedTime >= executionTime; +} diff --git a/Process.h b/Process.h new file mode 100644 index 0000000..74f6f1b --- /dev/null +++ b/Process.h @@ -0,0 +1,16 @@ +#ifndef PROCESS_H +#define PROCESS_H + +#include "PageTable.h" + +class Process { + public: + PageTable *pageTable; + unsigned int executionTime, elapsedTime; + Process(PageTable *pageTable, unsigned int executionTime); + bool is_finished(); +}; + + + +#endif //PROCESS_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..a3a0b92 --- /dev/null +++ b/main.cpp @@ -0,0 +1,31 @@ +#include +#include + +#include "Kernel.h" + +static int MAX_PROC = 10; +static int PAGE_N = 10; + +int main() { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution distribution(0, 10); + + List free_pages(0), busy_pages(0); + Kernel kernel(free_pages, busy_pages); + + for (int i = 0; i < PAGE_N; ++i) { + free_pages.insert_tail(new PhysicalPage(i)); + } + + for (int i = 0; i < MAX_PROC; ++i) { + kernel.RunQ.emplace_back(nullptr, distribution(gen)); + } + + for (const auto process : kernel.RunQ) + std::cout << process.executionTime << std::endl; + + // std::cout << MAX_PROC << std::endl; + + return 0; +}