Merge branch 'task1/themis/priority-donation' into 'task1/priority-donation'

Merge task1/themis/priority-donation into task1/priority-donation

See merge request lab2425_autumn/pintos_22!13
This commit is contained in:
Demetriades, Themis
2024-10-23 15:03:07 +00:00
3 changed files with 33 additions and 13 deletions

View File

@@ -194,11 +194,12 @@ lock_init (struct lock *lock)
sema_init (&lock->semaphore, 1); sema_init (&lock->semaphore, 1);
} }
/* Allows for the donor to donate its priority to donee, iteratively /* Current thread donates its priority to donee, iteratively
propagating the donation in the case of chains in the wait-for graph. propagating the donation in the case of chains in the wait-for graph.
Also keeps track of the donation by updating the donors list. */ Also keeps track of the donation by updating the donors list. */
static void static void
donate_priority (struct thread *donor, struct thread *donee) { donate_priority (struct thread *donee) {
struct thread *donor = thread_current ();
list_push_back (&donee->donors_list, &donor->donor_elem); list_push_back (&donee->donors_list, &donor->donor_elem);
while (donee != NULL) while (donee != NULL)
@@ -209,17 +210,26 @@ donate_priority (struct thread *donor, struct thread *donee) {
if (donor->priority <= donee->priority) if (donor->priority <= donee->priority)
break; break;
donee->priority = donor->priority;
/* Also stop propagation of donation once a donee is reached with /* Also stop propagation of donation once a donee is reached with
no donees of its own (sink node in WFG). */ no donees of its own (sink node in WFG). */
if (donee->waiting_lock == NULL) if (donee->waiting_lock == NULL)
donee = NULL; {
/* Only the sink node of the WFG isn't waiting for a lock and
could be on the ready list. Thus, as its priority changed,
it must be reinserted into the list. */
enum intr_level old_level = intr_disable ();
donee->priority = donor->priority;
ready_list_reinsert (donee);
intr_set_level (old_level);
donee = NULL;
}
else else
donee = donee->waiting_lock->holder; {
donee->priority = donor->priority;
donee = donee->waiting_lock->holder;
}
} }
ready_list_reorder ();
} }
/* Acquires LOCK, sleeping until it becomes available if /* Acquires LOCK, sleeping until it becomes available if
@@ -244,7 +254,7 @@ lock_acquire (struct lock *lock)
if (lock->holder != NULL) if (lock->holder != NULL)
{ {
t->waiting_lock = lock; t->waiting_lock = lock;
donate_priority (t, lock->holder); donate_priority (lock->holder);
} }
sema_down (&lock->semaphore); sema_down (&lock->semaphore);

View File

@@ -465,10 +465,20 @@ thread_get_recent_cpu (void)
return 0; return 0;
} }
/* Reinsert thread t into the ready list at its correct position
in descending order of priority. Used when this thread's priority
may have changed. Must be called with interrupts disabled. */
void void
ready_list_reorder (void) ready_list_reinsert (struct thread *t)
{ {
list_sort (&ready_list, priority_more, NULL); ASSERT (intr_get_level () == INTR_OFF);
/* If the thread isn't ready to run, do nothing. */
if (t->status != THREAD_READY)
return;
list_remove (&t->elem);
list_insert_ordered (&ready_list, &t->elem, priority_more, NULL);
} }
/* Idle thread. Executes when no other thread is ready to run. /* Idle thread. Executes when no other thread is ready to run.
@@ -558,7 +568,7 @@ init_thread (struct thread *t, const char *name, int priority)
t->stack = (uint8_t *) t + PGSIZE; t->stack = (uint8_t *) t + PGSIZE;
t->base_priority = priority; t->base_priority = priority;
t->magic = THREAD_MAGIC; t->magic = THREAD_MAGIC;
list_init (&t->donors_list); list_init (&t->donors_list);
t->priority = t->base_priority; t->priority = t->base_priority;
t->waiting_lock = NULL; t->waiting_lock = NULL;

View File

@@ -151,6 +151,6 @@ void thread_set_nice (int);
int thread_get_recent_cpu (void); int thread_get_recent_cpu (void);
int thread_get_load_avg (void); int thread_get_load_avg (void);
void ready_list_reorder (void); void ready_list_reinsert (struct thread *t);
#endif /* threads/thread.h */ #endif /* threads/thread.h */