feat: allow frames to have multiple owner threads.
This commit is contained in:
@@ -32,11 +32,18 @@ struct list_elem *next_victim = NULL;
|
||||
/* Protects access to 'lru_list'. */
|
||||
struct lock lru_lock;
|
||||
|
||||
struct frame_owner
|
||||
{
|
||||
struct thread *thread; /* Pointer to the thread referenced by the owner.*/
|
||||
struct list_elem elem; /* List element for the owners list in
|
||||
frame_metadata. */
|
||||
};
|
||||
|
||||
struct frame_metadata
|
||||
{
|
||||
void *frame; /* The kernel virtual address holding the frame. */
|
||||
void *upage; /* The user virtual address pointing to the frame. */
|
||||
struct thread *owner; /* Pointer to the thread that owns the frame. */
|
||||
struct list owners; /* List of owners of the frame. */
|
||||
struct hash_elem hash_elem; /* Tracks the position of the frame metadata
|
||||
within 'frame_table', whose key is the
|
||||
kernel virtual address of the frame. */
|
||||
@@ -96,12 +103,26 @@ frame_alloc (enum palloc_flags flags, void *upage, struct thread *owner)
|
||||
/* Mark page as 'not present' and flag the page directory as having
|
||||
been modified *before* eviction begins to prevent the owner of the
|
||||
victim page from accessing/modifying it mid-eviction. */
|
||||
pagedir_clear_page (victim->owner->pagedir, victim->upage);
|
||||
struct list_elem *e;
|
||||
for (e = list_begin (&victim->owners); e != list_end (&victim->owners);
|
||||
e = list_next (e))
|
||||
{
|
||||
struct frame_owner *frame_owner
|
||||
= list_entry (e, struct frame_owner, elem);
|
||||
pagedir_clear_page (frame_owner->thread->pagedir, victim->upage);
|
||||
}
|
||||
|
||||
// TODO: Lock PTE of victim page for victim process.
|
||||
|
||||
size_t swap_slot = swap_out (victim->frame);
|
||||
page_set_swap (victim->owner, victim->upage, swap_slot);
|
||||
for (e = list_begin (&victim->owners); e != list_end (&victim->owners);
|
||||
e = list_next (e))
|
||||
{
|
||||
struct frame_owner *frame_owner
|
||||
= list_entry (e, struct frame_owner, elem);
|
||||
page_set_swap (frame_owner->thread->pagedir, victim->upage,
|
||||
swap_slot);
|
||||
}
|
||||
|
||||
/* If zero flag is set, zero out the victim page. */
|
||||
if (flags & PAL_ZERO)
|
||||
@@ -142,7 +163,10 @@ frame_alloc (enum palloc_flags flags, void *upage, struct thread *owner)
|
||||
}
|
||||
|
||||
frame_metadata->upage = upage;
|
||||
frame_metadata->owner = owner;
|
||||
list_init (&frame_metadata->owners);
|
||||
struct frame_owner *frame_owner = malloc (sizeof (struct frame_owner));
|
||||
frame_owner->thread = owner;
|
||||
list_push_back (&frame_metadata->owners, &frame_owner->elem);
|
||||
lock_release (&lru_lock);
|
||||
|
||||
return frame_metadata->frame;
|
||||
@@ -190,24 +214,33 @@ frame_free (void *frame)
|
||||
static struct frame_metadata *
|
||||
get_victim (void)
|
||||
{
|
||||
struct list_elem *e = next_victim;
|
||||
struct list_elem *ve = next_victim;
|
||||
struct frame_metadata *frame_metadata;
|
||||
uint32_t *pd;
|
||||
void *upage;
|
||||
for (;;)
|
||||
bool found = false;
|
||||
while (!found)
|
||||
{
|
||||
frame_metadata = list_entry (e, struct frame_metadata, list_elem);
|
||||
pd = frame_metadata->owner->pagedir;
|
||||
upage = frame_metadata->upage;
|
||||
e = lru_next (e);
|
||||
|
||||
if (!pagedir_is_accessed (pd, upage))
|
||||
break;
|
||||
frame_metadata = list_entry (ve, struct frame_metadata, list_elem);
|
||||
void *upage = frame_metadata->upage;
|
||||
ve = lru_next (ve);
|
||||
|
||||
/* Check whether any owner thread has accessed the page. */
|
||||
found = true;
|
||||
struct list_elem *oe;
|
||||
for (oe = list_begin (&frame_metadata->owners);
|
||||
oe != list_end (&frame_metadata->owners); oe = list_next (oe))
|
||||
{
|
||||
struct frame_owner *frame_owner
|
||||
= list_entry (oe, struct frame_owner, elem);
|
||||
uint32_t *pd = frame_owner->thread->pagedir;
|
||||
if (pagedir_is_accessed (pd, upage))
|
||||
{
|
||||
found = false;
|
||||
pagedir_set_accessed (pd, upage, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
next_victim = e;
|
||||
next_victim = ve;
|
||||
return frame_metadata;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user