diff options
Diffstat (limited to 'threads/thread.c')
| -rw-r--r-- | threads/thread.c | 86 |
1 files changed, 74 insertions, 12 deletions
diff --git a/threads/thread.c b/threads/thread.c index 3fefbd8..17d21bd 100644 --- a/threads/thread.c +++ b/threads/thread.c | |||
| @@ -71,9 +71,9 @@ static void schedule (void); | |||
| 71 | void thread_schedule_tail (struct thread *prev); | 71 | void thread_schedule_tail (struct thread *prev); |
| 72 | static tid_t allocate_tid (void); | 72 | static tid_t allocate_tid (void); |
| 73 | 73 | ||
| 74 | //TODO: should take donated priority into account | 74 | /* comparison function for our descending ordered ready list. */ |
| 75 | static bool | 75 | bool |
| 76 | ready_list_cmp_less(const struct list_elem *a, const struct list_elem *b, | 76 | priority_list_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 | struct thread *t1 = list_entry (a, struct thread, elem); |
| @@ -222,7 +222,10 @@ thread_create (const char *name, int priority, | |||
| 222 | 222 | ||
| 223 | /* Add to run queue. */ | 223 | /* Add to run queue. */ |
| 224 | thread_unblock (t); | 224 | thread_unblock (t); |
| 225 | thread_yield (); | 225 | |
| 226 | /* and yield the cpu in case we have a higher priority */ | ||
| 227 | if (t->priority > thread_current ()->priority) | ||
| 228 | thread_yield (); | ||
| 226 | 229 | ||
| 227 | return tid; | 230 | return tid; |
| 228 | } | 231 | } |
| @@ -261,7 +264,7 @@ thread_unblock (struct thread *t) | |||
| 261 | old_level = intr_disable (); | 264 | old_level = intr_disable (); |
| 262 | ASSERT (t->status == THREAD_BLOCKED); | 265 | ASSERT (t->status == THREAD_BLOCKED); |
| 263 | /* add thread to our ordered ready_list */ | 266 | /* add thread to our ordered ready_list */ |
| 264 | list_insert_ordered (&ready_list, &t->elem, &ready_list_cmp_less, NULL); | 267 | list_insert_ordered (&ready_list, &t->elem, &priority_list_cmp_greater, NULL); |
| 265 | t->status = THREAD_READY; | 268 | t->status = THREAD_READY; |
| 266 | intr_set_level (old_level); | 269 | intr_set_level (old_level); |
| 267 | } | 270 | } |
| @@ -332,7 +335,7 @@ thread_yield (void) | |||
| 332 | 335 | ||
| 333 | old_level = intr_disable (); | 336 | old_level = intr_disable (); |
| 334 | if (cur != idle_thread) | 337 | if (cur != idle_thread) |
| 335 | list_insert_ordered (&ready_list, &cur->elem, &ready_list_cmp_less, NULL); | 338 | list_insert_ordered (&ready_list, &cur->elem, &priority_list_cmp_greater, NULL); |
| 336 | cur->status = THREAD_READY; | 339 | cur->status = THREAD_READY; |
| 337 | schedule (); | 340 | schedule (); |
| 338 | intr_set_level (old_level); | 341 | intr_set_level (old_level); |
| @@ -359,14 +362,71 @@ thread_foreach (thread_action_func *func, void *aux) | |||
| 359 | void | 362 | void |
| 360 | thread_set_priority (int new_priority) | 363 | thread_set_priority (int new_priority) |
| 361 | { | 364 | { |
| 362 | thread_current ()->priority = new_priority; | 365 | struct thread *cur = thread_current (); |
| 366 | if (cur->priority == new_priority) | ||
| 367 | return; | ||
| 368 | |||
| 369 | if (cur->is_donated) | ||
| 370 | { | ||
| 371 | cur->saved_priority = new_priority; | ||
| 372 | /* make sure we don't lower a donated priority */ | ||
| 373 | if (new_priority < cur->priority) | ||
| 374 | return; | ||
| 375 | } | ||
| 376 | thread_other_set_priority (cur, new_priority); | ||
| 377 | } | ||
| 363 | 378 | ||
| 364 | /* compare priority with the highest priority in the list */ | 379 | void |
| 365 | if (!list_empty (&ready_list)) | 380 | thread_other_set_priority (struct thread *t, int new_priority) |
| 381 | { | ||
| 382 | ASSERT (is_thread (t)); | ||
| 383 | |||
| 384 | if (t->priority == new_priority) | ||
| 385 | return; | ||
| 386 | |||
| 387 | t->priority = new_priority; | ||
| 388 | |||
| 389 | if (t->status == THREAD_READY) | ||
| 390 | { | ||
| 391 | /* sort our ordered list */ | ||
| 392 | list_remove (&t->elem); | ||
| 393 | list_insert_ordered (&ready_list, &t->elem, &priority_list_cmp_greater, NULL); | ||
| 394 | } | ||
| 395 | else if (t->status == THREAD_RUNNING && !list_empty (&ready_list)) | ||
| 396 | { | ||
| 397 | /* compare priority with the highest priority in the list */ | ||
| 398 | struct thread *t2 = list_entry (list_front (&ready_list), struct thread, elem); | ||
| 399 | if (t2->priority > t->priority) | ||
| 400 | thread_yield (); | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | void | ||
| 405 | thread_donate_priority (struct thread *donator, struct thread *donee) | ||
| 406 | { | ||
| 407 | ASSERT (is_thread (donator)); | ||
| 408 | ASSERT (is_thread (donee)); | ||
| 409 | |||
| 410 | /* make sure we don't lower a donated priority */ | ||
| 411 | if (donator->priority < donee->priority) | ||
| 412 | return; | ||
| 413 | |||
| 414 | /* store our base priority */ | ||
| 415 | if (!donee->is_donated) | ||
| 416 | { | ||
| 417 | donee->saved_priority = donee->priority; | ||
| 418 | donee->is_donated = true; | ||
| 419 | } | ||
| 420 | thread_other_set_priority (donee, donator->priority); | ||
| 421 | } | ||
| 422 | |||
| 423 | void | ||
| 424 | thread_donation_pass_back (void) | ||
| 425 | { | ||
| 426 | if (thread_current ()->is_donated) | ||
| 366 | { | 427 | { |
| 367 | struct thread *t = list_entry (list_front (&ready_list), struct thread, elem); | 428 | thread_current ()->is_donated = false; |
| 368 | if (t->priority > thread_current ()->priority) | 429 | thread_set_priority (thread_current ()->saved_priority); |
| 369 | thread_yield(); | ||
| 370 | } | 430 | } |
| 371 | } | 431 | } |
| 372 | 432 | ||
| @@ -497,6 +557,8 @@ init_thread (struct thread *t, const char *name, int priority) | |||
| 497 | #ifdef USERPROG | 557 | #ifdef USERPROG |
| 498 | list_init(&t->children); | 558 | list_init(&t->children); |
| 499 | #endif | 559 | #endif |
| 560 | t->is_donated = false; | ||
| 561 | list_init (&t->locks); | ||
| 500 | } | 562 | } |
| 501 | 563 | ||
| 502 | /* Allocates a SIZE-byte frame at the top of thread T's stack and | 564 | /* Allocates a SIZE-byte frame at the top of thread T's stack and |
