Finalised the lab work. #1
@ -4,10 +4,8 @@
 | 
			
		||||
 | 
			
		||||
using std::next;
 | 
			
		||||
 | 
			
		||||
Kernel::Kernel(const unsigned int RunQ_max_length, const List<PhysicalPage> &free_pages, const List<PhysicalPage> &busy_pages)
 | 
			
		||||
: free_pages(free_pages), busy_pages(busy_pages), swapped_page(nullptr) {
 | 
			
		||||
    RunQ.reserve(RunQ_max_length);
 | 
			
		||||
}
 | 
			
		||||
Kernel::Kernel(const List<PhysicalPage> &free_pages, const List<PhysicalPage> &busy_pages)
 | 
			
		||||
: free_pages(free_pages), busy_pages(busy_pages) {}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								Kernel.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Kernel.h
									
									
									
									
									
								
							@ -11,9 +11,8 @@
 | 
			
		||||
class Kernel {
 | 
			
		||||
public:
 | 
			
		||||
        List<PhysicalPage> free_pages, busy_pages;
 | 
			
		||||
        PhysicalPage *swapped_page;
 | 
			
		||||
        std::vector<Process> RunQ;
 | 
			
		||||
        Kernel(unsigned int RunQ_max_length, const List<PhysicalPage> &free_pages, const List<PhysicalPage> &busy_pages);
 | 
			
		||||
        List<Process> RunQ;
 | 
			
		||||
        Kernel(const List<PhysicalPage> &free_pages, const List<PhysicalPage> &busy_pages);
 | 
			
		||||
        void page_fault(std::vector<PTE> *page_table, unsigned int idx);
 | 
			
		||||
        void stat_update();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								Process.cpp
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Process.cpp
									
									
									
									
									
								
							@ -1,11 +1,19 @@
 | 
			
		||||
#include "Process.h"
 | 
			
		||||
 | 
			
		||||
#include <random>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
Process::Process(const unsigned int id, std::vector<PTE> pageTable, const unsigned int executionTime)
 | 
			
		||||
: pageTable(std::move(pageTable)), executionTime(executionTime), id(id) {
 | 
			
		||||
Process::Process(const unsigned int id, std::vector<PTE> page_table, const unsigned int working_set_size,
 | 
			
		||||
    const unsigned int execution_time) : page_table(std::move(page_table)), execution_time(execution_time), elapsed_time(0),
 | 
			
		||||
                                         id(id), next(nullptr), prev(nullptr) {
 | 
			
		||||
    std::random_device rd;
 | 
			
		||||
    std::mt19937 gen(rd());
 | 
			
		||||
    std::uniform_int_distribution<unsigned int> page_table_distribution(0, this->page_table.size() - 1);
 | 
			
		||||
    for (int i = 0; i < working_set_size; ++i) {
 | 
			
		||||
        working_set.push_back(page_table_distribution(gen));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Process::is_finished(const unsigned int elapsedTime) const {
 | 
			
		||||
    return elapsedTime >= executionTime;
 | 
			
		||||
bool Process::is_finished() const {
 | 
			
		||||
    return elapsed_time >= execution_time;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								Process.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Process.h
									
									
									
									
									
								
							@ -4,11 +4,14 @@
 | 
			
		||||
#include "PageTable.h"
 | 
			
		||||
 | 
			
		||||
class Process {
 | 
			
		||||
    public:
 | 
			
		||||
        std::vector<PTE> pageTable;
 | 
			
		||||
        unsigned int executionTime, id;
 | 
			
		||||
        Process(unsigned int id, std::vector<PTE> pageTable, unsigned int executionTime);
 | 
			
		||||
        [[nodiscard]] bool is_finished(unsigned int elapsedTime) const;
 | 
			
		||||
public:
 | 
			
		||||
    std::vector<PTE> page_table;
 | 
			
		||||
    std::vector<unsigned int> working_set;
 | 
			
		||||
    unsigned int execution_time, elapsed_time, id;
 | 
			
		||||
    Process *next, *prev;
 | 
			
		||||
 | 
			
		||||
    Process(unsigned int id, std::vector<PTE> page_table, unsigned int working_set_size, unsigned int execution_time);
 | 
			
		||||
    [[nodiscard]] bool is_finished() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								main.cpp
									
									
									
									
									
								
							@ -7,42 +7,49 @@
 | 
			
		||||
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<unsigned int> page_table_distribution(500, 1000), lifetime_distribution(50, 500), access_type_distr(1, 10);
 | 
			
		||||
 | 
			
		||||
    Kernel kernel(MAX_PROC, List<PhysicalPage>(), List<PhysicalPage>());
 | 
			
		||||
    Kernel kernel = Kernel(List<PhysicalPage>(), List<PhysicalPage>());
 | 
			
		||||
    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 < kernel.RunQ.capacity(); ++i) {
 | 
			
		||||
        kernel.RunQ.emplace_back(i, std::vector(page_table_distribution(gen), PTE()), lifetime_distribution(gen));
 | 
			
		||||
    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 < 10000; ++i) {
 | 
			
		||||
        if (kernel.RunQ.empty()) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    for (int i = 0; i < 10'000; ++i) {
 | 
			
		||||
        Process *current_process = kernel.RunQ.get_head();
 | 
			
		||||
 | 
			
		||||
        std::uniform_int_distribution<unsigned int> index_distribution(0, kernel.RunQ.at(0).pageTable.size() - 1);
 | 
			
		||||
        std::uniform_int_distribution<unsigned int> index_distribution;
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
            if (access_type_distr(gen) == 1) {
 | 
			
		||||
                index_distribution = std::uniform_int_distribution<unsigned int>(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<unsigned int>(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);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ++elapsed_time;
 | 
			
		||||
        ++current_process->elapsed_time;
 | 
			
		||||
        ++new_proc_time;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
        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;
 | 
			
		||||
@ -51,17 +58,19 @@ int main() {
 | 
			
		||||
                 curr && j < cached_len;
 | 
			
		||||
                 curr = cached_next, ++j) {
 | 
			
		||||
                cached_next = curr->next;
 | 
			
		||||
                if (curr->PT == &kernel.RunQ.at(0).pageTable) {
 | 
			
		||||
                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.erase(kernel.RunQ.begin());
 | 
			
		||||
 | 
			
		||||
            kernel.RunQ.set_head(current_process->next);
 | 
			
		||||
            kernel.RunQ.remove(current_process);
 | 
			
		||||
 | 
			
		||||
            if (new_proc_time >= PROC_CREATION_INTERVAL) {
 | 
			
		||||
                kernel.RunQ.emplace_back(new_ppn, std::vector(page_table_distribution(gen), PTE()), lifetime_distribution(gen));
 | 
			
		||||
                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;
 | 
			
		||||
            }
 | 
			
		||||
@ -72,10 +81,13 @@ int main() {
 | 
			
		||||
            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()) {
 | 
			
		||||
        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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user