summaryrefslogtreecommitdiffstats
path: root/threads/synch.c
diff options
context:
space:
mode:
Diffstat (limited to 'threads/synch.c')
-rw-r--r--threads/synch.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/threads/synch.c b/threads/synch.c
index 6ffe1de..364b769 100644
--- a/threads/synch.c
+++ b/threads/synch.c
@@ -223,32 +223,45 @@ void
223lock_acquire (struct lock *lock) 223lock_acquire (struct lock *lock)
224{ 224{
225 struct thread *cur = thread_current (); 225 struct thread *cur = thread_current ();
226 struct lock *blocked_lock;
226 227
227 ASSERT (lock != NULL); 228 ASSERT (lock != NULL);
228 ASSERT (!intr_context ()); 229 ASSERT (!intr_context ());
229 ASSERT (!lock_held_by_current_thread (lock)); 230 ASSERT (!lock_held_by_current_thread (lock));
230 231
232 /* nested priority donation: save currently blocked lock */
231 if (lock->holder != NULL) 233 if (lock->holder != NULL)
234 cur->blocked_lock = lock;
235
236 /* nested priority donation: we loop backwards: lock -> holder -> blocked_lock
237 and donate our priority */
238 blocked_lock = lock;
239 while (blocked_lock != NULL && blocked_lock->holder != NULL)
232 { 240 {
233 /* check for a possible priority donation */ 241 /* check for a possible priority donation */
234 if (cur->priority > lock->priority) 242 if (cur->priority > blocked_lock->priority)
235 { 243 {
236 /* the new priority of this lock is our own priority */ 244 /* the new priority of this lock is our own priority */
237 lock->priority = cur->priority; 245 blocked_lock->priority = cur->priority;
238 246
239 /* the lock priority changed so we need to sort the lock list of the lock holder */ 247 /* the lock priority changed so we need to sort the lock list of the lock holder */
240 list_remove (&lock->elem); 248 list_remove (&blocked_lock->elem);
241 list_insert_ordered (&lock->holder->locks, &lock->elem, 249 list_insert_ordered (&blocked_lock->holder->locks, &blocked_lock->elem,
242 lock_priority_cmp_greater, NULL); 250 lock_priority_cmp_greater, NULL);
243 251
244 /* finally donate our priority */ 252 /* finally donate our priority */
245 thread_donate_priority (cur, lock->holder); 253 thread_donate_priority (cur, blocked_lock->holder);
246 } 254 }
255
256 blocked_lock = blocked_lock->holder->blocked_lock;
247 } 257 }
248 258
249 sema_down (&lock->semaphore); 259 sema_down (&lock->semaphore);
250 lock->holder = cur; 260 lock->holder = cur;
251 261
262 /* nested priority donation: we got the lock, reset blocked_lock */
263 cur->blocked_lock = NULL;
264
252 /* the priority of this lock is our own priority */ 265 /* the priority of this lock is our own priority */
253 lock->priority = cur->priority; 266 lock->priority = cur->priority;
254 267
@@ -325,7 +338,7 @@ struct semaphore_elem
325 { 338 {
326 struct list_elem elem; /* List element. */ 339 struct list_elem elem; /* List element. */
327 struct semaphore semaphore; /* This semaphore. */ 340 struct semaphore semaphore; /* This semaphore. */
328 int priority; /* the priority of the waiting thread */ 341 struct thread *thread; /* the current waiting thread */
329 }; 342 };
330 343
331/* Initializes condition variable COND. A condition variable 344/* Initializes condition variable COND. A condition variable
@@ -346,7 +359,7 @@ semaphore_priority_cmp_greater(const struct list_elem *a, const struct list_elem
346{ 359{
347 const struct semaphore_elem *s1 = list_entry (a, struct semaphore_elem, elem); 360 const struct semaphore_elem *s1 = list_entry (a, struct semaphore_elem, elem);
348 const struct semaphore_elem *s2 = list_entry (b, struct semaphore_elem, elem); 361 const struct semaphore_elem *s2 = list_entry (b, struct semaphore_elem, elem);
349 return (s1->priority > s2->priority); 362 return (s1->thread->priority > s2->thread->priority);
350} 363}
351 364
352/* Atomically releases LOCK and waits for COND to be signaled by 365/* Atomically releases LOCK and waits for COND to be signaled by
@@ -380,8 +393,8 @@ cond_wait (struct condition *cond, struct lock *lock)
380 ASSERT (lock_held_by_current_thread (lock)); 393 ASSERT (lock_held_by_current_thread (lock));
381 394
382 sema_init (&waiter.semaphore, 0); 395 sema_init (&waiter.semaphore, 0);
383 /* set condition priority */ 396 /* set thread of waiter */
384 waiter.priority = thread_current ()->priority; 397 waiter.thread = thread_current ();
385 /* and add condition to our ordered waiters list */ 398 /* and add condition to our ordered waiters list */
386 list_insert_ordered (&cond->waiters, &waiter.elem, 399 list_insert_ordered (&cond->waiters, &waiter.elem,
387 &semaphore_priority_cmp_greater, NULL); 400 &semaphore_priority_cmp_greater, NULL);