fix: acquire lru_lock before pinning frames to avoid race condition with eviction
This commit is contained in:
@@ -28,9 +28,6 @@ struct list lru_list;
|
|||||||
victim. Otherwise, the next element in the queue is similarly considered. */
|
victim. Otherwise, the next element in the queue is similarly considered. */
|
||||||
struct list_elem *next_victim = NULL;
|
struct list_elem *next_victim = NULL;
|
||||||
|
|
||||||
/* Synchronisation variables. */
|
|
||||||
/* Protects access to 'lru_list'. */
|
|
||||||
struct lock lru_lock;
|
|
||||||
|
|
||||||
struct frame_metadata
|
struct frame_metadata
|
||||||
{
|
{
|
||||||
@@ -175,23 +172,29 @@ frame_alloc (enum palloc_flags flags, void *upage, struct thread *owner)
|
|||||||
void
|
void
|
||||||
frame_pin (void *frame)
|
frame_pin (void *frame)
|
||||||
{
|
{
|
||||||
|
ASSERT (frame != NULL);
|
||||||
|
lock_acquire (&lru_lock);
|
||||||
struct frame_metadata *frame_metadata = frame_metadata_get (frame);
|
struct frame_metadata *frame_metadata = frame_metadata_get (frame);
|
||||||
if (frame_metadata == NULL)
|
if (frame_metadata == NULL)
|
||||||
PANIC ("Attempted to pin a frame at an unallocated kernel address '%p'\n",
|
PANIC ("Attempted to pin a frame at an unallocated kernel address '%p'\n",
|
||||||
frame);
|
frame);
|
||||||
|
|
||||||
frame_metadata->pinned = true;
|
frame_metadata->pinned = true;
|
||||||
|
lock_release (&lru_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
frame_unpin (void *frame)
|
frame_unpin (void *frame)
|
||||||
{
|
{
|
||||||
|
ASSERT (frame != NULL);
|
||||||
|
lock_acquire (&lru_lock);
|
||||||
struct frame_metadata *frame_metadata = frame_metadata_get (frame);
|
struct frame_metadata *frame_metadata = frame_metadata_get (frame);
|
||||||
if (frame_metadata == NULL)
|
if (frame_metadata == NULL)
|
||||||
PANIC ("Attempted to unpin a frame at an unallocated kernel address '%p'\n",
|
PANIC ("Attempted to unpin a frame at an unallocated kernel address '%p'\n",
|
||||||
frame);
|
frame);
|
||||||
|
|
||||||
frame_metadata->pinned = false;
|
frame_metadata->pinned = false;
|
||||||
|
lock_release (&lru_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt to deallocate a frame for a user process by removing it from the
|
/* Attempt to deallocate a frame for a user process by removing it from the
|
||||||
@@ -372,7 +375,6 @@ frame_metadata_get (void *frame)
|
|||||||
|
|
||||||
struct hash_elem *e = hash_find (&frame_table, &key_metadata.hash_elem);
|
struct hash_elem *e = hash_find (&frame_table, &key_metadata.hash_elem);
|
||||||
if (e == NULL) return NULL;
|
if (e == NULL) return NULL;
|
||||||
|
|
||||||
return hash_entry (e, struct frame_metadata, hash_elem);
|
return hash_entry (e, struct frame_metadata, hash_elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ struct frame_owner
|
|||||||
struct list_elem elem; /* List element for the list of owners. */
|
struct list_elem elem; /* List element for the list of owners. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Synchronisation variables. */
|
||||||
|
/* Protects access to 'lru_list'. */
|
||||||
|
struct lock lru_lock;
|
||||||
void frame_init (void);
|
void frame_init (void);
|
||||||
|
|
||||||
void *frame_alloc (enum palloc_flags, void *, struct thread *);
|
void *frame_alloc (enum palloc_flags, void *, struct thread *);
|
||||||
void frame_pin (void *frame);
|
void frame_pin (void *frame);
|
||||||
void frame_unpin (void *frame);
|
void frame_unpin (void *frame);
|
||||||
|
|||||||
Reference in New Issue
Block a user