diff options
Diffstat (limited to 'threads/thread.c')
| -rw-r--r-- | threads/thread.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/threads/thread.c b/threads/thread.c index 61ab5d9..cf404b6 100644 --- a/threads/thread.c +++ b/threads/thread.c | |||
| @@ -379,12 +379,26 @@ thread_set_priority (int new_priority) | |||
| 379 | void | 379 | void |
| 380 | thread_other_set_priority (struct thread *t, int new_priority) | 380 | thread_other_set_priority (struct thread *t, int new_priority) |
| 381 | { | 381 | { |
| 382 | enum intr_level old_level; | ||
| 383 | bool yield = false; | ||
| 384 | |||
| 382 | ASSERT (is_thread (t)); | 385 | ASSERT (is_thread (t)); |
| 383 | ASSERT (new_priority >= PRI_MIN && new_priority <= PRI_MAX); | 386 | ASSERT (new_priority >= PRI_MIN && new_priority <= PRI_MAX); |
| 384 | 387 | ||
| 385 | if (t->priority == new_priority) | 388 | if (t->priority == new_priority) |
| 386 | return; | 389 | return; |
| 387 | 390 | ||
| 391 | /* we need to disable interrupts here because after changing the thread's | ||
| 392 | priority and a possible timer interrupt which triggers thread_yield() we | ||
| 393 | could run into a couple of races. e.g. no proper sorted ready list, | ||
| 394 | corrupt ready list (wrong internal pointers) or the timer interrupt fires | ||
| 395 | after calling list_empty() but before list_front() while having only two | ||
| 396 | threads (one active, the other one ready). the scheduler then schedules the | ||
| 397 | other thread which runs and terminates, thus removing itself from all lists. | ||
| 398 | after that our thread gets scheduled again and reads from an empty list, | ||
| 399 | although it wasn't empty before. */ | ||
| 400 | old_level = intr_disable (); | ||
| 401 | |||
| 388 | t->priority = new_priority; | 402 | t->priority = new_priority; |
| 389 | 403 | ||
| 390 | if (t->status == THREAD_READY) | 404 | if (t->status == THREAD_READY) |
| @@ -398,8 +412,13 @@ thread_other_set_priority (struct thread *t, int new_priority) | |||
| 398 | /* compare priority with the highest priority in the list */ | 412 | /* compare priority with the highest priority in the list */ |
| 399 | struct thread *t2 = list_entry (list_front (&ready_list), struct thread, elem); | 413 | struct thread *t2 = list_entry (list_front (&ready_list), struct thread, elem); |
| 400 | if (t2->priority > t->priority) | 414 | if (t2->priority > t->priority) |
| 401 | thread_yield (); | 415 | yield = true; |
| 402 | } | 416 | } |
| 417 | |||
| 418 | intr_set_level (old_level); | ||
| 419 | |||
| 420 | if (yield) | ||
| 421 | thread_yield (); | ||
| 403 | } | 422 | } |
| 404 | 423 | ||
| 405 | void | 424 | void |
