Update frame table to add a pinned flag and protect those from being evicted

This commit is contained in:
sBubshait
2024-12-05 17:52:01 +00:00
parent 5cf79b5389
commit e03273756d
2 changed files with 51 additions and 7 deletions

View File

@@ -37,6 +37,8 @@ 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. */
bool pinned;
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. */
@@ -50,6 +52,7 @@ hash_less_func frame_metadata_less;
static struct list_elem *lru_next (struct list_elem *e);
static struct list_elem *lru_prev (struct list_elem *e);
static struct frame_metadata *frame_metadata_get (void *frame);
static struct frame_metadata *get_victim (void);
/* Initialize the frame system by initializing the frame (hash) table with
@@ -143,11 +146,34 @@ frame_alloc (enum palloc_flags flags, void *upage, struct thread *owner)
frame_metadata->upage = upage;
frame_metadata->owner = owner;
frame_metadata->pinned = false;
lock_release (&lru_lock);
return frame_metadata->frame;
}
void
frame_pin (void *frame)
{
struct frame_metadata *frame_metadata = frame_metadata_get (frame);
if (frame_metadata == NULL)
PANIC ("Attempted to pin a frame at an unallocated kernel address '%p'\n",
frame);
frame_metadata->pinned = true;
}
void
frame_unpin (void *frame)
{
struct frame_metadata *frame_metadata = frame_metadata_get (frame);
if (frame_metadata == NULL)
PANIC ("Attempted to unpin a frame at an unallocated kernel address '%p'\n",
frame);
frame_metadata->pinned = false;
}
/* Attempt to deallocate a frame for a user process by removing it from the
frame table as well as lru_list, and freeing the underlying page
memory & metadata struct. Panics if the frame isn't active in memory. */
@@ -201,6 +227,10 @@ get_victim (void)
upage = frame_metadata->upage;
e = lru_next (e);
/* Skip pinned frames */
if (frame_metadata->pinned)
continue;
if (!pagedir_is_accessed (pd, upage))
break;
@@ -237,6 +267,18 @@ frame_metadata_less (const struct hash_elem *a_, const struct hash_elem *b_,
return a->frame < b->frame;
}
static struct frame_metadata *
frame_metadata_get (void *frame)
{
struct frame_metadata key_metadata;
key_metadata.frame = frame;
struct hash_elem *e = hash_find (&frame_table, &key_metadata.hash_elem);
if (e == NULL) return NULL;
return hash_entry (e, struct frame_metadata, hash_elem);
}
/* Returns the next recently used element after the one provided, which
is achieved by iterating through lru_list like a circular queue
(wrapping around the list at the tail). */

View File

@@ -6,6 +6,8 @@
void frame_init (void);
void *frame_alloc (enum palloc_flags, void *, struct thread *);
void frame_pin (void *frame);
void frame_unpin (void *frame);
void frame_free (void *frame);
#endif /* vm/frame.h */