void lock_donate_priority(struct lock *l, int priority) { l->donated_priority = priority; struct thread *holder = l->holder; if (holder != NULL && holder->lock_waiting != NULL && holder->lock_waiting->donated_priority < priority) { lock_donate_priority(holder->lock_waiting, priority); } }
/* Donate the priority to the lock holder when necessary */ void lock_donate_priority (struct thread *doner, struct lock *lock) { if (lock->holder == NULL) return; struct thread *donee = lock->holder; if (doner->priority > donee->priority) { donee->priority = doner->priority; /* Pass down the priority */ if (donee->wait_lock) { doner = donee; lock_donate_priority(doner, doner->wait_lock); } } }
/*! Acquires LOCK, sleeping until it becomes available if necessary. The lock must not already be held by the current thread. This function may sleep, so it must not be called within an interrupt handler. This function may be called with interrupts disabled, but interrupts will be turned back on if we need to sleep. */ void lock_acquire(struct lock *lock) { ASSERT(lock != NULL); ASSERT(!intr_context()); ASSERT(!lock_held_by_current_thread(lock)); struct thread *cur = thread_current(); if (compute_priority(cur) > lock->donated_priority) { lock_donate_priority(lock, compute_priority(cur)); } cur->lock_waiting = lock; sema_down(&lock->semaphore); cur->lock_waiting = NULL; lock->holder = cur; /* TODO: recompute lock donation priority */ list_push_back(&cur->lock_list, &lock->elem); }
/* Acquires LOCK, sleeping until it becomes available if necessary. The lock must not already be held by the current thread. This function may sleep, so it must not be called within an interrupt handler. This function may be called with interrupts disabled, but interrupts will be turned back on if we need to sleep. */ void lock_acquire (struct lock *lock) { ASSERT (lock != NULL); ASSERT (!intr_context ()); ASSERT (!lock_held_by_current_thread (lock)); if (!sema_try_down (&lock->semaphore)) { sema_down (&lock->sema_lock); thread_current ()->wait_lock = lock; lock_donate_priority(thread_current(), lock); sema_up (&lock->sema_lock); sema_down (&lock->semaphore); } lock->holder = thread_current (); list_push_back (&(lock->holder->hold_locks), &lock->hold_elem); sema_down (&lock->sema_lock); lock->holder->wait_lock = NULL; sema_up (&lock->sema_lock); }