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