Add data structures for shared executable files along with helper methods for them, w/ G
This commit is contained in:
@@ -149,14 +149,6 @@ page_fault (struct intr_frame *f)
|
||||
write = (f->error_code & PF_W) != 0;
|
||||
user = (f->error_code & PF_U) != 0;
|
||||
|
||||
if (!user)
|
||||
{
|
||||
f->eip = (void *)f->eax;
|
||||
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. */
|
||||
|
||||
115
src/vm/page.c
115
src/vm/page.c
@@ -7,6 +7,10 @@
|
||||
#include "userprog/process.h"
|
||||
#include "vm/frame.h"
|
||||
|
||||
static struct hash shared_files;
|
||||
|
||||
static struct shared_file_entry *shared_file_get (struct file *file);
|
||||
|
||||
/* Hashing function needed for the SPT table. Returns a hash for an entry,
|
||||
based on its upage. */
|
||||
unsigned
|
||||
@@ -108,6 +112,117 @@ page_cleanup (struct hash_elem *e, void *aux UNUSED)
|
||||
free (hash_entry (e, struct page_entry, elem));
|
||||
}
|
||||
|
||||
/* Hashing function needed for the shared_file table. Returns a hash for an
|
||||
entry based on its file pointer. */
|
||||
unsigned
|
||||
shared_file_hash (const struct hash_elem *e, void *aux UNUSED)
|
||||
{
|
||||
return file_hash (hash_entry (e, struct shared_file_entry, elem)->file);
|
||||
}
|
||||
|
||||
/* Less function needed for the shared_file table. */
|
||||
bool
|
||||
shared_file_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
||||
void *aux UNUSED)
|
||||
{
|
||||
const struct shared_file_entry *a = hash_entry (a_, struct shared_file_entry,
|
||||
elem);
|
||||
const struct shared_file_entry *b = hash_entry (b_, struct shared_file_entry,
|
||||
elem);
|
||||
|
||||
return file_compare (a->file, b->file);
|
||||
}
|
||||
|
||||
/* Hashing function needed for the shared pages table. Returns a hash for an
|
||||
entry based on its user virtual address (upage) pointer. */
|
||||
unsigned
|
||||
shared_page_hash (const struct hash_elem *e, void *aux UNUSED)
|
||||
{
|
||||
return hash_ptr (hash_entry (e, struct shared_page_entry, elem)->upage);
|
||||
}
|
||||
|
||||
/* Less function needed for the shared pages table. */
|
||||
bool
|
||||
shared_page_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
||||
void *aux UNUSED)
|
||||
{
|
||||
const struct shared_page_entry *a = hash_entry (a_, struct shared_page_entry,
|
||||
elem);
|
||||
const struct shared_page_entry *b = hash_entry (b_, struct shared_page_entry,
|
||||
elem);
|
||||
|
||||
return a->upage < b->upage;
|
||||
}
|
||||
|
||||
static struct shared_file_entry *
|
||||
shared_file_get (struct file *file)
|
||||
{
|
||||
struct shared_file_entry fake_shared_file;
|
||||
fake_shared_file.file = file;
|
||||
|
||||
struct hash_elem *e = hash_find (&shared_files, &fake_shared_file.elem);
|
||||
|
||||
if (e == NULL)
|
||||
return NULL;
|
||||
|
||||
return hash_entry (e, struct shared_file_entry, elem);
|
||||
}
|
||||
|
||||
/* Gets a shared_page_entry from the shared_pages table using the file and upage
|
||||
of the page. Returns NULL if no such page_entry exists in the hash map.*/
|
||||
struct shared_page_entry *
|
||||
shared_page_get (struct file *file, void *upage)
|
||||
{
|
||||
/* Search first for the file within the shared_pages structure */
|
||||
struct shared_file_entry *shared_file = shared_file_get (file);
|
||||
if (shared_file == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Search for the page within the shared_file's hash table */
|
||||
struct shared_page_entry fake_shared_page_entry;
|
||||
fake_shared_page_entry.upage = upage;
|
||||
|
||||
struct hash_elem *e = hash_find (&shared_file->pages, &fake_shared_page_entry.elem);
|
||||
|
||||
if (e == NULL)
|
||||
return NULL;
|
||||
|
||||
return hash_entry (e, struct shared_page_entry, elem);
|
||||
}
|
||||
|
||||
struct shared_page_entry *
|
||||
shared_page_insert (struct file *file, void *upage, void *frame)
|
||||
{
|
||||
struct shared_file_entry *shared_file = shared_file_get (file);
|
||||
/* 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;
|
||||
|
||||
shared_file->file = file;
|
||||
shared_file->ref_count = 0;
|
||||
if (!hash_init (&shared_file->pages, shared_page_hash, shared_page_less, NULL))
|
||||
{
|
||||
free (shared_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
return shared_page;
|
||||
}
|
||||
|
||||
/* Updates the 'owner' thread's page table entry for virtual address 'upage'
|
||||
to have a present bit of 0 and stores the specified swap slot value in the
|
||||
entry for later retrieval from disk. */
|
||||
|
||||
@@ -23,6 +23,21 @@ struct page_entry {
|
||||
struct hash_elem elem; /* An elem for the hash table. */
|
||||
};
|
||||
|
||||
struct shared_file_entry {
|
||||
struct file *file; /* Pointer to the file. */
|
||||
struct hash pages;
|
||||
int ref_count;
|
||||
|
||||
struct hash_elem elem;
|
||||
};
|
||||
|
||||
struct shared_page_entry {
|
||||
void *upage;
|
||||
void *frame;
|
||||
|
||||
struct hash_elem elem;
|
||||
};
|
||||
|
||||
unsigned page_hash (const struct hash_elem *e, void *aux);
|
||||
bool page_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
||||
void *aux);
|
||||
|
||||
Reference in New Issue
Block a user