Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
cac03a91a5 |
19
Kernel.cpp
19
Kernel.cpp
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
4
Kernel.h
4
Kernel.h
|
@ -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();
|
||||||
|
|
||||||
|
|
14
Process.cpp
14
Process.cpp
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
10
Process.h
10
Process.h
|
@ -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
|
||||||
|
|
50
main.cpp
50
main.cpp
|
@ -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, ¤t_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, ¤t_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 == ¤t_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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue