diff options
| -rw-r--r-- | threads/synch.c | 51 | ||||
| -rw-r--r-- | threads/thread.c | 12 | ||||
| -rw-r--r-- | threads/thread.h | 2 |
3 files changed, 46 insertions, 19 deletions
diff --git a/threads/synch.c b/threads/synch.c index 1f15bb9..92008ef 100644 --- a/threads/synch.c +++ b/threads/synch.c | |||
| @@ -32,8 +32,10 @@ | |||
| 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, | 35 | static bool lock_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b, |
| 36 | void *AUX UNUSED); | 36 | void *AUX UNUSED); |
| 37 | static bool semaphore_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b, | ||
| 38 | void *aux UNUSED); | ||
| 37 | 39 | ||
| 38 | /* Initializes semaphore SEMA to VALUE. A semaphore is a | 40 | /* Initializes semaphore SEMA to VALUE. A semaphore is a |
| 39 | nonnegative integer along with two atomic operators for | 41 | nonnegative integer along with two atomic operators for |
| @@ -72,7 +74,8 @@ sema_down (struct semaphore *sema) | |||
| 72 | while (sema->value == 0) | 74 | while (sema->value == 0) |
| 73 | { | 75 | { |
| 74 | /* add thread to our ordered waiters list */ | 76 | /* add thread to our ordered waiters list */ |
| 75 | list_insert_ordered (&sema->waiters, &thread_current ()->elem, &priority_list_cmp_greater, NULL); | 77 | list_insert_ordered (&sema->waiters, &thread_current ()->elem, |
| 78 | &thread_priority_cmp_greater, NULL); | ||
| 76 | thread_block (); | 79 | thread_block (); |
| 77 | } | 80 | } |
| 78 | sema->value--; | 81 | sema->value--; |
| @@ -113,15 +116,25 @@ void | |||
| 113 | sema_up (struct semaphore *sema) | 116 | sema_up (struct semaphore *sema) |
| 114 | { | 117 | { |
| 115 | enum intr_level old_level; | 118 | enum intr_level old_level; |
| 119 | bool yield = false; | ||
| 116 | 120 | ||
| 117 | ASSERT (sema != NULL); | 121 | ASSERT (sema != NULL); |
| 118 | 122 | ||
| 119 | old_level = intr_disable (); | 123 | old_level = intr_disable (); |
| 120 | if (!list_empty (&sema->waiters)) | 124 | if (!list_empty (&sema->waiters)) |
| 121 | thread_unblock (list_entry (list_pop_front (&sema->waiters), | 125 | { |
| 122 | struct thread, elem)); | 126 | struct thread *t = list_entry (list_pop_front (&sema->waiters), |
| 127 | struct thread, elem); | ||
| 128 | thread_unblock (t); | ||
| 129 | /* thread_unblock() doesn't yield so check if there's a need */ | ||
| 130 | if (t->priority > thread_current ()->priority) | ||
| 131 | yield = true; | ||
| 132 | } | ||
| 123 | sema->value++; | 133 | sema->value++; |
| 124 | intr_set_level (old_level); | 134 | intr_set_level (old_level); |
| 135 | |||
| 136 | if (yield) | ||
| 137 | thread_yield(); | ||
| 125 | } | 138 | } |
| 126 | 139 | ||
| 127 | static void sema_test_helper (void *sema_); | 140 | static void sema_test_helper (void *sema_); |
| @@ -187,11 +200,11 @@ lock_init (struct lock *lock) | |||
| 187 | 200 | ||
| 188 | /* comparison function for our descending ordered lock list. */ | 201 | /* comparison function for our descending ordered lock list. */ |
| 189 | static bool | 202 | static bool |
| 190 | lock_list_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b, | 203 | lock_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b, |
| 191 | void *AUX UNUSED) | 204 | void *AUX UNUSED) |
| 192 | { | 205 | { |
| 193 | struct lock *l1 = list_entry (a, struct lock, elem); | 206 | const struct lock *l1 = list_entry (a, struct lock, elem); |
| 194 | struct lock *l2 = list_entry (b, struct lock, elem); | 207 | const struct lock *l2 = list_entry (b, struct lock, elem); |
| 195 | /* descending order - put newer in front */ | 208 | /* descending order - put newer in front */ |
| 196 | return (l1->priority >= l2->priority); | 209 | return (l1->priority >= l2->priority); |
| 197 | } | 210 | } |
| @@ -226,7 +239,7 @@ lock_acquire (struct lock *lock) | |||
| 226 | /* the lock priority changed so we need to sort the lock list of the lock holder */ | 239 | /* the lock priority changed so we need to sort the lock list of the lock holder */ |
| 227 | list_remove (&lock->elem); | 240 | list_remove (&lock->elem); |
| 228 | list_insert_ordered (&lock->holder->locks, &lock->elem, | 241 | list_insert_ordered (&lock->holder->locks, &lock->elem, |
| 229 | lock_list_priority_cmp_greater, NULL); | 242 | lock_priority_cmp_greater, NULL); |
| 230 | 243 | ||
| 231 | /* finally donate our priority */ | 244 | /* finally donate our priority */ |
| 232 | thread_donate_priority (cur, lock->holder); | 245 | thread_donate_priority (cur, lock->holder); |
| @@ -241,7 +254,7 @@ lock_acquire (struct lock *lock) | |||
| 241 | 254 | ||
| 242 | /* save the locks we hold in descending order of their priority */ | 255 | /* save the locks we hold in descending order of their priority */ |
| 243 | list_insert_ordered (&lock->holder->locks, &lock->elem, | 256 | list_insert_ordered (&lock->holder->locks, &lock->elem, |
| 244 | lock_list_priority_cmp_greater, NULL); | 257 | lock_priority_cmp_greater, NULL); |
| 245 | } | 258 | } |
| 246 | 259 | ||
| 247 | /* Tries to acquires LOCK and returns true if successful or false | 260 | /* Tries to acquires LOCK and returns true if successful or false |
| @@ -315,6 +328,7 @@ struct semaphore_elem | |||
| 315 | { | 328 | { |
| 316 | struct list_elem elem; /* List element. */ | 329 | struct list_elem elem; /* List element. */ |
| 317 | struct semaphore semaphore; /* This semaphore. */ | 330 | struct semaphore semaphore; /* This semaphore. */ |
| 331 | int priority; /* the priority of the waiting thread */ | ||
| 318 | }; | 332 | }; |
| 319 | 333 | ||
| 320 | /* Initializes condition variable COND. A condition variable | 334 | /* Initializes condition variable COND. A condition variable |
| @@ -328,6 +342,16 @@ cond_init (struct condition *cond) | |||
| 328 | list_init (&cond->waiters); | 342 | list_init (&cond->waiters); |
| 329 | } | 343 | } |
| 330 | 344 | ||
| 345 | /* comparison function for our descending ordered condition waiters list. */ | ||
| 346 | static bool | ||
| 347 | semaphore_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b, | ||
| 348 | void *aux UNUSED) | ||
| 349 | { | ||
| 350 | const struct semaphore_elem *s1 = list_entry (a, struct semaphore_elem, elem); | ||
| 351 | const struct semaphore_elem *s2 = list_entry (b, struct semaphore_elem, elem); | ||
| 352 | return (s1->priority > s2->priority); | ||
| 353 | } | ||
| 354 | |||
| 331 | /* Atomically releases LOCK and waits for COND to be signaled by | 355 | /* Atomically releases LOCK and waits for COND to be signaled by |
| 332 | some other piece of code. After COND is signaled, LOCK is | 356 | some other piece of code. After COND is signaled, LOCK is |
| 333 | reacquired before returning. LOCK must be held before calling | 357 | reacquired before returning. LOCK must be held before calling |
| @@ -359,8 +383,11 @@ cond_wait (struct condition *cond, struct lock *lock) | |||
| 359 | ASSERT (lock_held_by_current_thread (lock)); | 383 | ASSERT (lock_held_by_current_thread (lock)); |
| 360 | 384 | ||
| 361 | sema_init (&waiter.semaphore, 0); | 385 | sema_init (&waiter.semaphore, 0); |
| 362 | /* add thread to our ordered waiters list */ | 386 | /* set condition priority */ |
| 363 | list_insert_ordered (&cond->waiters, &waiter.elem, &priority_list_cmp_greater, NULL); | 387 | waiter.priority = thread_current ()->priority; |
| 388 | /* and add condition to our ordered waiters list */ | ||
| 389 | list_insert_ordered (&cond->waiters, &waiter.elem, | ||
| 390 | &semaphore_priority_cmp_greater, NULL); | ||
| 364 | lock_release (lock); | 391 | lock_release (lock); |
| 365 | sema_down (&waiter.semaphore); | 392 | sema_down (&waiter.semaphore); |
| 366 | lock_acquire (lock); | 393 | lock_acquire (lock); |
diff --git a/threads/thread.c b/threads/thread.c index 17d21bd..a7db106 100644 --- a/threads/thread.c +++ b/threads/thread.c | |||
| @@ -73,11 +73,11 @@ static tid_t allocate_tid (void); | |||
| 73 | 73 | ||
| 74 | /* comparison function for our descending ordered ready list. */ | 74 | /* comparison function for our descending ordered ready list. */ |
| 75 | bool | 75 | bool |
| 76 | priority_list_cmp_greater(const struct list_elem *a, const struct list_elem *b, | 76 | thread_priority_cmp_greater(const struct list_elem *a, const struct list_elem *b, |
| 77 | void *AUX UNUSED) | 77 | void *AUX UNUSED) |
| 78 | { | 78 | { |
| 79 | struct thread *t1 = list_entry (a, struct thread, elem); | 79 | const struct thread *t1 = list_entry (a, struct thread, elem); |
| 80 | struct thread *t2 = list_entry (b, struct thread, elem); | 80 | const struct thread *t2 = list_entry (b, struct thread, elem); |
| 81 | return (t1->priority > t2->priority); | 81 | return (t1->priority > t2->priority); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| @@ -264,7 +264,7 @@ thread_unblock (struct thread *t) | |||
| 264 | old_level = intr_disable (); | 264 | old_level = intr_disable (); |
| 265 | ASSERT (t->status == THREAD_BLOCKED); | 265 | ASSERT (t->status == THREAD_BLOCKED); |
| 266 | /* add thread to our ordered ready_list */ | 266 | /* add thread to our ordered ready_list */ |
| 267 | list_insert_ordered (&ready_list, &t->elem, &priority_list_cmp_greater, NULL); | 267 | list_insert_ordered (&ready_list, &t->elem, &thread_priority_cmp_greater, NULL); |
| 268 | t->status = THREAD_READY; | 268 | t->status = THREAD_READY; |
| 269 | intr_set_level (old_level); | 269 | intr_set_level (old_level); |
| 270 | } | 270 | } |
| @@ -335,7 +335,7 @@ thread_yield (void) | |||
| 335 | 335 | ||
| 336 | old_level = intr_disable (); | 336 | old_level = intr_disable (); |
| 337 | if (cur != idle_thread) | 337 | if (cur != idle_thread) |
| 338 | list_insert_ordered (&ready_list, &cur->elem, &priority_list_cmp_greater, NULL); | 338 | list_insert_ordered (&ready_list, &cur->elem, &thread_priority_cmp_greater, NULL); |
| 339 | cur->status = THREAD_READY; | 339 | cur->status = THREAD_READY; |
| 340 | schedule (); | 340 | schedule (); |
| 341 | intr_set_level (old_level); | 341 | intr_set_level (old_level); |
| @@ -390,7 +390,7 @@ thread_other_set_priority (struct thread *t, int new_priority) | |||
| 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, &priority_list_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 | { |
diff --git a/threads/thread.h b/threads/thread.h index a6ef25d..8bc6512 100644 --- a/threads/thread.h +++ b/threads/thread.h | |||
| @@ -118,7 +118,7 @@ struct thread | |||
| 118 | Controlled by kernel command-line option "-o mlfqs". */ | 118 | Controlled by kernel command-line option "-o mlfqs". */ |
| 119 | extern bool thread_mlfqs; | 119 | extern bool thread_mlfqs; |
| 120 | 120 | ||
| 121 | bool priority_list_cmp_greater (const struct list_elem *a, const struct list_elem *b, | 121 | bool thread_priority_cmp_greater (const struct list_elem *a, const struct list_elem *b, |
| 122 | void *aux); | 122 | void *aux); |
| 123 | 123 | ||
| 124 | void thread_init (void); | 124 | void thread_init (void); |
