Compare commits

..

1 Commits

Author SHA1 Message Date
rhinemann cac03a91a5 Added the working set, broke the program, segfault. 2025-04-01 20:17:08 +03:00
5 changed files with 53 additions and 44 deletions

View File

@ -4,8 +4,10 @@
using std::next; using std::next;
Kernel::Kernel(const List<PhysicalPage> &free_pages, const List<PhysicalPage> &busy_pages) Kernel::Kernel(const unsigned int RunQ_max_length, const List<PhysicalPage> &free_pages,
: free_pages(free_pages), busy_pages(busy_pages) {} const List<PhysicalPage> &busy_pages) : free_pages(free_pages), busy_pages(busy_pages) {
RunQ.reserve(RunQ_max_length);
}
void Kernel::page_fault(std::vector<PTE> *page_table, const unsigned int idx) { void Kernel::page_fault(std::vector<PTE> *page_table, const unsigned int idx) {
std::cout << std::format("[kernel:page_fault] Handling {} started", idx) << std::endl; std::cout << std::format("[kernel:page_fault] Handling {} started", idx) << std::endl;
@ -16,20 +18,24 @@ void Kernel::page_fault(std::vector<PTE> *page_table, const unsigned int idx) {
free_pages.remove(page); free_pages.remove(page);
busy_pages.insert_tail(page); busy_pages.insert_tail(page);
std::cout << std::format("[kernel:page_fault:free] Found free page #{}, using it", page->PPN) << std::endl; std::cout << std::format("[kernel:page_fault:free] Found free page #{}, using it",
page->PPN) << std::endl;
} else { } else {
std::cout << "[kernel:page_fault] No free pages available, trying to swap..." << std::endl; std::cout << "[kernel:page_fault] No free pages available, trying to swap..." << std::endl;
for (PhysicalPage *curr = busy_pages.get_head();; curr = curr->next) { for (PhysicalPage *curr = busy_pages.get_head();; curr = curr->next) {
if ((*curr->PT)[curr->idx].R) if ((*curr->PT)[curr->idx].R)
(*curr->PT)[curr->idx].R = false; (*curr->PT)[curr->idx].R = false;
else { else {
std::cout << std::format("[kernel:page_fault:random] Selected physical page #{} for replacement", curr->PPN) << std::endl; 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)); // curr->PT->erase(next(curr->PT->begin(), curr->idx));
(*curr->PT)[curr->idx].P = false;
page = curr; page = curr;
busy_pages.set_head(curr->next); 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; 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; break;
} }
} }
@ -52,4 +58,5 @@ void Kernel::stat_update() {
std::cout << std::format("[kernel:update_job] Updating ppn {} status", curr->PPN) << std::endl; std::cout << std::format("[kernel:update_job] Updating ppn {} status", curr->PPN) << std::endl;
} }
} }
busy_pages.set_head(curr);
} }

View File

@ -11,8 +11,8 @@
class Kernel { class Kernel {
public: public:
List<PhysicalPage> free_pages, busy_pages; List<PhysicalPage> free_pages, busy_pages;
List<Process> RunQ; std::vector<Process> RunQ;
Kernel(const List<PhysicalPage> &free_pages, const List<PhysicalPage> &busy_pages); Kernel(unsigned int RunQ_max_length, const List<PhysicalPage> &free_pages, const List<PhysicalPage> &busy_pages);
void page_fault(std::vector<PTE> *page_table, unsigned int idx); void page_fault(std::vector<PTE> *page_table, unsigned int idx);
void stat_update(); void stat_update();

View File

@ -1,19 +1,21 @@
#include "Process.h" #include "Process.h"
#include <iostream>
#include <ostream>
#include <random> #include <random>
#include <utility> #include <utility>
Process::Process(const unsigned int id, std::vector<PTE> page_table, const unsigned int working_set_size, Process::Process(const unsigned int id, std::vector<PTE> page_table, const unsigned int execution_time, const unsigned int working_set_size)
const unsigned int execution_time) : page_table(std::move(page_table)), execution_time(execution_time), elapsed_time(0), : page_table(std::move(page_table)), execution_time(execution_time), id(id) {
id(id), next(nullptr), prev(nullptr) {
std::random_device rd; std::random_device rd;
std::mt19937 gen(rd()); std::mt19937 gen(rd());
std::uniform_int_distribution<unsigned int> page_table_distribution(0, this->page_table.size() - 1); std::uniform_int_distribution<unsigned int> working_set_distribution(0, this->page_table.size() - 1);
std::cout << page_table.size() - 1 << std::endl;
for (int i = 0; i < working_set_size; ++i) { for (int i = 0; i < working_set_size; ++i) {
working_set.push_back(page_table_distribution(gen)); working_set.push_back(working_set_distribution(gen));
} }
} }
bool Process::is_finished() const { bool Process::is_finished(const unsigned int elapsed_time) const {
return elapsed_time >= execution_time; return elapsed_time >= execution_time;
} }

View File

@ -7,13 +7,9 @@ class Process {
public: public:
std::vector<PTE> page_table; std::vector<PTE> page_table;
std::vector<unsigned int> working_set; std::vector<unsigned int> working_set;
unsigned int execution_time, elapsed_time, id; unsigned int execution_time, id;
Process *next, *prev; Process(unsigned int id, std::vector<PTE> page_table, unsigned int execution_time, unsigned int working_set_size);
[[nodiscard]] bool is_finished(unsigned int elapsed_time) const;
Process(unsigned int id, std::vector<PTE> page_table, unsigned int working_set_size, unsigned int execution_time);
[[nodiscard]] bool is_finished() const;
}; };
#endif //PROCESS_H #endif //PROCESS_H

View File

@ -14,42 +14,48 @@ int main() {
std::mt19937 gen(rd()); std::mt19937 gen(rd());
std::uniform_int_distribution<unsigned int> page_table_distribution(500, 1000), lifetime_distribution(50, 500), access_type_distr(1, 10); std::uniform_int_distribution<unsigned int> page_table_distribution(500, 1000), lifetime_distribution(50, 500), access_type_distr(1, 10);
Kernel kernel = Kernel(List<PhysicalPage>(), List<PhysicalPage>()); Kernel kernel(MAX_PROC, List<PhysicalPage>(), List<PhysicalPage>());
unsigned int elapsed_time = 0, new_proc_time = 0, new_ppn; unsigned int elapsed_time = 0, new_proc_time = 0, new_ppn;
for (new_ppn = 1; new_ppn <= PAGE_N; ++new_ppn) { for (new_ppn = 1; new_ppn <= PAGE_N; ++new_ppn) {
kernel.free_pages.insert_head(new PhysicalPage(new_ppn)); kernel.free_pages.insert_head(new PhysicalPage(new_ppn));
} }
for (int i = 0; i < MAX_PROC; ++i) { for (int i = 0; i < kernel.RunQ.capacity(); ++i) {
kernel.RunQ.insert_head(new Process(i, std::vector(page_table_distribution(gen), PTE()), WORKING_SET_SIZE, lifetime_distribution(gen))); kernel.RunQ.emplace_back(i, std::vector(page_table_distribution(gen), PTE()), lifetime_distribution(gen),
WORKING_SET_SIZE);
} }
for (int i = 0; i < 10'000; ++i) { for (int i = 0; i < 10'000; ++i) {
Process *current_process = kernel.RunQ.get_head(); const int process_index = i % kernel.RunQ.size();
if (kernel.RunQ.empty()) {
break;
}
std::uniform_int_distribution<unsigned int> index_distribution; std::uniform_int_distribution<unsigned int> index_distribution;
for (int j = 0; j < 30; ++j) { for (int j = 0; j < 30; ++j) {
const AccessType type = access_type_distr(gen) == 1 ? WRITE : READ; const AccessType access_type = access_type_distr(gen) == 1 ? WRITE : READ;
if (access_type_distr(gen) == 1) { if (access_type_distr(gen) == 1) {
index_distribution = std::uniform_int_distribution<unsigned int>(0, current_process->page_table.size() - 1); index_distribution = std::uniform_int_distribution<unsigned int>(0, kernel.RunQ.at(process_index).page_table.size() - 1);
const unsigned int table_index = index_distribution(gen); const unsigned int table_index = index_distribution(gen);
MMU::access(kernel, &current_process->page_table, table_index, type); MMU::access(kernel, &kernel.RunQ.at(process_index).page_table, table_index, access_type);
} else { }
index_distribution = std::uniform_int_distribution<unsigned int>(0, current_process->working_set.size() - 1); else {
const unsigned int table_index = index_distribution(gen); index_distribution = std::uniform_int_distribution<unsigned int>(0, kernel.RunQ.at(process_index).working_set.size() - 1);
MMU::access(kernel, &current_process->page_table, current_process->working_set[table_index], type); const unsigned int table_index = kernel.RunQ.at(process_index).working_set[index_distribution(gen)];
MMU::access(kernel, &kernel.RunQ.at(process_index).page_table, table_index, access_type);
} }
} }
++current_process->elapsed_time; ++elapsed_time;
++new_proc_time; ++new_proc_time;
kernel.stat_update(); kernel.stat_update();
if (current_process->is_finished()) { if (kernel.RunQ.at(process_index).is_finished(elapsed_time)) {
std::cout << std::format("[kernel:remove_current_process] Cleaning up process id {}", current_process->id) << std::endl; std::cout << std::format("[kernel:remove_current_process] Cleaning up process id {}", kernel.RunQ.at(process_index).id) << std::endl;
PhysicalPage *curr, *cached_next; PhysicalPage *curr, *cached_next;
unsigned int j; unsigned int j;
@ -58,19 +64,20 @@ int main() {
curr && j < cached_len; curr && j < cached_len;
curr = cached_next, ++j) { curr = cached_next, ++j) {
cached_next = curr->next; cached_next = curr->next;
if (curr->PT == &current_process->page_table) { if (curr->PT == &kernel.RunQ.at(process_index).page_table) {
std::cout << std::format("[kernel:remove_current_process] Found ppn #{}, freeing it", curr->PPN) << std::endl; std::cout << std::format("[kernel:remove_current_process] Found ppn #{}, freeing it", curr->PPN) << std::endl;
kernel.busy_pages.remove(curr); kernel.busy_pages.remove(curr);
curr->PT = nullptr;
kernel.free_pages.insert_tail(curr); kernel.free_pages.insert_tail(curr);
} }
} }
kernel.RunQ.erase(kernel.RunQ.begin());
kernel.RunQ.set_head(current_process->next);
kernel.RunQ.remove(current_process);
if (new_proc_time >= PROC_CREATION_INTERVAL) { 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))); kernel.RunQ.emplace_back(new_ppn, std::vector(page_table_distribution(gen), PTE()), lifetime_distribution(gen), WORKING_SET_SIZE);
++new_ppn; ++new_ppn;
new_proc_time = 0; new_proc_time = 0;
} }
@ -81,13 +88,10 @@ int main() {
std::cout << std::format("[main:metrics] Memory usage stats: busy {}, free {}, total {}", busy_stat, free_stat, free_stat + busy_stat) << std::endl; 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()) { if (kernel.RunQ.empty()) {
std::cout << "[main:scheduling] No processes left to execute!" << std::endl; std::cout << "[main:scheduling] No processes left to execute!" << std::endl;
break;
} }
} }
std::cout << "[main:scheduling] Simulation finished." << std::endl;
return 0; return 0;
} }