From 0b08893aaff77932a7698a6620cfff40a662b4f2 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Sat, 30 Nov 2024 01:54:10 +0000 Subject: [PATCH] Update page_load to create and use the shared read-only pages of executables, w/ G --- src/threads/thread.c | 3 +++ src/vm/page.c | 52 +++++++++++++++++++++++++++++++++++++------- src/vm/page.h | 2 ++ 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/threads/thread.c b/src/threads/thread.c index abf50d4..8487ff8 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -134,9 +134,12 @@ thread_start (void) t)) PANIC ("Failed to initialise child results table for main thread."); + /* Initialise the shared files table and lock. */ if (!hash_init (&shared_files, shared_file_hash, shared_file_less, NULL)) PANIC ("Failed to initialise shared pages table."); + lock_init (&shared_files_lock); + /* Create the idle thread. */ struct semaphore idle_started; sema_init (&idle_started, 0); diff --git a/src/vm/page.c b/src/vm/page.c index d8b31c7..7c9f7c2 100644 --- a/src/vm/page.c +++ b/src/vm/page.c @@ -3,9 +3,12 @@ #include "filesys/file.h" #include "threads/malloc.h" #include "threads/palloc.h" +#include "threads/vaddr.h" #include "userprog/process.h" #include "vm/frame.h" +static struct shared_page_entry *shared_page_insert (struct file *file, + void *upage, void *frame); static struct shared_file_entry *shared_file_get (struct file *file); static unsigned shared_page_hash (const struct hash_elem *e, void *aux UNUSED); static bool shared_page_less (const struct hash_elem *a_, @@ -73,6 +76,23 @@ page_get (void *upage) bool page_load (struct page_entry *page, bool writable) { + /* If the page is read-only, we want to check if it is a shared page already + loaded into memory. If it is, we can just map the page to the frame. */ + if (!page->writable) + { + ASSERT (page->read_bytes == PGSIZE); + + struct shared_page_entry *shared_page = + shared_page_get (page->file, page->upage); + + if (shared_page != NULL) + { + /* Map the page to the shared frame for this read-only portion. */ + if (!install_page (page->upage, shared_page->frame, false)) + return false; + } + } + /* Allocate a frame for the page. If a frame allocation fails, then frame_alloc should try to evict a page. If it is still NULL, the OS panics as this should not happen if eviction is working correctly. */ @@ -81,7 +101,7 @@ page_load (struct page_entry *page, bool writable) PANIC ("Could not allocate a frame to load page into memory."); /* Map the page to the frame. */ - if (!install_page (page->upage, frame, writable)) + if (!install_page (page->upage, frame, page->writable)) { frame_free (frame); return false; @@ -100,6 +120,16 @@ page_load (struct page_entry *page, bool writable) /* Zero out the remaining bytes in the frame. */ memset (frame + page->read_bytes, 0, page->zero_bytes); + /* If the page is read-only, we need to add it to the shared pages table. */ + if (!page->writable) + { + if (shared_page_insert (page->file, page->upage, frame) == NULL) + { + frame_free (frame); + return false; + } + } + /* Mark the page as loaded successfully. */ return true; } @@ -190,21 +220,32 @@ shared_page_get (struct file *file, void *upage) return hash_entry (e, struct shared_page_entry, elem); } -struct shared_page_entry * +static struct shared_page_entry * shared_page_insert (struct file *file, void *upage, void *frame) { struct shared_file_entry *shared_file = shared_file_get (file); + + /* Allocate a new shared_page_entry first for easier error handling. */ + struct shared_page_entry *shared_page + = malloc (sizeof (struct shared_page_entry)); + if (shared_page == NULL) + return NULL; + /* If shared file doesn't exist in table, also create it. */ if (shared_file == NULL) { shared_file = malloc (sizeof (struct shared_file_entry)); if (shared_file == NULL) - return NULL; + { + free (shared_page); + return NULL; + } shared_file->file = file; shared_file->ref_count = 0; if (!hash_init (&shared_file->pages, shared_page_hash, shared_page_less, NULL)) { + free (shared_page); free (shared_file); return NULL; } @@ -212,11 +253,6 @@ shared_page_insert (struct file *file, void *upage, void *frame) hash_insert (&shared_files, &shared_file->elem); } - struct shared_page_entry *shared_page - = malloc (sizeof (struct shared_page_entry)); - if (shared_page == NULL) - return NULL; - shared_page->upage = upage; shared_page->frame = frame; hash_insert (&shared_file->pages, &shared_page->elem); diff --git a/src/vm/page.h b/src/vm/page.h index 312e481..74344c1 100644 --- a/src/vm/page.h +++ b/src/vm/page.h @@ -2,9 +2,11 @@ #define VM_PAGE_H #include "threads/thread.h" +#include "threads/synch.h" #include "filesys/off_t.h" struct hash shared_files; +struct lock shared_files_lock; enum page_type { PAGE_EXECUTABLE,