Merge branch 'vm/memory-mapped-files' into vm/virtual-memory/saleh

This commit is contained in:
sBubshait
2024-12-05 01:24:50 +00:00
11 changed files with 275 additions and 24 deletions

View File

@@ -259,7 +259,7 @@ try_fetch_page (void *upage, bool write)
/* Load the page into memory based on the type of data it is expecting. */
bool success = false;
switch (page->type) {
case PAGE_EXECUTABLE:
case PAGE_FILE:
success = page_load (page, page->writable);
break;
default:

View File

@@ -25,6 +25,7 @@
#include "threads/synch.h"
#include "devices/timer.h"
#include "vm/page.h"
#include "vm/mmap.h"
#ifdef VM
#include "vm/frame.h"
#endif
@@ -363,6 +364,9 @@ process_exit (void)
struct thread *cur = thread_current ();
uint32_t *pd;
/* Unmap all memory mapped files */
mmap_destroy ();
/* Clean up all open files */
hash_destroy (&cur->open_files, fd_cleanup);
hash_destroy (&cur->pages, page_cleanup);
@@ -706,7 +710,7 @@ load_segment (struct file *file, off_t ofs, uint8_t *upage,
/* Add the page metadata to the SPT to be lazy loaded later on */
if (page_insert (file, ofs, upage, page_read_bytes, page_zero_bytes,
writable, PAGE_EXECUTABLE) == NULL)
writable, PAGE_FILE) == NULL)
return false;
/* Advance. */

View File

@@ -10,12 +10,15 @@
#include "threads/synch.h"
#include "userprog/process.h"
#include "userprog/pagedir.h"
#include "vm/page.h"
#include "vm/mmap.h"
#include <stdio.h>
#include <stdbool.h>
#include <syscall-nr.h>
#define MAX_SYSCALL_ARGS 3
#define EXIT_FAILURE -1
#define MMAP_FAILURE -1
struct open_file
{
@@ -45,6 +48,8 @@ static int syscall_write (int fd, const void *buffer, unsigned size);
static void syscall_seek (int fd, unsigned position);
static unsigned syscall_tell (int fd);
static void syscall_close (int fd);
static mapid_t syscall_mmap (int fd, void *addr);
static void syscall_munmap (mapid_t mapping);
static struct open_file *fd_get_file (int fd);
static void validate_user_pointer (const void *ptr, size_t size,
@@ -77,6 +82,8 @@ static const struct syscall_arguments syscall_lookup[] =
[SYS_SEEK] = {(syscall_function) syscall_seek, 2},
[SYS_TELL] = {(syscall_function) syscall_tell, 1},
[SYS_CLOSE] = {(syscall_function) syscall_close, 1},
[SYS_MMAP] = {(syscall_function) syscall_mmap, 2},
[SYS_MUNMAP] = {(syscall_function) syscall_munmap, 1}
};
/* The number of syscall functions (i.e, number of elements) within the
@@ -391,6 +398,79 @@ syscall_close (int fd)
}
}
/* Handles the syscall for memory mapping a file. */
static mapid_t
syscall_mmap (int fd, void *addr)
{
/* Ensure the FD is for a file in the filesystem (not STDIN or STDOUT). */
if (fd == STDOUT_FILENO || fd == STDIN_FILENO)
return MMAP_FAILURE;
/* Validate that there is a file associated with the given FD. */
struct open_file *file_info = fd_get_file (fd);
if (file_info == NULL)
return MMAP_FAILURE;
/* Ensure that the address is page-aligned and it's neither NULL nor zero. */
if (addr == 0 || addr == NULL || pg_ofs (addr) != 0)
return MMAP_FAILURE;
/* Reopen the file to obtain a separate and independent reference to the file
for the mapping. */
struct file *file = file_reopen (file_info->file);
if (file == NULL)
return MMAP_FAILURE;
/* Get the size of the file. Mmap fails if the file is empty. */
off_t file_size = file_length (file);
if (file_size == 0)
return MMAP_FAILURE;
/* Check and ensure that there is enough space in the user virtual memory to
hold the entire file. */
for (off_t ofs = 0; ofs < file_size; ofs += PGSIZE)
{
if (page_get (addr + ofs) != NULL)
return MMAP_FAILURE;
}
/* Map the file data into the user virtual memory starting from addr. */
for (off_t ofs = 0; ofs < file_size; ofs += PGSIZE)
{
off_t read_bytes = file_size - ofs < PGSIZE ? file_size - ofs : PGSIZE;
off_t zero_bytes = PGSIZE - read_bytes;
if (page_insert (file, ofs, addr + ofs, read_bytes, zero_bytes, true,
PAGE_FILE) == NULL)
return MMAP_FAILURE;
}
/* Create a new mapping for the file. */
struct mmap_entry *mmap = mmap_insert (file, addr);
if (mmap == NULL)
return MMAP_FAILURE;
return mmap->mapping;
}
/* Handles the syscall for unmapping a memory mapped file.
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);
/* Delete the mmap entry from the hash table. */
hash_delete (&thread_current ()->mmap_files, &mmap->elem);
/* Unmap the mmap entry: free the pages and write back to the file if
necessary. NOTE. freeing and cleaning up is also handled by mmap_unmap. */
mmap_unmap (mmap);
}
/* Hashing function needed for the open_file table. Returns a hash for an entry,
based on its FD. */
unsigned