From 775eb861fff678cb02867f4d6bd074c0d66a7d48 Mon Sep 17 00:00:00 2001 From: hasslesstech Date: Fri, 7 Mar 2025 15:44:45 +0200 Subject: [PATCH] add wsclock and background page analysis job implementations --- config.h | 3 +- inc/kernel.h | 3 ++ src/kernel.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/main.c | 11 ++++---- 4 files changed, 90 insertions(+), 7 deletions(-) diff --git a/config.h b/config.h index e201281..fe26c6a 100644 --- a/config.h +++ b/config.h @@ -1,2 +1,3 @@ #define PHYSICAL_PAGE_AMOUNT 64 -#define PAGE_REPLACEMENT_ALGORITHM 1 +#define PAGE_REPLACEMENT_ALGORITHM 2 +#define WSCLOCK_TIME_WINDOW 15 diff --git a/inc/kernel.h b/inc/kernel.h index 6ccc914..534d794 100644 --- a/inc/kernel.h +++ b/inc/kernel.h @@ -18,6 +18,7 @@ void RUNQ_add_process(size_t max_page_accesses, size_t total_pages_owned); struct PhysPage { size_t ppn; size_t busy_flag; + size_t last_accessed; struct PhysPage *prev; struct PhysPage *next; struct PageTableEntry *pt; @@ -27,4 +28,6 @@ struct PhysPage { void KERNEL_page_fault(struct PageTableEntry *pt, size_t page_no); +void KERNEL_update_job(size_t page_amount); + #endif diff --git a/src/kernel.c b/src/kernel.c index be61a45..54ddfff 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -12,6 +12,8 @@ extern struct RunQ *runq; extern struct PhysPage *first_free_page; extern struct PhysPage *first_busy_page; +extern size_t system_time; + struct RunQ * RunQ(size_t max_procs) @@ -110,7 +112,83 @@ KERNEL_page_fault(struct PageTableEntry *pt, size_t page_no) printf("[kernel:page_fault:random] Auto-advanced the list of busy pages to ppn %d\n", first_busy_page->ppn); #elif PAGE_REPLACEMENT_ALGORITHM == 2 - printf("[kernel:page_fault:wsclock] Not implemented\n"); + + // first pass (no reference flag + out of time window) + for (size_t i = 0; i < PHYSICAL_PAGE_AMOUNT; i++) { + if (first_busy_page->pt[first_busy_page->pt_index].r) { + printf("[kernel:page_fault:wsclock] ppn %d: r = 1, time %d -> %d\n", + first_busy_page->ppn, first_busy_page->last_accessed, system_time); + first_busy_page->last_accessed = system_time; + first_busy_page->pt[first_busy_page->pt_index].r = 0; + + first_busy_page = first_busy_page->next; + } else if ((system_time - first_busy_page->last_accessed) > WSCLOCK_TIME_WINDOW) { + printf("[kernel:page_fault:wsclock] ppn %d: r = 0, time_window = %d (> WSCLOCK_TIME_WINDOW), using it\n", + first_busy_page->ppn, system_time - first_busy_page->last_accessed); + first_busy_page->pt[first_busy_page->pt_index].p = 0; + first_busy_page->pt = pt; + first_busy_page->pt_index = page_no; + pt[page_no].p = 1; + pt[page_no].ppn = first_busy_page->ppn; + + first_busy_page = first_busy_page->next; + + goto page_replacement_resolved; + } else { + printf("[kernel:page_fault:wsclock] ppn %d: r = 0, time_window = %d (<= WSCLOCK_TIME_WINDOW), still active\n", + first_busy_page->ppn, system_time - first_busy_page->last_accessed); + + first_busy_page = first_busy_page->next; + } + } + + // fallback to random + printf("[kernel:page_fault:wsclock] Failed to find non-active page, randomly selecting ppn %d\n", first_busy_page->ppn); + + // clear presence 'bit' from old PTE + first_busy_page->pt[first_busy_page->pt_index].p = 0; + + // update physical page data + first_busy_page->pt = pt; + first_busy_page->pt_index = page_no; + + // update PTE data + pt[page_no].p = 1; + pt[page_no].ppn = first_busy_page->ppn; + + // move hand to next physical page + first_busy_page = first_busy_page->next; + + printf("[kernel:page_fault:wsclock] Auto-advanced the list of busy pages to ppn %d\n", first_busy_page->ppn); + +page_replacement_resolved: #endif } } + +void KERNEL_update_job(size_t page_amount) +{ + if (first_busy_page == NULL) { + printf("[kernel:update_job] No pages to update\n"); + return; + } + + struct PhysPage *starting_page = first_busy_page; + + for (size_t i = 0; i < page_amount; i++) { + if (first_busy_page->pt[first_busy_page->pt_index].r) { + printf("[kernel:update_job] ppn %d updated time %d -> %d\n", first_busy_page->ppn, first_busy_page->last_accessed, system_time); + first_busy_page->pt[first_busy_page->pt_index].r = 0; + first_busy_page->last_accessed = system_time; + } else { + printf("[kernel:update_job] ppn %d is up-to-date (time = %d)\n", first_busy_page->ppn, first_busy_page->last_accessed); + } + + first_busy_page = first_busy_page->next; + + if (first_busy_page == starting_page) { + printf("[kernel:update_job] Looped around the busy page list, exiting after %d iterations\n", i); + break; + } + } +} diff --git a/src/main.c b/src/main.c index eddff4c..d8cf5c5 100644 --- a/src/main.c +++ b/src/main.c @@ -28,7 +28,7 @@ main(void) first_free_page->prev = first_free_page; first_free_page->next = first_free_page; - for (int i = 1; i <= PHYSICAL_PAGE_AMOUNT; i++) { + for (int i = 1; i < PHYSICAL_PAGE_AMOUNT; i++) { struct PhysPage *pp = malloc(sizeof(struct PhysPage)); pp->ppn = i; pp->busy_flag = 0; @@ -50,12 +50,13 @@ main(void) runq = RunQ(10); - for (size_t i = 0; i < 5; i++) { - RUNQ_add_process(10000, 10 + randint(70)); + for (size_t i = 0; i < 10; i++) { + RUNQ_add_process(10000, 10 + randint(90)); } - for (int i = 0; i < 20; i++) { - PROCESS_run_for(runq->current_proc, 20); + for (int i = 0; i < 100; i++) { + PROCESS_run_for(runq->current_proc, 50); runq->current_proc = runq->current_proc->next; + KERNEL_update_job(8); } }