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))
|
t))
|
||||||
PANIC ("Failed to initialise child results table for main thread.");
|
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))
|
if (!hash_init (&shared_files, shared_file_hash, shared_file_less, NULL))
|
||||||
PANIC ("Failed to initialise shared pages table.");
|
PANIC ("Failed to initialise shared pages table.");
|
||||||
|
|
||||||
|
lock_init (&shared_files_lock);
|
||||||
|
|
||||||
/* Create the idle thread. */
|
/* Create the idle thread. */
|
||||||
struct semaphore idle_started;
|
struct semaphore idle_started;
|
||||||
sema_init (&idle_started, 0);
|
sema_init (&idle_started, 0);
|
||||||
|
|||||||
@@ -3,9 +3,12 @@
|
|||||||
#include "filesys/file.h"
|
#include "filesys/file.h"
|
||||||
#include "threads/malloc.h"
|
#include "threads/malloc.h"
|
||||||
#include "threads/palloc.h"
|
#include "threads/palloc.h"
|
||||||
|
#include "threads/vaddr.h"
|
||||||
#include "userprog/process.h"
|
#include "userprog/process.h"
|
||||||
#include "vm/frame.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 struct shared_file_entry *shared_file_get (struct file *file);
|
||||||
static unsigned shared_page_hash (const struct hash_elem *e, void *aux UNUSED);
|
static unsigned shared_page_hash (const struct hash_elem *e, void *aux UNUSED);
|
||||||
static bool shared_page_less (const struct hash_elem *a_,
|
static bool shared_page_less (const struct hash_elem *a_,
|
||||||
@@ -73,6 +76,23 @@ page_get (void *upage)
|
|||||||
bool
|
bool
|
||||||
page_load (struct page_entry *page, bool writable)
|
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
|
/* 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
|
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. */
|
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.");
|
PANIC ("Could not allocate a frame to load page into memory.");
|
||||||
|
|
||||||
/* Map the page to the frame. */
|
/* Map the page to the frame. */
|
||||||
if (!install_page (page->upage, frame, writable))
|
if (!install_page (page->upage, frame, page->writable))
|
||||||
{
|
{
|
||||||
frame_free (frame);
|
frame_free (frame);
|
||||||
return false;
|
return false;
|
||||||
@@ -100,6 +120,16 @@ page_load (struct page_entry *page, bool writable)
|
|||||||
/* Zero out the remaining bytes in the frame. */
|
/* Zero out the remaining bytes in the frame. */
|
||||||
memset (frame + page->read_bytes, 0, page->zero_bytes);
|
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. */
|
/* Mark the page as loaded successfully. */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -190,21 +220,32 @@ shared_page_get (struct file *file, void *upage)
|
|||||||
return hash_entry (e, struct shared_page_entry, elem);
|
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)
|
shared_page_insert (struct file *file, void *upage, void *frame)
|
||||||
{
|
{
|
||||||
struct shared_file_entry *shared_file = shared_file_get (file);
|
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 doesn't exist in table, also create it. */
|
||||||
if (shared_file == NULL)
|
if (shared_file == NULL)
|
||||||
{
|
{
|
||||||
shared_file = malloc (sizeof (struct shared_file_entry));
|
shared_file = malloc (sizeof (struct shared_file_entry));
|
||||||
if (shared_file == NULL)
|
if (shared_file == NULL)
|
||||||
|
{
|
||||||
|
free (shared_page);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
shared_file->file = file;
|
shared_file->file = file;
|
||||||
shared_file->ref_count = 0;
|
shared_file->ref_count = 0;
|
||||||
if (!hash_init (&shared_file->pages, shared_page_hash, shared_page_less, NULL))
|
if (!hash_init (&shared_file->pages, shared_page_hash, shared_page_less, NULL))
|
||||||
{
|
{
|
||||||
|
free (shared_page);
|
||||||
free (shared_file);
|
free (shared_file);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -212,11 +253,6 @@ shared_page_insert (struct file *file, void *upage, void *frame)
|
|||||||
hash_insert (&shared_files, &shared_file->elem);
|
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->upage = upage;
|
||||||
shared_page->frame = frame;
|
shared_page->frame = frame;
|
||||||
hash_insert (&shared_file->pages, &shared_page->elem);
|
hash_insert (&shared_file->pages, &shared_page->elem);
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
#define VM_PAGE_H
|
#define VM_PAGE_H
|
||||||
|
|
||||||
#include "threads/thread.h"
|
#include "threads/thread.h"
|
||||||
|
#include "threads/synch.h"
|
||||||
#include "filesys/off_t.h"
|
#include "filesys/off_t.h"
|
||||||
|
|
||||||
struct hash shared_files;
|
struct hash shared_files;
|
||||||
|
struct lock shared_files_lock;
|
||||||
|
|
||||||
enum page_type {
|
enum page_type {
|
||||||
PAGE_EXECUTABLE,
|
PAGE_EXECUTABLE,
|
||||||
|
|||||||
Reference in New Issue
Block a user