Implement VM #63
@@ -11,6 +11,7 @@
|
|||||||
#include "threads/synch.h"
|
#include "threads/synch.h"
|
||||||
#include "userprog/process.h"
|
#include "userprog/process.h"
|
||||||
#include "userprog/pagedir.h"
|
#include "userprog/pagedir.h"
|
||||||
|
#include "vm/page.h"
|
||||||
#include "vm/mmap.h"
|
#include "vm/mmap.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <syscall-nr.h>
|
#include <syscall-nr.h>
|
||||||
@@ -404,7 +405,56 @@ syscall_close (int fd)
|
|||||||
static mapid_t
|
static mapid_t
|
||||||
syscall_mmap (int fd, void *addr)
|
syscall_mmap (int fd, void *addr)
|
||||||
{
|
{
|
||||||
return MMAP_FAILURE;
|
/* 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_EXECUTABLE) == 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. */
|
/* Handles the syscall for unmapping a memory mapped file. */
|
||||||
|
|||||||
Reference in New Issue
Block a user