diff options
| author | manuel <manuel@mausz.at> | 2012-05-11 20:48:58 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-05-11 20:48:58 +0200 |
| commit | 9b19a84ed640cb15e6ca87ddc025c90d78a5fbdc (patch) | |
| tree | 54345ae3ba366d1a4663e93b6b883e842f7a3918 /threads/thread.c | |
| parent | 4571d64e74dadd1b2169e8cd276f8a298decd5f0 (diff) | |
| download | progos-9b19a84ed640cb15e6ca87ddc025c90d78a5fbdc.tar.gz progos-9b19a84ed640cb15e6ca87ddc025c90d78a5fbdc.tar.bz2 progos-9b19a84ed640cb15e6ca87ddc025c90d78a5fbdc.zip | |
* fix possible race in thread_set_priority
* fill in same parts of proj1.txt
* use thread_get_priority() whenever possible
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 |
