diff options
| author | manuel <manuel@mausz.at> | 2012-05-07 18:01:20 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-05-07 18:01:20 +0200 |
| commit | 158ea87fba909161a084c29feff29a168725fe4e (patch) | |
| tree | ce580f0fec9f4d5105e817ae11fded8015817574 /threads/synch.c | |
| parent | 3d1e18466b44b2de06dd7c00a85e78ed9340906d (diff) | |
| download | progos-158ea87fba909161a084c29feff29a168725fe4e.tar.gz progos-158ea87fba909161a084c29feff29a168725fe4e.tar.bz2 progos-158ea87fba909161a084c29feff29a168725fe4e.zip | |
first priority donation implementation
Diffstat (limited to 'threads/synch.c')
| -rw-r--r-- | threads/synch.c | 71 |
1 files changed, 68 insertions, 3 deletions
diff --git a/threads/synch.c b/threads/synch.c index 317c68a..1f15bb9 100644 --- a/threads/synch.c +++ b/threads/synch.c | |||
| @@ -32,6 +32,9 @@ | |||
| 32 | #include "threads/interrupt.h" | 32 | #include "threads/interrupt.h" |
| 33 | #include "threads/thread.h" | 33 | #include "threads/thread.h" |
| 34 | 34 | ||
| 35 | static bool lock_list_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b, | ||
| 36 | void *AUX UNUSED); | ||
| 37 | |||
| 35 | /* Initializes semaphore SEMA to VALUE. A semaphore is a | 38 | /* Initializes semaphore SEMA to VALUE. A semaphore is a |
| 36 | nonnegative integer along with two atomic operators for | 39 | nonnegative integer along with two atomic operators for |
| 37 | manipulating it: | 40 | manipulating it: |
| @@ -68,7 +71,8 @@ sema_down (struct semaphore *sema) | |||
| 68 | old_level = intr_disable (); | 71 | old_level = intr_disable (); |
| 69 | while (sema->value == 0) | 72 | while (sema->value == 0) |
| 70 | { | 73 | { |
| 71 | list_push_back (&sema->waiters, &thread_current ()->elem); | 74 | /* add thread to our ordered waiters list */ |
| 75 | list_insert_ordered (&sema->waiters, &thread_current ()->elem, &priority_list_cmp_greater, NULL); | ||
| 72 | thread_block (); | 76 | thread_block (); |
| 73 | } | 77 | } |
| 74 | sema->value--; | 78 | sema->value--; |
| @@ -181,6 +185,17 @@ lock_init (struct lock *lock) | |||
| 181 | sema_init (&lock->semaphore, 1); | 185 | sema_init (&lock->semaphore, 1); |
| 182 | } | 186 | } |
| 183 | 187 | ||
| 188 | /* comparison function for our descending ordered lock list. */ | ||
| 189 | static bool | ||
| 190 | lock_list_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b, | ||
| 191 | void *AUX UNUSED) | ||
| 192 | { | ||
| 193 | struct lock *l1 = list_entry (a, struct lock, elem); | ||
| 194 | struct lock *l2 = list_entry (b, struct lock, elem); | ||
| 195 | /* descending order - put newer in front */ | ||
| 196 | return (l1->priority >= l2->priority); | ||
| 197 | } | ||
| 198 | |||
| 184 | /* Acquires LOCK, sleeping until it becomes available if | 199 | /* Acquires LOCK, sleeping until it becomes available if |
| 185 | necessary. The lock must not already be held by the current | 200 | necessary. The lock must not already be held by the current |
| 186 | thread. | 201 | thread. |
| @@ -192,12 +207,41 @@ lock_init (struct lock *lock) | |||
| 192 | void | 207 | void |
| 193 | lock_acquire (struct lock *lock) | 208 | lock_acquire (struct lock *lock) |
| 194 | { | 209 | { |
| 210 | struct thread *cur = thread_current (); | ||
| 211 | |||
| 195 | ASSERT (lock != NULL); | 212 | ASSERT (lock != NULL); |
| 196 | ASSERT (!intr_context ()); | 213 | ASSERT (!intr_context ()); |
| 197 | ASSERT (!lock_held_by_current_thread (lock)); | 214 | ASSERT (!lock_held_by_current_thread (lock)); |
| 198 | 215 | ||
| 216 | if (lock->holder != NULL) | ||
| 217 | { | ||
| 218 | //printf("[%d] acquire: lock=%p prio=%d\n", cur->tid, lock, cur->priority); | ||
| 219 | |||
| 220 | /* check for a possible priority donation */ | ||
| 221 | if (cur->priority > lock->priority) | ||
| 222 | { | ||
| 223 | /* the new priority of this lock is our own priority */ | ||
| 224 | lock->priority = cur->priority; | ||
| 225 | |||
| 226 | /* the lock priority changed so we need to sort the lock list of the lock holder */ | ||
| 227 | list_remove (&lock->elem); | ||
| 228 | list_insert_ordered (&lock->holder->locks, &lock->elem, | ||
| 229 | lock_list_priority_cmp_greater, NULL); | ||
| 230 | |||
| 231 | /* finally donate our priority */ | ||
| 232 | thread_donate_priority (cur, lock->holder); | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 199 | sema_down (&lock->semaphore); | 236 | sema_down (&lock->semaphore); |
| 200 | lock->holder = thread_current (); | 237 | lock->holder = cur; |
| 238 | |||
| 239 | /* the priority of this lock is our own priority */ | ||
| 240 | lock->priority = cur->priority; | ||
| 241 | |||
| 242 | /* save the locks we hold in descending order of their priority */ | ||
| 243 | list_insert_ordered (&lock->holder->locks, &lock->elem, | ||
| 244 | lock_list_priority_cmp_greater, NULL); | ||
| 201 | } | 245 | } |
| 202 | 246 | ||
| 203 | /* Tries to acquires LOCK and returns true if successful or false | 247 | /* Tries to acquires LOCK and returns true if successful or false |
| @@ -228,11 +272,31 @@ lock_try_acquire (struct lock *lock) | |||
| 228 | void | 272 | void |
| 229 | lock_release (struct lock *lock) | 273 | lock_release (struct lock *lock) |
| 230 | { | 274 | { |
| 275 | struct thread *cur = thread_current (); | ||
| 276 | |||
| 231 | ASSERT (lock != NULL); | 277 | ASSERT (lock != NULL); |
| 232 | ASSERT (lock_held_by_current_thread (lock)); | 278 | ASSERT (lock_held_by_current_thread (lock)); |
| 233 | 279 | ||
| 234 | lock->holder = NULL; | 280 | lock->holder = NULL; |
| 281 | //lock->priority = we don't care as the next lock_acquire ()-call does | ||
| 235 | sema_up (&lock->semaphore); | 282 | sema_up (&lock->semaphore); |
| 283 | |||
| 284 | /* we don't hold the lock any longer so remove it from the lock list */ | ||
| 285 | list_remove (&lock->elem); | ||
| 286 | |||
| 287 | if (list_empty (&cur->locks)) | ||
| 288 | { | ||
| 289 | //printf("[%d] restoring prio from %d to %d\n", cur->tid, cur->priority, cur->saved_priority); | ||
| 290 | /* we don't hold another lock so restore our base priority */ | ||
| 291 | thread_donation_pass_back (); | ||
| 292 | } | ||
| 293 | else | ||
| 294 | { | ||
| 295 | /* we still hold at least one lock so change our priority to the priority of the lock */ | ||
| 296 | struct lock *lock2 = list_entry (list_front (&cur->locks), struct lock, elem); | ||
| 297 | /* (forced) priority change */ | ||
| 298 | thread_other_set_priority (cur, lock2->priority); | ||
| 299 | } | ||
| 236 | } | 300 | } |
| 237 | 301 | ||
| 238 | /* Returns true if the current thread holds LOCK, false | 302 | /* Returns true if the current thread holds LOCK, false |
| @@ -295,7 +359,8 @@ cond_wait (struct condition *cond, struct lock *lock) | |||
| 295 | ASSERT (lock_held_by_current_thread (lock)); | 359 | ASSERT (lock_held_by_current_thread (lock)); |
| 296 | 360 | ||
| 297 | sema_init (&waiter.semaphore, 0); | 361 | sema_init (&waiter.semaphore, 0); |
| 298 | list_push_back (&cond->waiters, &waiter.elem); | 362 | /* add thread to our ordered waiters list */ |
| 363 | list_insert_ordered (&cond->waiters, &waiter.elem, &priority_list_cmp_greater, NULL); | ||
| 299 | lock_release (lock); | 364 | lock_release (lock); |
| 300 | sema_down (&waiter.semaphore); | 365 | sema_down (&waiter.semaphore); |
| 301 | lock_acquire (lock); | 366 | lock_acquire (lock); |
