2025-03-06 21:50:29 +02:00
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdlib.h>
|
2025-03-06 23:05:21 +02:00
|
|
|
#include <stdio.h>
|
2025-03-06 21:50:29 +02:00
|
|
|
|
|
|
|
#include "kernel.h"
|
|
|
|
#include "process.h"
|
|
|
|
|
2025-03-07 10:35:51 +02:00
|
|
|
#include "config.h"
|
2025-03-06 23:05:21 +02:00
|
|
|
|
|
|
|
extern struct RunQ *runq;
|
|
|
|
|
|
|
|
extern struct PhysPage *first_free_page;
|
|
|
|
extern struct PhysPage *first_busy_page;
|
|
|
|
|
|
|
|
|
2025-03-06 21:50:29 +02:00
|
|
|
struct RunQ *
|
|
|
|
RunQ(size_t max_procs)
|
|
|
|
{
|
|
|
|
struct RunQ *runq = malloc(sizeof(struct RunQ));
|
|
|
|
runq->current_proc = NULL;
|
|
|
|
runq->max_procs = max_procs;
|
|
|
|
runq->proc_amount = 0;
|
|
|
|
runq->next_proc_id = 1;
|
|
|
|
|
|
|
|
return runq;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RUNQ_add_process(size_t max_page_accesses,
|
|
|
|
size_t total_pages_owned)
|
|
|
|
{
|
|
|
|
if (runq->proc_amount >= runq->max_procs)
|
|
|
|
return;
|
|
|
|
|
|
|
|
struct Process *new_p = Process(runq->next_proc_id, max_page_accesses, total_pages_owned);
|
|
|
|
|
|
|
|
if (!runq->current_proc) {
|
|
|
|
runq->current_proc = new_p;
|
|
|
|
new_p->next = new_p;
|
|
|
|
new_p->prev = new_p;
|
|
|
|
} else {
|
|
|
|
new_p->next = runq->current_proc;
|
|
|
|
new_p->prev = runq->current_proc->prev;
|
|
|
|
new_p->next->prev = new_p;
|
|
|
|
new_p->prev->next = new_p;
|
|
|
|
runq->current_proc = new_p;
|
|
|
|
}
|
|
|
|
|
|
|
|
runq->proc_amount++;
|
|
|
|
runq->next_proc_id++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
KERNEL_page_fault(struct PageTableEntry *pt, size_t page_no)
|
|
|
|
{
|
2025-03-06 23:05:21 +02:00
|
|
|
printf("[kernel:page_fault] Handling %d started\n", page_no);
|
|
|
|
|
2025-03-06 21:50:29 +02:00
|
|
|
if (first_free_page) {
|
2025-03-06 23:05:21 +02:00
|
|
|
printf("[kernel:page_fault] Found free page #%d, using it\n", first_free_page->ppn);
|
2025-03-06 21:50:29 +02:00
|
|
|
pt[page_no].ppn = first_free_page->ppn;
|
|
|
|
pt[page_no].p = 1;
|
2025-03-06 23:05:21 +02:00
|
|
|
|
|
|
|
first_free_page->busy_flag = 1;
|
|
|
|
first_free_page->pt = pt;
|
|
|
|
first_free_page->pt_index = page_no;
|
|
|
|
|
|
|
|
// ---- free list -> busy list ----
|
|
|
|
struct PhysPage *this_page = first_free_page;
|
|
|
|
|
|
|
|
if (first_free_page->next != first_free_page) {
|
|
|
|
// reconnect free list items together
|
|
|
|
first_free_page->prev->next = first_free_page->next;
|
|
|
|
first_free_page->next->prev = first_free_page->prev;
|
|
|
|
first_free_page = first_free_page->next;
|
|
|
|
} else {
|
|
|
|
// clear list if it only had this page
|
|
|
|
first_free_page = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!first_busy_page) {
|
|
|
|
// initialize the busy list with this page
|
|
|
|
first_busy_page = this_page;
|
|
|
|
} else {
|
|
|
|
// insert this page at the end of the list
|
|
|
|
this_page->next = first_busy_page;
|
|
|
|
this_page->prev = first_busy_page->prev;
|
|
|
|
this_page->prev->next = this_page;
|
|
|
|
this_page->next->prev = this_page;
|
|
|
|
}
|
2025-03-07 10:35:51 +02:00
|
|
|
} else {
|
|
|
|
printf("[kernel:page_fault] No free pages available, trying to swap...\n");
|
|
|
|
|
|
|
|
#if PAGE_REPLACEMENT_ALGORITHM == 1
|
|
|
|
printf("[kernel:page_fault:random] Selected physical page #%d for replacement\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: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");
|
|
|
|
#endif
|
2025-03-06 21:50:29 +02:00
|
|
|
}
|
|
|
|
}
|