From 9b19a84ed640cb15e6ca87ddc025c90d78a5fbdc Mon Sep 17 00:00:00 2001 From: manuel Date: Fri, 11 May 2012 20:48:58 +0200 Subject: * fix possible race in thread_set_priority * fill in same parts of proj1.txt * use thread_get_priority() whenever possible --- threads/thread.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'threads/thread.c') 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) void thread_other_set_priority (struct thread *t, int new_priority) { + enum intr_level old_level; + bool yield = false; + ASSERT (is_thread (t)); ASSERT (new_priority >= PRI_MIN && new_priority <= PRI_MAX); if (t->priority == new_priority) return; + /* we need to disable interrupts here because after changing the thread's + priority and a possible timer interrupt which triggers thread_yield() we + could run into a couple of races. e.g. no proper sorted ready list, + corrupt ready list (wrong internal pointers) or the timer interrupt fires + after calling list_empty() but before list_front() while having only two + threads (one active, the other one ready). the scheduler then schedules the + other thread which runs and terminates, thus removing itself from all lists. + after that our thread gets scheduled again and reads from an empty list, + although it wasn't empty before. */ + old_level = intr_disable (); + t->priority = new_priority; if (t->status == THREAD_READY) @@ -398,8 +412,13 @@ thread_other_set_priority (struct thread *t, int new_priority) /* compare priority with the highest priority in the list */ struct thread *t2 = list_entry (list_front (&ready_list), struct thread, elem); if (t2->priority > t->priority) - thread_yield (); + yield = true; } + + intr_set_level (old_level); + + if (yield) + thread_yield (); } void -- cgit v1.2.3