From 21cbfc9fe0dfa22f20380f2258b0031cbfc2065a Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Tue, 22 Oct 2024 20:06:21 +0100 Subject: [PATCH] Implement transfer of orphaned donors when releasing lock w/ S --- src/threads/synch.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/threads/synch.c b/src/threads/synch.c index b74303d..4ec2266 100644 --- a/src/threads/synch.c +++ b/src/threads/synch.c @@ -270,15 +270,53 @@ lock_release (struct lock *lock) ASSERT (lock_held_by_current_thread (lock)); struct thread *current_thread = thread_current (); + struct thread *max_donor = NULL; + + struct list orphan_list; + list_init (&orphan_list); + + /* Loop through current thread's donors, removing the ones waiting for the + lock being released and keeping track of them (within orphan_list). + Also identifies the highest priority donor thread among them. */ struct list_elem *tail = list_tail (¤t_thread->donors_list); - for (struct list_elem *e = list_begin (¤t_thread->donors_list); - e != tail; e = e->next) + struct list_elem *e = list_begin (¤t_thread->donors_list); + while (e != tail) { struct thread *donor = list_entry (e, struct thread, donor_elem); + struct list_elem *next = list_next (e); + + /* Excludes donors that aren't waiting for the lock being released, + and tracks the rest. */ if (donor->waiting_lock == lock) + { list_remove (e); + list_push_back (&orphan_list, e); + + /* Identify highest priority donor. */ + if (max_donor == NULL || donor->priority > max_donor->priority) + max_donor = donor; + } + + e = next; } + /* If there exists a maximum donor thread waiting for this lock to be + released, transfer the remaining orphaned donors to its donor list. */ + if (max_donor != NULL) + { + tail = list_tail (&orphan_list); + e = list_begin (&orphan_list); + while (e != tail) + { + struct list_elem *next = list_next (e); + list_push_back (&max_donor->donors_list, e); + + e = next; + } + } + + /* Removal of donors to this thread may change its effective priority, + so recalculate. */ thread_recalculate_priority (); lock->holder = NULL;