summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-05-10 12:04:50 +0200
committermanuel <manuel@mausz.at>2012-05-10 12:04:50 +0200
commit2ea82ff0203b1cc22b55900752d44514506eb01e (patch)
tree7b073ca8027d1065c06a5894799d8b48e38887a4
parent2aaf7251b5191920d0880010c1cb30fb56f92c14 (diff)
downloadprogos-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.c67
-rw-r--r--threads/thread.c51
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
116sema_up (struct semaphore *sema) 115sema_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
404void 404void
@@ -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
423void 423void
424thread_donation_pass_back (void) 424thread_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. */