Merge remote-tracking branch 'origin/vm/page-swap-synch' into vm/virtual-memory/saleh
# Conflicts: # .gitlab-ci.yml # src/Makefile.build # src/threads/thread.c # src/userprog/exception.c # src/userprog/process.c # src/vm/frame.c # src/vm/page.c # src/vm/page.h # src/vm/stackgrowth.c # src/vm/stackgrowth.h
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# -*- makefile -*-
|
||||
|
||||
kernel.bin: DEFINES = -DUSERPROG -DFILESYS -DVM
|
||||
KERNEL_SUBDIRS = threads devices lib lib/kernel userprog filesys vm
|
||||
kernel.bin: DEFINES = -DUSERPROG -DFILESYS
|
||||
KERNEL_SUBDIRS = threads devices lib lib/kernel userprog filesys
|
||||
TEST_SUBDIRS = tests/userprog tests/userprog/no-vm tests/filesys/base
|
||||
GRADING_FILE = $(SRCDIR)/tests/userprog/Grading
|
||||
SIMULATOR = --qemu
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "userprog/exception.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include "stdbool.h"
|
||||
#include "userprog/gdt.h"
|
||||
#include "userprog/pagedir.h"
|
||||
#include "userprog/process.h"
|
||||
@@ -8,11 +9,13 @@
|
||||
#include "threads/palloc.h"
|
||||
#include "threads/thread.h"
|
||||
#include "threads/vaddr.h"
|
||||
#include "vm/frame.h"
|
||||
#include "vm/page.h"
|
||||
#include "devices/swap.h"
|
||||
#include "userprog/pagedir.h"
|
||||
|
||||
#define MAX_STACK_SIZE (8 * 1024 * 1024) // 8MB
|
||||
#define MAX_STACK_OFFSET 32 // 32 bytes offset below stack pointer (ESP)
|
||||
|
||||
/* Number of page faults processed. */
|
||||
static long long page_fault_cnt;
|
||||
|
||||
@@ -164,9 +167,24 @@ page_fault (struct intr_frame *f)
|
||||
be just that the stack needs to grow or that it needs to be lazily loaded.
|
||||
So we attempt to grow the stack. If this does not work, we check our SPT to
|
||||
see if the page is expected to have data loaded in memory. */
|
||||
struct thread *t = thread_current ();
|
||||
void *upage = pg_round_down (fault_addr);
|
||||
if (not_present && is_user_vaddr (upage) && upage != NULL)
|
||||
{
|
||||
/* Check if the non-present user page is in the swap partition.
|
||||
If so, swap it back into main memory, updating the PTE for
|
||||
the faulted virtual address to point to the newly allocated
|
||||
frame. */
|
||||
if (page_in_swap (t, fault_addr))
|
||||
{
|
||||
size_t swap_slot = page_get_swap (t, fault_addr);
|
||||
void *kpage = frame_alloc (0, upage, t);
|
||||
swap_in (kpage, swap_slot);
|
||||
|
||||
bool writeable = pagedir_is_writable (t->pagedir, upage);
|
||||
if (pagedir_set_page (t->pagedir, upage, kpage, writeable)) return;
|
||||
}
|
||||
|
||||
if (is_valid_stack_access (fault_addr, esp))
|
||||
if (grow_stack (upage))
|
||||
return;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "threads/palloc.h"
|
||||
|
||||
static uint32_t *active_pd (void);
|
||||
static void invalidate_pagedir (uint32_t *);
|
||||
|
||||
/* Creates a new page directory that has mappings for kernel
|
||||
virtual addresses, but none for user virtual addresses.
|
||||
@@ -53,7 +52,7 @@ pagedir_destroy (uint32_t *pd)
|
||||
on CREATE. If CREATE is true, then a new page table is
|
||||
created and a pointer into it is returned. Otherwise, a null
|
||||
pointer is returned. */
|
||||
static uint32_t *
|
||||
uint32_t *
|
||||
lookup_page (uint32_t *pd, const void *vaddr, bool create)
|
||||
{
|
||||
uint32_t *pt, *pde;
|
||||
@@ -278,7 +277,7 @@ active_pd (void)
|
||||
This function invalidates the TLB if PD is the active page
|
||||
directory. (If PD is not active then its entries are not in
|
||||
the TLB, so there is no need to invalidate anything.) */
|
||||
static void
|
||||
void
|
||||
invalidate_pagedir (uint32_t *pd)
|
||||
{
|
||||
if (active_pd () == pd)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
uint32_t *pagedir_create (void);
|
||||
void pagedir_destroy (uint32_t *pd);
|
||||
uint32_t *lookup_page (uint32_t *pd, const void *vaddr, bool create);
|
||||
bool pagedir_set_page (uint32_t *pd, void *upage, void *kpage, bool rw);
|
||||
void *pagedir_get_page (uint32_t *pd, const void *upage);
|
||||
void pagedir_clear_page (uint32_t *pd, void *upage);
|
||||
@@ -16,5 +17,6 @@ void pagedir_set_accessed (uint32_t *pd, const void *upage, bool accessed);
|
||||
bool pagedir_is_writable (uint32_t *pd, const void *upage);
|
||||
void pagedir_set_writable (uint32_t *pd, const void *upage, bool writable);
|
||||
void pagedir_activate (uint32_t *pd);
|
||||
void invalidate_pagedir (uint32_t *pd);
|
||||
|
||||
#endif /* userprog/pagedir.h */
|
||||
|
||||
@@ -369,6 +369,8 @@ process_exit (void)
|
||||
|
||||
/* Clean up all open files */
|
||||
hash_destroy (&cur->open_files, fd_cleanup);
|
||||
|
||||
/* Clean up the thread's supplemental page table. */
|
||||
hash_destroy (&cur->pages, page_cleanup);
|
||||
|
||||
/* Close the executable file, implicitly allowing it to be written to. */
|
||||
@@ -627,6 +629,9 @@ load (const char *file_name, void (**eip) (void), void **esp)
|
||||
|
||||
done:
|
||||
/* We arrive here whether the load is successful or not. */
|
||||
#ifndef VM
|
||||
file_close (file);
|
||||
#endif
|
||||
lock_release (&filesys_lock);
|
||||
return success;
|
||||
}
|
||||
@@ -758,6 +763,7 @@ get_usr_kpage (enum palloc_flags flags, void *upage)
|
||||
return NULL;
|
||||
else
|
||||
page = frame_alloc (flags, upage, t);
|
||||
pagedir_set_accessed (t->pagedir, upage, true);
|
||||
#else
|
||||
page = palloc_get_page (flags | PAL_USER);
|
||||
#endif
|
||||
|
||||
@@ -616,4 +616,4 @@ put_user (uint8_t *udst, uint8_t byte)
|
||||
: "=&a"(error_code), "=m"(*udst)
|
||||
: "q"(byte));
|
||||
return error_code != -1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user