diff options
| author | manuel <manuel@mausz.at> | 2012-05-10 12:04:50 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-05-10 12:04:50 +0200 |
| commit | 2ea82ff0203b1cc22b55900752d44514506eb01e (patch) | |
| tree | 7b073ca8027d1065c06a5894799d8b48e38887a4 | |
| parent | 2aaf7251b5191920d0880010c1cb30fb56f92c14 (diff) | |
| download | progos-2ea82ff0203b1cc22b55900752d44514506eb01e.tar.gz progos-2ea82ff0203b1cc22b55900752d44514506eb01e.tar.bz2 progos-2ea82ff0203b1cc22b55900752d44514506eb01e.zip | |
* only wake up one thread in sema_up() and remove pre-sorting in sema_down()
* some small code guideline fixes
| -rw-r--r-- | threads/synch.c | 67 | ||||
| -rw-r--r-- | threads/thread.c | 51 |
2 files changed, 61 insertions, 57 deletions
diff --git a/threads/synch.c b/threads/synch.c index 2cb4805..6ffe1de 100644 --- a/threads/synch.c +++ b/threads/synch.c | |||
| @@ -73,9 +73,8 @@ sema_down (struct semaphore *sema) | |||
| 73 | old_level = intr_disable (); | 73 | old_level = intr_disable (); |
| 74 | while (sema->value == 0) | 74 | while (sema->value == 0) |
| 75 | { | 75 | { |
| 76 | /* add thread to our ordered waiters list */ | 76 | /* sorting the list here isn't useful. see sema_up() for more details */ |
| 77 | list_insert_ordered (&sema->waiters, &thread_current ()->elem, | 77 | list_push_back (&sema->waiters, &thread_current ()->elem); |
| 78 | &thread_priority_cmp_greater, NULL); | ||
| 79 | thread_block (); | 78 | thread_block (); |
| 80 | } | 79 | } |
| 81 | sema->value--; | 80 | sema->value--; |
| @@ -116,21 +115,27 @@ void | |||
| 116 | sema_up (struct semaphore *sema) | 115 | sema_up (struct semaphore *sema) |
| 117 | { | 116 | { |
| 118 | enum intr_level old_level; | 117 | enum intr_level old_level; |
| 119 | struct thread *t = NULL; | 118 | bool yield = false; |
| 120 | 119 | ||
| 121 | ASSERT (sema != NULL); | 120 | ASSERT (sema != NULL); |
| 122 | 121 | ||
| 123 | old_level = intr_disable (); | 122 | old_level = intr_disable (); |
| 124 | while (!list_empty (&sema->waiters)) | 123 | if (!list_empty (&sema->waiters)) |
| 125 | { | 124 | { |
| 126 | t = list_entry (list_pop_front (&sema->waiters), struct thread, elem); | 125 | /* we can't sort the list during insertion that easily as the priority of |
| 127 | thread_unblock (t); | 126 | blocked/waiting threads may change due to priority donation. |
| 128 | } | 127 | we only need to unblock one thread thus we simply sort the list here */ |
| 128 | list_sort (&sema->waiters, &thread_priority_cmp_greater, NULL); | ||
| 129 | struct thread *t = list_entry (list_pop_front (&sema->waiters), struct thread, elem); | ||
| 130 | /* thread_unblock() doesn't yield so check if there's a need */ | ||
| 131 | if (t->priority > thread_current ()->priority) | ||
| 132 | yield = true; | ||
| 133 | thread_unblock (t); | ||
| 134 | } | ||
| 129 | sema->value++; | 135 | sema->value++; |
| 130 | intr_set_level (old_level); | 136 | intr_set_level (old_level); |
| 131 | 137 | ||
| 132 | /* thread_unblock() doesn't yield so check if there's a need */ | 138 | if (yield) |
| 133 | if (t != NULL && t->priority > thread_current ()->priority) | ||
| 134 | thread_yield(); | 139 | thread_yield(); |
| 135 | } | 140 | } |
| 136 | 141 | ||
| @@ -224,22 +229,22 @@ lock_acquire (struct lock *lock) | |||
| 224 | ASSERT (!lock_held_by_current_thread (lock)); | 229 | ASSERT (!lock_held_by_current_thread (lock)); |
| 225 | 230 | ||
| 226 | if (lock->holder != NULL) | 231 | if (lock->holder != NULL) |
| 227 | { | ||
| 228 | /* check for a possible priority donation */ | ||
| 229 | if (cur->priority > lock->priority) | ||
| 230 | { | 232 | { |
| 231 | /* the new priority of this lock is our own priority */ | 233 | /* check for a possible priority donation */ |
| 232 | lock->priority = cur->priority; | 234 | if (cur->priority > lock->priority) |
| 233 | 235 | { | |
| 234 | /* the lock priority changed so we need to sort the lock list of the lock holder */ | 236 | /* the new priority of this lock is our own priority */ |
| 235 | list_remove (&lock->elem); | 237 | lock->priority = cur->priority; |
| 236 | list_insert_ordered (&lock->holder->locks, &lock->elem, | 238 | |
| 237 | lock_priority_cmp_greater, NULL); | 239 | /* the lock priority changed so we need to sort the lock list of the lock holder */ |
| 238 | 240 | list_remove (&lock->elem); | |
| 239 | /* finally donate our priority */ | 241 | list_insert_ordered (&lock->holder->locks, &lock->elem, |
| 240 | thread_donate_priority (cur, lock->holder); | 242 | lock_priority_cmp_greater, NULL); |
| 243 | |||
| 244 | /* finally donate our priority */ | ||
| 245 | thread_donate_priority (cur, lock->holder); | ||
| 246 | } | ||
| 241 | } | 247 | } |
| 242 | } | ||
| 243 | 248 | ||
| 244 | sema_down (&lock->semaphore); | 249 | sema_down (&lock->semaphore); |
| 245 | lock->holder = cur; | 250 | lock->holder = cur; |
| @@ -296,12 +301,12 @@ lock_release (struct lock *lock) | |||
| 296 | /* we don't hold another lock so restore our base priority */ | 301 | /* we don't hold another lock so restore our base priority */ |
| 297 | thread_donation_pass_back (); | 302 | thread_donation_pass_back (); |
| 298 | else | 303 | else |
| 299 | { | 304 | { |
| 300 | /* we still hold at least one lock so change our priority to the priority of the lock */ | 305 | /* we still hold at least one lock so change our priority to the priority of the lock */ |
| 301 | struct lock *lock2 = list_entry (list_front (&cur->locks), struct lock, elem); | 306 | struct lock *lock2 = list_entry (list_front (&cur->locks), struct lock, elem); |
| 302 | /* (forced) priority change */ | 307 | /* (forced) priority change */ |
| 303 | thread_other_set_priority (cur, lock2->priority); | 308 | thread_other_set_priority (cur, lock2->priority); |
| 304 | } | 309 | } |
| 305 | } | 310 | } |
| 306 | 311 | ||
| 307 | /* Returns true if the current thread holds LOCK, false | 312 | /* Returns true if the current thread holds LOCK, false |
diff --git a/threads/thread.c b/threads/thread.c index a7db106..358d3a1 100644 --- a/threads/thread.c +++ b/threads/thread.c | |||
| @@ -367,12 +367,12 @@ thread_set_priority (int new_priority) | |||
| 367 | return; | 367 | return; |
| 368 | 368 | ||
| 369 | if (cur->is_donated) | 369 | if (cur->is_donated) |
| 370 | { | 370 | { |
| 371 | cur->saved_priority = new_priority; | 371 | cur->saved_priority = new_priority; |
| 372 | /* make sure we don't lower a donated priority */ | 372 | /* make sure we don't lower a donated priority */ |
| 373 | if (new_priority < cur->priority) | 373 | if (new_priority < cur->priority) |
| 374 | return; | 374 | return; |
| 375 | } | 375 | } |
| 376 | thread_other_set_priority (cur, new_priority); | 376 | thread_other_set_priority (cur, new_priority); |
| 377 | } | 377 | } |
| 378 | 378 | ||
| @@ -387,18 +387,18 @@ thread_other_set_priority (struct thread *t, int new_priority) | |||
| 387 | t->priority = new_priority; | 387 | t->priority = new_priority; |
| 388 | 388 | ||
| 389 | if (t->status == THREAD_READY) | 389 | if (t->status == THREAD_READY) |
| 390 | { | 390 | { |
| 391 | /* sort our ordered list */ | 391 | /* sort our ordered list */ |
| 392 | list_remove (&t->elem); | 392 | list_remove (&t->elem); |
| 393 | list_insert_ordered (&ready_list, &t->elem, &thread_priority_cmp_greater, NULL); | 393 | list_insert_ordered (&ready_list, &t->elem, &thread_priority_cmp_greater, NULL); |
| 394 | } | 394 | } |
| 395 | else if (t->status == THREAD_RUNNING && !list_empty (&ready_list)) | 395 | else if (t->status == THREAD_RUNNING && !list_empty (&ready_list)) |
| 396 | { | 396 | { |
| 397 | /* compare priority with the highest priority in the list */ | 397 | /* compare priority with the highest priority in the list */ |
| 398 | struct thread *t2 = list_entry (list_front (&ready_list), struct thread, elem); | 398 | struct thread *t2 = list_entry (list_front (&ready_list), struct thread, elem); |
| 399 | if (t2->priority > t->priority) | 399 | if (t2->priority > t->priority) |
| 400 | thread_yield (); | 400 | thread_yield (); |
| 401 | } | 401 | } |
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | void | 404 | void |
| @@ -413,21 +413,20 @@ thread_donate_priority (struct thread *donator, struct thread *donee) | |||
| 413 | 413 | ||
| 414 | /* store our base priority */ | 414 | /* store our base priority */ |
| 415 | if (!donee->is_donated) | 415 | if (!donee->is_donated) |
| 416 | { | 416 | { |
| 417 | donee->saved_priority = donee->priority; | 417 | donee->saved_priority = donee->priority; |
| 418 | donee->is_donated = true; | 418 | donee->is_donated = true; |
| 419 | } | 419 | } |
| 420 | thread_other_set_priority (donee, donator->priority); | 420 | thread_other_set_priority (donee, donator->priority); |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | void | 423 | void |
| 424 | thread_donation_pass_back (void) | 424 | thread_donation_pass_back (void) |
| 425 | { | 425 | { |
| 426 | if (thread_current ()->is_donated) | 426 | if (!thread_current ()->is_donated) |
| 427 | { | 427 | return; |
| 428 | thread_current ()->is_donated = false; | 428 | thread_current ()->is_donated = false; |
| 429 | thread_set_priority (thread_current ()->saved_priority); | 429 | thread_set_priority (thread_current ()->saved_priority); |
| 430 | } | ||
| 431 | } | 430 | } |
| 432 | 431 | ||
| 433 | /* Returns the current thread's priority. */ | 432 | /* Returns the current thread's priority. */ |
