From ecbb4e74a552640f4f29afeee715e2f882fbd067 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 4 Dec 2024 19:07:28 +0000 Subject: [PATCH] Implement the unmap system call, writing back to the file if a page is dirty before removing from SPT --- src/userprog/syscall.c | 33 ++++++++++++++++++++++++++++++++- src/vm/mmap.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/vm/mmap.h | 1 + 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/userprog/syscall.c b/src/userprog/syscall.c index 16e345f..2a32cd3 100644 --- a/src/userprog/syscall.c +++ b/src/userprog/syscall.c @@ -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, diff --git a/src/vm/mmap.c b/src/vm/mmap.c index 864cfcd..b3b16db 100644 --- a/src/vm/mmap.c +++ b/src/vm/mmap.c @@ -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 diff --git a/src/vm/mmap.h b/src/vm/mmap.h index 5f7143b..593e070 100644 --- a/src/vm/mmap.h +++ b/src/vm/mmap.h @@ -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 */