Implement the unmap system call, writing back to the file if a page is dirty before removing from SPT
This commit is contained in:
@@ -459,11 +459,42 @@ syscall_mmap (int fd, void *addr)
|
||||
|
||||
/* Handles the syscall for unmapping a memory mapped file.
|
||||
|
||||
Pre: mapping is a valid mapping identifier returned by mmap syscall.*/
|
||||
Pre: mapping is a valid mapping identifier returned by mmap syscall. */
|
||||
static void
|
||||
syscall_munmap (mapid_t mapping)
|
||||
{
|
||||
/* Get the mmap entry from the mapping identifier. */
|
||||
struct mmap_entry *mmap = mmap_get (mapping);
|
||||
|
||||
/* Free all the pages associated with the mapping, writing back to the file
|
||||
if necessary. */
|
||||
off_t length = file_length (mmap->file);
|
||||
for (off_t ofs = 0; ofs < length; ofs += PGSIZE)
|
||||
{
|
||||
void *upage = mmap->upage + ofs;
|
||||
|
||||
/* Get the SPT page entry for this page. */
|
||||
struct page_entry *page = page_get(upage);
|
||||
if (page == NULL)
|
||||
continue;
|
||||
|
||||
/* Write the page back to the file if it is dirty. */
|
||||
if (pagedir_is_dirty (thread_current ()->pagedir, upage))
|
||||
{
|
||||
lock_acquire (&filesys_lock);
|
||||
file_write_at (mmap->file, upage, page->read_bytes, ofs);
|
||||
lock_release (&filesys_lock);
|
||||
}
|
||||
|
||||
/* Remove the page from the supplemental page table. */
|
||||
hash_delete (&thread_current ()->pages, &page->elem);
|
||||
}
|
||||
|
||||
/* Remove the mapping from the mmap table. Close the file and free the mmap
|
||||
entry. */
|
||||
hash_delete (&thread_current ()->mmap_files, &mmap->elem);
|
||||
file_close (mmap->file);
|
||||
free(mmap);
|
||||
}
|
||||
|
||||
/* Hashing function needed for the open_file table. Returns a hash for an entry,
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#include "mmap.h"
|
||||
#include "page.h"
|
||||
#include "threads/vaddr.h"
|
||||
#include "threads/malloc.h"
|
||||
#include "userprog/syscall.h"
|
||||
#include "userprog/pagedir.h"
|
||||
|
||||
static unsigned mmap_hash (const struct hash_elem *e, void *aux);
|
||||
static bool mmap_less (const struct hash_elem *a_, const struct hash_elem *b_,
|
||||
@@ -50,6 +54,44 @@ mmap_insert (struct file *file, void *upage)
|
||||
return mmap;
|
||||
}
|
||||
|
||||
/* Unmaps the given mmap entry from the current thread's mmap table. */
|
||||
void
|
||||
mmap_unmap (struct mmap_entry *mmap)
|
||||
{
|
||||
if (mmap == NULL)
|
||||
return;
|
||||
|
||||
/* Free all the pages associated with the mapping, writing back to the file
|
||||
if necessary. */
|
||||
off_t length = file_length (mmap->file);
|
||||
for (off_t ofs = 0; ofs < length; ofs += PGSIZE)
|
||||
{
|
||||
void *upage = mmap->upage + ofs;
|
||||
|
||||
/* Get the SPT page entry for this page. */
|
||||
struct page_entry *page = page_get(upage);
|
||||
if (page == NULL)
|
||||
continue;
|
||||
|
||||
/* Write the page back to the file if it is dirty. */
|
||||
if (pagedir_is_dirty (thread_current ()->pagedir, upage))
|
||||
{
|
||||
lock_acquire (&filesys_lock);
|
||||
file_write_at (mmap->file, upage, page->read_bytes, ofs);
|
||||
lock_release (&filesys_lock);
|
||||
}
|
||||
|
||||
/* Remove the page from the supplemental page table. */
|
||||
hash_delete (&thread_current ()->pages, &page->elem);
|
||||
}
|
||||
|
||||
/* Remove the mapping from the mmap table. Close the file and free the mmap
|
||||
entry. */
|
||||
hash_delete (&thread_current ()->mmap_files, &mmap->elem);
|
||||
file_close (mmap->file);
|
||||
free(mmap);
|
||||
}
|
||||
|
||||
/* Destroys the mmap table for the current thread. Frees all the memory
|
||||
allocated for the mmap entries. */
|
||||
void
|
||||
|
||||
@@ -20,6 +20,7 @@ struct mmap_entry {
|
||||
bool mmap_init (struct thread *t);
|
||||
struct mmap_entry *mmap_get (mapid_t mapping);
|
||||
struct mmap_entry *mmap_insert (struct file *file, void *upage);
|
||||
void mmap_unmap (struct mmap_entry *mmap);
|
||||
void mmap_destroy (void);
|
||||
|
||||
#endif /* vm/mmap.h */
|
||||
|
||||
Reference in New Issue
Block a user