Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#124] Change supplemental page table from list to hash #127

Merged
merged 1 commit into from
May 11, 2017
Merged
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
71 changes: 40 additions & 31 deletions src/vm/page.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "vm/page.h"
#include <list.h>
#include <hash.h>
#include <string.h>
#include "threads/malloc.h"
#include "threads/thread.h"
Expand All @@ -8,7 +8,9 @@
#include "vm/frame.h"
#include "vm/swap.h"

static void suppl_pt_free_pte (struct suppl_pte *);
static hash_hash_func suppl_pt_hash;
static hash_less_func suppl_pt_less;
static hash_action_func suppl_pt_free_pte;

/* Creates and returns a new supplemental page table. */
struct suppl_pt *
Expand All @@ -18,7 +20,7 @@ suppl_pt_create (void)
if (pt == NULL)
return NULL;

list_init (&pt->list);
hash_init (&pt->hash, suppl_pt_hash, suppl_pt_less, NULL);

return pt;
}
Expand All @@ -30,14 +32,7 @@ suppl_pt_create (void)
void
suppl_pt_destroy (struct suppl_pt *pt)
{
struct list_elem *e;
for (e = list_begin (&pt->list); e != list_end (&pt->list);)
{
struct suppl_pte *pte = list_entry (e, struct suppl_pte, elem);
e = list_next (e);
suppl_pt_free_pte (pte);
}
free (pt);
hash_destroy (&pt->hash, suppl_pt_free_pte);
}

/* Adds a new supplemental page table entry of zero-fill with
Expand All @@ -57,7 +52,7 @@ suppl_pt_set_zero (void *upage)
pte->dirty = false;

struct suppl_pt *pt = thread_current ()->suppl_pt;
list_push_back (&pt->list, &pte->elem);
hash_insert (&pt->hash, &pte->elem);

return true;
}
Expand Down Expand Up @@ -85,7 +80,7 @@ suppl_pt_set_file (void *upage, struct file *file, off_t ofs,
pte->writable = writable;

struct suppl_pt *pt = thread_current ()->suppl_pt;
list_push_back (&pt->list, &pte->elem);
hash_insert (&pt->hash, &pte->elem);

return true;
}
Expand Down Expand Up @@ -166,7 +161,9 @@ suppl_pt_clear_page (void *upage)
{
struct suppl_pte *pte = suppl_pt_get_page (upage);
pagedir_clear_page (pte->pagedir, upage);
suppl_pt_free_pte (pte);
if (pte == NULL)
return;
suppl_pt_free_pte (&pte->elem, thread_current ()->suppl_pt);
}

/* Returns the supplemental page table entry associated with
Expand All @@ -176,15 +173,12 @@ struct suppl_pte *
suppl_pt_get_page (void *upage)
{
struct suppl_pt *pt = thread_current ()->suppl_pt;
struct list_elem *e;
for (e = list_begin (&pt->list); e != list_end (&pt->list);
e = list_next (e))
{
struct suppl_pte *pte = list_entry (e, struct suppl_pte, elem);
if (pte->upage == upage)
return pte;
}
return NULL;
struct suppl_pte pte;
struct hash_elem *e;

pte.upage = upage;
e = hash_find (&pt->hash, &pte.elem);
return e != NULL ? hash_entry (e, struct suppl_pte, elem) : NULL;
}

/* Updates dirty bit at the given supplemental page table entry
Expand All @@ -195,27 +189,42 @@ suppl_pt_update_dirty (struct suppl_pte *pte)
ASSERT (pte != NULL);

if (pte->kpage == NULL)
return;
return pte->dirty;

pte->dirty = pte->dirty || pagedir_is_dirty (pte->pagedir, pte->upage)
|| pagedir_is_dirty (pte->pagedir, pte->kpage);

return pte->dirty;
}

static unsigned
suppl_pt_hash (const struct hash_elem *e, void *aux UNUSED)
{
struct suppl_pte *pte = hash_entry (e, struct suppl_pte, elem);
return hash_bytes (&pte->upage, sizeof pte->upage);
}

static bool
suppl_pt_less (const struct hash_elem *e1, const struct hash_elem *e2,
void *aux UNUSED)
{
struct suppl_pte *pte1 = hash_entry (e1, struct suppl_pte, elem);
struct suppl_pte *pte2 = hash_entry (e2, struct suppl_pte, elem);
return pte1->upage < pte2->upage;
}

/* Frees a supplemental page table entry.
This also removes the frame table entry, but not frees
allocated page. */
This also removes the frame table entry if supplemental page
PT is given, but not frees allocated page. */
static void
suppl_pt_free_pte (struct suppl_pte *pte)
suppl_pt_free_pte (struct hash_elem *e, void *pt)
{
if (pte == NULL)
return;

struct suppl_pte *pte = hash_entry (e, struct suppl_pte, elem);
if (pte->kpage != NULL)
frame_remove (pte->kpage);
else if (pte->type == PAGE_SWAP)
swap_remove (pte->swap_index);
list_remove (&pte->elem);
if (pt != NULL)
hash_delete (&((struct suppl_pt *) pt)->hash, &pte->elem);
free (pte);
}
6 changes: 3 additions & 3 deletions src/vm/page.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef VM_PAGE_H
#define VM_PAGE_H

#include <list.h>
#include <hash.h>
#include "filesys/file.h"
#include "vm/swap.h"

Expand All @@ -16,7 +16,7 @@ enum page_type
/* Supplemental page table. */
struct suppl_pt
{
struct list list; /* List. */
struct hash hash; /* Hash table. */
};

/* Supplemental page table entry. */
Expand Down Expand Up @@ -44,7 +44,7 @@ struct suppl_pte
};
};

struct list_elem elem; /* List element. */
struct hash_elem elem; /* Hash element. */
};

struct suppl_pt *suppl_pt_create (void);
Expand Down
1 change: 1 addition & 0 deletions src/vm/swap.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
void swap_table_init (void);
bool swap_in (void *kpage, size_t idx);
size_t swap_out (void *kpage);
void swap_remove (size_t idx);

#endif /* vm/swap.h */