diff options
| author | manuel <manuel@mausz.at> | 2012-05-11 03:02:38 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-05-11 03:02:38 +0200 |
| commit | 04bb67f0e37a9144c4656d21f9f876f256de13e5 (patch) | |
| tree | 9a81ebbfb4653258c5fa97cfe527dd7628f348b2 /threads | |
| parent | 2ea82ff0203b1cc22b55900752d44514506eb01e (diff) | |
| download | progos-04bb67f0e37a9144c4656d21f9f876f256de13e5.tar.gz progos-04bb67f0e37a9144c4656d21f9f876f256de13e5.tar.bz2 progos-04bb67f0e37a9144c4656d21f9f876f256de13e5.zip | |
major: added support for nested priority donation
minor: replaced priority with a pointer to the waiting thread in condition handling
status: 0/18 failed!
Diffstat (limited to 'threads')
| -rw-r--r-- | threads/synch.c | 31 | ||||
| -rw-r--r-- | threads/thread.c | 1 | ||||
| -rw-r--r-- | threads/thread.h | 1 |
3 files changed, 24 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 | |||
| 223 | lock_acquire (struct lock *lock) | 223 | lock_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); |
diff --git a/threads/thread.c b/threads/thread.c index 358d3a1..61ab5d9 100644 --- a/threads/thread.c +++ b/threads/thread.c | |||
| @@ -380,6 +380,7 @@ void | |||
| 380 | thread_other_set_priority (struct thread *t, int new_priority) | 380 | thread_other_set_priority (struct thread *t, int new_priority) |
| 381 | { | 381 | { |
| 382 | ASSERT (is_thread (t)); | 382 | ASSERT (is_thread (t)); |
| 383 | ASSERT (new_priority >= PRI_MIN && new_priority <= PRI_MAX); | ||
| 383 | 384 | ||
| 384 | if (t->priority == new_priority) | 385 | if (t->priority == new_priority) |
| 385 | return; | 386 | return; |
diff --git a/threads/thread.h b/threads/thread.h index 8cfafe6..fd4f8a6 100644 --- a/threads/thread.h +++ b/threads/thread.h | |||
| @@ -111,6 +111,7 @@ struct thread | |||
| 111 | int is_donated; /* flag if threads priority has been donated by another thread */ | 111 | int is_donated; /* flag if threads priority has been donated by another thread */ |
| 112 | int saved_priority; /* saved base priority in case of priority dontation */ | 112 | int saved_priority; /* saved base priority in case of priority dontation */ |
| 113 | struct list locks; /* list of locks the thread currently holds */ | 113 | struct list locks; /* list of locks the thread currently holds */ |
| 114 | struct lock *blocked_lock; /* lock the thread currently trys to accquire (but hasn't yet) */ | ||
| 114 | }; | 115 | }; |
| 115 | 116 | ||
| 116 | /* If false (default), use round-robin scheduler. | 117 | /* If false (default), use round-robin scheduler. |
