Update page_load to create and use the shared read-only pages of executables, w/ G
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user