++ old_level = intr_disable ();
++ while (thread_recompute_priority (t) && t->donee != NULL)
++ t = t->donee;
++ thread_yield_to_higher_priority ();
++ intr_set_level (old_level);
++}
++
++/* Returns the current thread's priority. */
++int
++thread_get_priority (void)
++{
++ return thread_current ()->priority;
++}
++
++/* Returns true if thread A has lower priority than thread B,
++ within a list of donors. */
++static bool
++donated_lower_priority (const struct list_elem *a_,
++ const struct list_elem *b_,
++ void *aux UNUSED)
++{
++ const struct thread *a = list_entry (a_, struct thread, donor_elem);
++ const struct thread *b = list_entry (b_, struct thread, donor_elem);
++
++ return a->priority < b->priority;
++}
++
++/* Recomputes T's priority in terms of its normal priority and
++ its donors' priorities, if any.
++ Returns true if T's new priority is higher than its old
++ priority, false otherwise. */
++bool
++thread_recompute_priority (struct thread *t)
++{
++ int old = t->priority;
++ int donation = 0;
++ if (!list_empty (&t->donors))
++ donation = list_entry (list_max (&t->donors, donated_lower_priority, NULL),
++ struct thread, donor_elem)->priority;
++ t->priority = donation > t->normal_priority ? donation : t->normal_priority;
++ return t->priority > old;
++}
++
++/* If the ready list contains a thread with a higher priority,
++ yields to it. */
++void
++thread_yield_to_higher_priority (void)
++{
++ enum intr_level old_level = intr_disable ();
++ if (!list_empty (&ready_list))