/* 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 = thread_current (); /* If we are not in the multi-level feedback queue scheduler then use priority donation */ if(!thread_mlfqs) { /* donate priority if someone holds the lock we want */ enum intr_level old_level = intr_disable (); if (lock->holder != NULL) { cur_thread->lock_waiting_for = lock; cur_thread->t_donating_to = lock->holder; thread_donate_priority(cur_thread); } intr_set_level (old_level); } sema_down (&lock->semaphore); lock->holder = cur_thread; }
/* Down or "P" operation on a semaphore. Waits for SEMA's value to become positive and then atomically decrements it. This function may sleep, so it must not be called within an interrupt handler. This function may be called with interrupts disabled, but if it sleeps then the next scheduled thread will probably turn interrupts back on. */ void sema_down (struct semaphore *sema) { enum intr_level old_level; ASSERT (sema != NULL); ASSERT (!intr_context ()); old_level = intr_disable (); struct thread *currentThread = thread_current(); while (sema->value == 0) { if(!thread_mlfqs) { thread_donate_priority(); } //list_insert_priority_ordered (&sema->waiters, ¤tThread->elem, currentThread->priority); list_insert_ordered (&sema->waiters, ¤tThread->elem, (list_less_func *) &thread_cmp_priority, NULL); thread_block (); } sema->value--; intr_set_level (old_level); }
/* 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)); ASSERT (thread_current ()->waiting_on == NULL); enum intr_level old_level; old_level = intr_disable (); /* If the lock is currently held by someone, then we need to invoke thread_donate_priority to donate our priority to that special someone. */ if (!thread_mlfqs && lock->holder != NULL) { thread_current ()->waiting_on = lock; thread_donate_priority (thread_current ()); } sema_down (&lock->semaphore); lock->holder = thread_current (); thread_current ()->waiting_on = NULL; intr_set_level (old_level); }
/* 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)); enum intr_level old_level = intr_disable (); if (!thread_mlfqs && lock->holder != NULL && lock->holder->priority < thread_current ()->priority) thread_donate_priority (lock->holder, lock); sema_down (&lock->semaphore); lock->holder = thread_current (); intr_set_level (old_level); }
/* 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)); /* Added for priority donation. */ if (lock->holder != NULL) { if (lock->highest_waiter == NULL) { lock->highest_waiter = thread_current (); lock->highest_waiter->waiting_for = lock->holder; } else if (lock->highest_waiter->priority < thread_current ()->priority) { list_remove (&lock->highest_waiter->waiting_elem); lock->highest_waiter->waiting_for = thread_current (); lock->highest_waiter = thread_current (); lock->highest_waiter->waiting_for = lock->holder; } if (lock->highest_waiter == thread_current ()) { list_insert_ordered (&lock->holder->waiting_threads, &lock->highest_waiter->waiting_elem, waiting_value_great, NULL); if (lock->holder->priority < &lock->highest_waiter->priority) { if (lock->holder->priority_orig < 0) lock->holder->priority_orig = lock->holder->priority; thread_donate_priority (lock->holder, lock->highest_waiter->priority); } } } sema_down (&lock->semaphore); lock->holder = thread_current (); /* Added for priority donation. */ lock->highest_waiter = !list_empty (&lock->semaphore.waiters) ? list_entry (list_begin (&lock->semaphore.waiters), struct thread, elem) : NULL; }