Files
pintos_22/src/vm/mmap.c

147 lines
4.0 KiB
C

#include "mmap.h"
#include "page.h"
#include "threads/vaddr.h"
#include "threads/malloc.h"
#include "userprog/syscall.h"
#include "userprog/pagedir.h"
#include <stdio.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_,
void *aux);
static void mmap_cleanup(struct hash_elem *e, void *aux);
/* Initializes the mmap table for the given thread, setting the mmap counter to
0 and initializing the hash table. */
bool
mmap_init (struct thread *t)
{
t->mmap_counter = 0;
return hash_init (&t->mmap_files, mmap_hash, mmap_less, NULL);
}
struct mmap_entry *
mmap_get (mapid_t mapping)
{
struct mmap_entry fake_mmap_entry;
fake_mmap_entry.mapping = mapping;
struct hash_elem *e
= hash_find (&thread_current ()->mmap_files, &fake_mmap_entry.elem);
if (e == NULL)
return NULL;
return hash_entry (e, struct mmap_entry, elem);
}
/* Inserts a new mmap entry into the mmap table for the current thread. Upage
is the start address of the file data in the user VM. */
struct mmap_entry *
mmap_insert (struct file *file, void *upage)
{
if (file == NULL || upage == NULL)
return NULL;
struct mmap_entry *mmap = malloc (sizeof (struct mmap_entry));
if (mmap == NULL)
return NULL;
mmap->mapping = thread_current ()->mmap_counter++;
mmap->file = file;
mmap->upage = upage;
hash_insert (&thread_current ()->mmap_files, &mmap->elem);
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);
}
file_close (mmap->file);
free (mmap);
}
/* Destroys the mmap table for the current thread. Frees all the memory
allocated for the mmap entries. */
void
mmap_destroy (void)
{
hash_destroy (&thread_current ()->mmap_files, mmap_cleanup);
}
/* A hash function for the mmap table. Returns a hash for an entry, based on its
mapping. */
static unsigned
mmap_hash (const struct hash_elem *e, void *aux UNUSED)
{
return hash_entry (e, struct mmap_entry, elem)->mapping;
}
/* A comparator function for the mmap table. Compares two entries based on their
mappings. */
static bool
mmap_less (const struct hash_elem *a_, const struct hash_elem *b_,
void *aux UNUSED)
{
const struct mmap_entry *a = hash_entry (a_, struct mmap_entry, elem);
const struct mmap_entry *b = hash_entry (b_, struct mmap_entry, elem);
return a->mapping < b->mapping;
}
/* Cleans up the mmap table for the current thread. Implicitly unmaps the mmap
entry, freeing pages and writing back to the file if necessary. */
static void
mmap_cleanup (struct hash_elem *e, void *aux UNUSED)
{
struct mmap_entry *mmap = hash_entry (e, struct mmap_entry, elem);
mmap_unmap (mmap);
}
/* 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. */
void
page_set_swap (struct thread *owner, void *upage, size_t swap_slot)
{
}
/* Given that the page with user address 'upage' owned by 'owner' is flagged
to be in the swap disk via the owner's page table, returns its stored
swap slot. Otherwise panics the kernel. */
size_t
page_get_swap (struct thread *owner, void *upage)
{
return 0;
}