Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions pintos/include/vm/anon.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ struct page;
enum vm_type;

struct anon_page {
size_t swap_idx;
size_t swap_idx;
};

void vm_anon_init (void);
bool anon_initializer (struct page *page, enum vm_type type, void *kva);
void vm_anon_init(void);
bool anon_initializer(struct page* page, enum vm_type type, void* kva);

#endif
20 changes: 10 additions & 10 deletions pintos/include/vm/file.h
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
#ifndef VM_FILE_H
#define VM_FILE_H
#include <list.h>

#include "filesys/file.h"

struct page;
enum vm_type;
struct mmap_file;

struct file_page {
struct file *file;
struct file* file;
off_t ofs;
size_t read_bytes;
size_t zero_bytes;
struct mmap_file *mmap;
struct mmap_file* mmap;
};

struct mmap_file {
void *start;
void* start;
size_t page_cnt;
struct file *file;
struct file* file;
off_t offset;
struct list_elem elem;
};


void vm_file_init (void);
bool file_backed_initializer (struct page *page, enum vm_type type, void *kva);
bool lazy_load_file (struct page *page, void *aux);
void *do_mmap(void *addr, size_t length, int writable, struct file *file, off_t offset);
void do_munmap (void *va);
void vm_file_init(void);
bool file_backed_initializer(struct page* page, enum vm_type type, void* kva);
bool lazy_load_file(struct page* page, void* aux);
void* do_mmap(void* addr, size_t length, int writable, struct file* file, off_t offset);
void do_munmap(void* va);
#endif
134 changes: 67 additions & 67 deletions pintos/include/vm/vm.h
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
#ifndef VM_VM_H
#define VM_VM_H
#include <stdbool.h>
#include "threads/palloc.h"
#include "lib/kernel/hash.h"

#include "filesys/off_t.h"
#include "lib/kernel/hash.h"
#include "threads/palloc.h"

enum vm_type {
/* page not initialized */
VM_UNINIT = 0,
/* page not related to the file, aka anonymous page */
VM_ANON = 1,
/* page that realated to the file */
VM_FILE = 2,
/* page that hold the page cache, for project 4 */
VM_PAGE_CACHE = 3,

/* Bit flags to store state */

/* Auxillary bit flag marker for store information. You can add more
* markers, until the value is fit in the int. */
VM_MARKER_0 = (1 << 3),
VM_MARKER_1 = (1 << 4),

/* DO NOT EXCEED THIS VALUE. */
VM_MARKER_END = (1 << 31),
/* page not initialized */
VM_UNINIT = 0,
/* page not related to the file, aka anonymous page */
VM_ANON = 1,
/* page that realated to the file */
VM_FILE = 2,
/* page that hold the page cache, for project 4 */
VM_PAGE_CACHE = 3,

/* Bit flags to store state */

/* Auxillary bit flag marker for store information. You can add more
* markers, until the value is fit in the int. */
VM_MARKER_0 = (1 << 3),
VM_MARKER_1 = (1 << 4),

/* DO NOT EXCEED THIS VALUE. */
VM_MARKER_END = (1 << 31),
};

#include "vm/uninit.h"
#include "vm/anon.h"
#include "vm/file.h"
#include "vm/uninit.h"
#ifdef EFILESYS
#include "filesys/page_cache.h"
#endif
Expand All @@ -44,75 +45,74 @@ struct file;
* uninit_page, file_page, anon_page, and page cache (project4).
* DO NOT REMOVE/MODIFY PREDEFINED MEMBER OF THIS STRUCTURE. */
struct page {
const struct page_operations *operations;
void *va; /* Address in terms of user space */
struct frame *frame; /* Back reference for frame */

/* Your implementation */
struct hash_elem hash_elem;
bool writable;
/* Per-type data are binded into the union.
* Each function automatically detects the current union */
union {
struct uninit_page uninit;
struct anon_page anon;
struct file_page file;
const struct page_operations* operations;
void* va; /* Address in terms of user space */
struct frame* frame; /* Back reference for frame */

/* Your implementation */
struct hash_elem hash_elem;
bool writable;

/* Per-type data are binded into the union.
* Each function automatically detects the current union */
union {
struct uninit_page uninit;
struct anon_page anon;
struct file_page file;
#ifdef EFILESYS
struct page_cache page_cache;
struct page_cache page_cache;
#endif
};
};
};

/* The representation of "frame" */
struct frame {
void *kva;
struct page *page;
void* kva;
struct page* page;
struct list_elem frame_table_elem;
};

/* The function table for page operations.
* This is one way of implementing "interface" in C.
* Put the table of "method" into the struct's member, and
* call it whenever you needed. */
struct page_operations {
bool (*swap_in) (struct page *, void *);
bool (*swap_out) (struct page *);
void (*destroy) (struct page *);
enum vm_type type;
bool (*swap_in)(struct page*, void*);
bool (*swap_out)(struct page*);
void (*destroy)(struct page*);
enum vm_type type;
};

#define swap_in(page, v) (page)->operations->swap_in ((page), v)
#define swap_out(page) (page)->operations->swap_out (page)
#define swap_in(page, v) (page)->operations->swap_in((page), v)
#define swap_out(page) (page)->operations->swap_out(page)
#define destroy(page) \
if ((page)->operations->destroy) (page)->operations->destroy (page)
if ((page)->operations->destroy) (page)->operations->destroy(page)

/* Representation of current process's memory space.
* We don't want to force you to obey any specific design for this struct.
* All designs up to you for this. */
struct supplemental_page_table {
struct hash hash_table;
struct hash hash_table;
};

#include "threads/thread.h"
void supplemental_page_table_init (struct supplemental_page_table *spt);
bool supplemental_page_table_copy (struct supplemental_page_table *dst,
struct supplemental_page_table *src);
void supplemental_page_table_kill (struct supplemental_page_table *spt);
struct page *spt_find_page (struct supplemental_page_table *spt,
void *va);
bool spt_insert_page (struct supplemental_page_table *spt, struct page *page);
bool spt_remove_page (struct supplemental_page_table *spt, struct page *page);

void vm_init (void);
bool vm_try_handle_fault (struct intr_frame *f, void *addr, bool user,
bool write, bool not_present);
void supplemental_page_table_init(struct supplemental_page_table* spt);
bool supplemental_page_table_copy(struct supplemental_page_table* dst,
struct supplemental_page_table* src);
void supplemental_page_table_kill(struct supplemental_page_table* spt);
struct page* spt_find_page(struct supplemental_page_table* spt, void* va);
bool spt_insert_page(struct supplemental_page_table* spt, struct page* page);
bool spt_remove_page(struct supplemental_page_table* spt, struct page* page);

void vm_init(void);
bool vm_try_handle_fault(struct intr_frame* f, void* addr, bool user, bool write, bool not_present);

#define vm_alloc_page(type, upage, writable) \
vm_alloc_page_with_initializer ((type), (upage), (writable), NULL, NULL)
bool vm_alloc_page_with_initializer (enum vm_type type, void *upage,
bool writable, vm_initializer *init, void *aux);
void vm_dealloc_page (struct page *page);
bool vm_claim_page (void *va);
enum vm_type page_get_type (struct page *page);

#endif /* VM_VM_H */
vm_alloc_page_with_initializer((type), (upage), (writable), NULL, NULL)
bool vm_alloc_page_with_initializer(enum vm_type type, void* upage, bool writable,
vm_initializer* init, void* aux);
void vm_dealloc_page(struct page* page);
bool vm_claim_page(void* va);
enum vm_type page_get_type(struct page* page);

#endif /* VM_VM_H */
114 changes: 78 additions & 36 deletions pintos/vm/anon.c
Original file line number Diff line number Diff line change
@@ -1,63 +1,105 @@
/* anon.c: Implementation of page for non-disk image (a.k.a. anonymous page). */

#include "vm/vm.h"
#include "devices/disk.h"
#include "vm/vm.h"
#define SECTORS_PER_PAGE 8

#include "lib/kernel/bitmap.h"
#include "threads/malloc.h"
#include "threads/mmu.h"

/* DO NOT MODIFY BELOW LINE */
static struct disk *swap_disk;
static bool anon_swap_in (struct page *page, void *kva);
static bool anon_swap_out (struct page *page);
static void anon_destroy (struct page *page);
static struct disk* swap_disk;
static bool anon_swap_in(struct page* page, void* kva);
static bool anon_swap_out(struct page* page);
static void anon_destroy(struct page* page);

static struct disk* swap_disk;
static struct bitmap* swap_bitmap;

/* DO NOT MODIFY this struct */
static const struct page_operations anon_ops = {
.swap_in = anon_swap_in,
.swap_out = anon_swap_out,
.destroy = anon_destroy,
.type = VM_ANON,
.swap_in = anon_swap_in,
.swap_out = anon_swap_out,
.destroy = anon_destroy,
.type = VM_ANON,
};

/* Initialize the data for anonymous pages */
void vm_anon_init (void) {
swap_disk = disk_get (1, 1);
void vm_anon_init(void) {
swap_disk = disk_get(1, 1);
size_t swap_size = disk_size(swap_disk) / SECTORS_PER_PAGE;
swap_bitmap = bitmap_create(swap_size);
}

/* Initialize the file mapping */
bool anon_initializer (struct page *page, enum vm_type type, void *kva) {
struct anon_page *anon_page;
page->operations = &anon_ops;
// anon_page = &page->anon;
// anon_page->swap_idx = BITMAP_ERROR;
return true;
bool anon_initializer(struct page* page, enum vm_type type, void* kva) {
struct anon_page* anon_page = &page->anon;
page->operations = &anon_ops;
anon_page->swap_idx = BITMAP_ERROR;
return true;
}

/* Swap in the page by read contents from the swap disk. */
static bool
anon_swap_in (struct page *page, void *kva) {
ASSERT (page != NULL);
ASSERT (page->frame != NULL);
return true;
static bool anon_swap_in(struct page* page, void* kva) {
ASSERT(page != NULL);
ASSERT(page->frame != NULL);

struct anon_page* anon_page = &page->anon;

size_t swap_slot_idx = anon_page->swap_idx;

if (swap_bitmap == NULL || !bitmap_test(swap_bitmap, swap_slot_idx))
return false;

for (int i = 0; i < SECTORS_PER_PAGE; i++) {
disk_sector_t sec_no = (swap_slot_idx * SECTORS_PER_PAGE) + i;
void* buffer = kva + (DISK_SECTOR_SIZE * i);
disk_read(swap_disk, sec_no, buffer);
}

bitmap_set(swap_bitmap, swap_slot_idx, false);

anon_page->swap_idx = BITMAP_ERROR;

return true;
}

/* Swap out the page by writing contents to the swap disk. */
static bool
anon_swap_out (struct page *page) {
ASSERT (page != NULL);
return true;
static bool anon_swap_out(struct page* page) {
struct anon_page* anon_page = &page->anon;

size_t swap_slot_idx = bitmap_scan_and_flip(swap_bitmap, 0, 1, false);

if (swap_slot_idx == BITMAP_ERROR)
return false;

for (int i = 0; i < SECTORS_PER_PAGE; i++) {
disk_sector_t sec_no = (swap_slot_idx * SECTORS_PER_PAGE) + i;

void* buffer = page->frame->kva + (DISK_SECTOR_SIZE * i);

disk_write(swap_disk, sec_no, buffer);
}

anon_page->swap_idx = swap_slot_idx;

return true;
}

/* Destroy the anonymous page. PAGE will be freed by the caller. */
static void anon_destroy (struct page *page) {
struct anon_page *anon_page = &page->anon;
static void anon_destroy(struct page* page) {
struct anon_page* anon_page = &page->anon;

ASSERT (page != NULL);
ASSERT(page != NULL);

if (page->frame != NULL) {
struct thread *t = thread_current ();
if (page->frame != NULL) {
struct thread* t = thread_current();

pml4_clear_page (t->pml4, page->va);
palloc_free_page (page->frame->kva);
free (page->frame);
page->frame = NULL;
}
pml4_clear_page(t->pml4, page->va);
palloc_free_page(page->frame->kva);
list_remove(&page->frame->frame_table_elem);
free(page->frame);
page->frame = NULL;
}
}
Loading