Merge branch 'vm/lazy-loading' into vm/page-swap-synch

This commit is contained in:
Themis Demetriades
2024-12-04 19:11:37 +00:00
parent 4bf6914cfa
commit 1e236a5c47
7 changed files with 59 additions and 43 deletions

View File

@@ -5,13 +5,13 @@
#include "userprog/gdt.h"
#include "threads/interrupt.h"
#include "threads/thread.h"
#include "userprog/pagedir.h"
#ifdef VM
#include "vm/stackgrowth.h"
#include "vm/frame.h"
#include "vm/page.h"
#include "devices/swap.h"
#include "threads/vaddr.h"
#include "userprog/pagedir.h"
#endif
/* Number of page faults processed. */
@@ -19,6 +19,7 @@ static long long page_fault_cnt;
static void kill (struct intr_frame *);
static void page_fault (struct intr_frame *);
bool try_fetch_page (void *upage, bool write);
/* Registers handlers for interrupts that can be caused by user
programs.
@@ -156,6 +157,7 @@ page_fault (struct intr_frame *f)
#ifdef VM
struct thread *t = thread_current ();
void *upage = pg_round_down (fault_addr);
if (user)
{
if (not_present)
@@ -167,7 +169,6 @@ page_fault (struct intr_frame *f)
if (page_in_swap (t, fault_addr))
{
size_t swap_slot = page_get_swap (t, fault_addr);
void *upage = pg_round_down (fault_addr);
void *kpage = frame_alloc (0, upage, t);
swap_in (kpage, swap_slot);
@@ -192,6 +193,15 @@ page_fault (struct intr_frame *f)
f->eax = 0xffffffff;
return;
}
/* If the fault address is in a user page that is not present, then it might
just need to be lazily loaded. So, we check our SPT to see if the page
is expected to have data loaded in memory. */
if (not_present && is_user_vaddr (upage) && upage != NULL)
{
if (try_fetch_page (upage, write))
return;
}
#endif
/* To implement virtual memory, delete the rest of the function
@@ -205,3 +215,32 @@ page_fault (struct intr_frame *f)
kill (f);
}
bool
try_fetch_page (void *upage, bool write)
{
/* Check if the page is in the supplemental page table. That is, it is a page
that is expected to be in memory. */
struct page_entry *page = page_get (upage);
if (page == NULL)
return false;
/* An attempt to write to a non-writeable should fail. */
if (write && !page->writable)
return false;
/* Load the page into memory based on the type of data it is expecting. */
bool success = false;
switch (page->type) {
case PAGE_EXECUTABLE:
success = page_load (page, page->writable);
break;
default:
return false;
}
if (success && page->writable &&
!pagedir_is_writable(thread_current()->pagedir, upage))
pagedir_set_writable(thread_current()->pagedir, upage, true);
return success;
}