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;
|
write = (f->error_code & PF_W) != 0;
|
||||||
user = (f->error_code & PF_U) != 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
|
/* 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
|
just need to be lazily loaded. So, we check our SPT to see if the page
|
||||||
is expected to have data loaded in memory. */
|
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 "userprog/process.h"
|
||||||
#include "vm/frame.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,
|
/* Hashing function needed for the SPT table. Returns a hash for an entry,
|
||||||
based on its upage. */
|
based on its upage. */
|
||||||
unsigned
|
unsigned
|
||||||
@@ -108,6 +112,117 @@ page_cleanup (struct hash_elem *e, void *aux UNUSED)
|
|||||||
free (hash_entry (e, struct page_entry, elem));
|
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'
|
/* 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
|
to have a present bit of 0 and stores the specified swap slot value in the
|
||||||
entry for later retrieval from disk. */
|
entry for later retrieval from disk. */
|
||||||
|
|||||||
@@ -23,6 +23,21 @@ struct page_entry {
|
|||||||
struct hash_elem elem; /* An elem for the hash table. */
|
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);
|
unsigned page_hash (const struct hash_elem *e, void *aux);
|
||||||
bool page_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
bool page_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
||||||
void *aux);
|
void *aux);
|
||||||
|
|||||||
Reference in New Issue
Block a user