feat: proper cleanup for shared pages
This commit is contained in:
@@ -172,8 +172,9 @@ start_process (void *proc_start_data)
|
|||||||
to store the command that executed the process. */
|
to store the command that executed the process. */
|
||||||
if (data->success)
|
if (data->success)
|
||||||
{
|
{
|
||||||
data->success =
|
data->success = use_shared_file (exec_file)
|
||||||
process_init_stack (data->cmd_saveptr, &if_.esp, data->file_name);
|
&& process_init_stack (data->cmd_saveptr, &if_.esp,
|
||||||
|
data->file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Signal that the process has finished attempting to load. */
|
/* Signal that the process has finished attempting to load. */
|
||||||
@@ -366,6 +367,7 @@ process_exit (void)
|
|||||||
/* Clean up all open files */
|
/* Clean up all open files */
|
||||||
hash_destroy (&cur->open_files, fd_cleanup);
|
hash_destroy (&cur->open_files, fd_cleanup);
|
||||||
hash_destroy (&cur->pages, page_cleanup);
|
hash_destroy (&cur->pages, page_cleanup);
|
||||||
|
unuse_shared_file (cur->exec_file);
|
||||||
|
|
||||||
/* Close the executable file, implicitly allowing it to be written to. */
|
/* Close the executable file, implicitly allowing it to be written to. */
|
||||||
if (cur->exec_file != NULL)
|
if (cur->exec_file != NULL)
|
||||||
|
|||||||
@@ -12,14 +12,19 @@
|
|||||||
static unsigned page_hash (const struct hash_elem *e, void *aux UNUSED);
|
static unsigned page_hash (const struct hash_elem *e, void *aux UNUSED);
|
||||||
static bool page_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
static bool page_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
||||||
void *aux UNUSED);
|
void *aux UNUSED);
|
||||||
|
static struct shared_file_entry *shared_file_insert (struct file *file);
|
||||||
static struct shared_page_entry *shared_page_insert (struct file *file,
|
static struct shared_page_entry *shared_page_insert (struct file *file,
|
||||||
void *upage, void *frame);
|
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 struct shared_page_entry *shared_page_get (struct file *file,
|
static struct shared_page_entry *shared_page_get (struct file *file,
|
||||||
void *upage);
|
void *upage);
|
||||||
|
static unsigned shared_file_hash (const struct hash_elem *e, void *aux UNUSED);
|
||||||
|
static bool shared_file_less (const struct hash_elem *a_,
|
||||||
|
const struct hash_elem *b_, void *aux UNUSED);
|
||||||
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_,
|
||||||
const struct hash_elem *b_, void *aux UNUSED);
|
const struct hash_elem *b_, void *aux UNUSED);
|
||||||
|
static void shared_page_cleanup (struct hash_elem *e, void *aux UNUSED);
|
||||||
|
|
||||||
/* Initialise a thread's supplemental pages table. */
|
/* Initialise a thread's supplemental pages table. */
|
||||||
bool
|
bool
|
||||||
@@ -180,7 +185,7 @@ page_cleanup (struct hash_elem *e, void *aux UNUSED)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise the shared files and table and lock. */
|
/* Initialise the shared files and table and lock. */
|
||||||
bool
|
void
|
||||||
shared_files_init ()
|
shared_files_init ()
|
||||||
{
|
{
|
||||||
lock_init (&shared_files_lock);
|
lock_init (&shared_files_lock);
|
||||||
@@ -188,16 +193,64 @@ shared_files_init ()
|
|||||||
PANIC ("Failed to initialise shared_files table.");
|
PANIC ("Failed to initialise shared_files table.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
use_shared_file (struct file *file)
|
||||||
|
{
|
||||||
|
lock_acquire (&shared_files_lock);
|
||||||
|
struct shared_file_entry *shared_file = shared_file_get (file);
|
||||||
|
if (shared_file == NULL)
|
||||||
|
{
|
||||||
|
shared_file = shared_file_insert (file);
|
||||||
|
if (shared_file == NULL)
|
||||||
|
{
|
||||||
|
lock_release (&shared_files_lock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shared_file->ref_count++;
|
||||||
|
lock_release (&shared_files_lock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
unuse_shared_file (struct file *file)
|
||||||
|
{
|
||||||
|
lock_acquire (&shared_files_lock);
|
||||||
|
struct shared_file_entry *shared_file = shared_file_get (file);
|
||||||
|
if (shared_file == NULL)
|
||||||
|
{
|
||||||
|
lock_release (&shared_files_lock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
shared_file->ref_count--;
|
||||||
|
if (shared_file->ref_count <= 0)
|
||||||
|
{
|
||||||
|
hash_destroy (&shared_file->pages, shared_page_cleanup);
|
||||||
|
hash_delete (&shared_files, &shared_file->elem);
|
||||||
|
free (shared_file);
|
||||||
|
}
|
||||||
|
lock_release (&shared_files_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shared_page_cleanup (struct hash_elem *e, void *aux UNUSED)
|
||||||
|
{
|
||||||
|
struct shared_page_entry *shared_page
|
||||||
|
= hash_entry (e, struct shared_page_entry, elem);
|
||||||
|
// frame_free (shared_page->frame);
|
||||||
|
free (shared_page);
|
||||||
|
}
|
||||||
|
|
||||||
/* Hashing function needed for the shared_file table. Returns a hash for an
|
/* Hashing function needed for the shared_file table. Returns a hash for an
|
||||||
entry based on its file pointer. */
|
entry based on its file pointer. */
|
||||||
unsigned
|
static unsigned
|
||||||
shared_file_hash (const struct hash_elem *e, void *aux UNUSED)
|
shared_file_hash (const struct hash_elem *e, void *aux UNUSED)
|
||||||
{
|
{
|
||||||
return file_hash (hash_entry (e, struct shared_file_entry, elem)->file);
|
return file_hash (hash_entry (e, struct shared_file_entry, elem)->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Less function needed for the shared_file table. */
|
/* Less function needed for the shared_file table. */
|
||||||
bool
|
static bool
|
||||||
shared_file_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
shared_file_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
||||||
void *aux UNUSED)
|
void *aux UNUSED)
|
||||||
{
|
{
|
||||||
@@ -246,7 +299,7 @@ shared_file_get (struct file *file)
|
|||||||
|
|
||||||
/* Gets a shared_page_entry from the shared_pages table using the file and upage
|
/* 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.*/
|
of the page. Returns NULL if no such page_entry exists in the hash map.*/
|
||||||
struct shared_page_entry *
|
static struct shared_page_entry *
|
||||||
shared_page_get (struct file *file, void *upage)
|
shared_page_get (struct file *file, void *upage)
|
||||||
{
|
{
|
||||||
/* Search first for the file within the shared_pages structure */
|
/* Search first for the file within the shared_pages structure */
|
||||||
@@ -266,6 +319,27 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct shared_file_entry *
|
||||||
|
shared_file_insert (struct file *file)
|
||||||
|
{
|
||||||
|
struct shared_file_entry *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);
|
||||||
|
return shared_file;
|
||||||
|
}
|
||||||
|
|
||||||
static 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)
|
||||||
{
|
{
|
||||||
@@ -280,23 +354,12 @@ shared_page_insert (struct file *file, void *upage, void *frame)
|
|||||||
/* 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 = shared_file_insert (file);
|
||||||
if (shared_file == NULL)
|
if (shared_file == NULL)
|
||||||
{
|
{
|
||||||
free (shared_page);
|
free (shared_page);
|
||||||
return 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_page);
|
|
||||||
free (shared_file);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash_insert (&shared_files, &shared_file->elem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_page->upage = upage;
|
shared_page->upage = upage;
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ bool page_load (struct page_entry *page);
|
|||||||
void page_cleanup (struct hash_elem *e, void *aux UNUSED);
|
void page_cleanup (struct hash_elem *e, void *aux UNUSED);
|
||||||
|
|
||||||
void shared_files_init ();
|
void shared_files_init ();
|
||||||
|
bool use_shared_file (struct file *file);
|
||||||
|
bool unuse_shared_file (struct file *file);
|
||||||
|
|
||||||
void page_set_swap (struct thread *, void *, size_t);
|
void page_set_swap (struct thread *, void *, size_t);
|
||||||
size_t page_get_swap (struct thread *, void *);
|
size_t page_get_swap (struct thread *, void *);
|
||||||
|
|||||||
Reference in New Issue
Block a user