From 21808e8f0bf71d342e572e9980119c0a5dc24ec6 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Tue, 8 Oct 2013 02:54:58 +0200 Subject: [PATCH] kernel: Limit maximum priority penalty The maximum penalty the thread can receive is now limited depending on the real thread priority. However, since it make it possible to starve threads with priority lower than that limit. To prevent that threads that have already earned the maximum penalty are periodically forced to yield CPU to all other threads. --- .../kernel/scheduler/scheduler_simple.cpp | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index 417e90843a..461c601f52 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -51,6 +51,8 @@ struct scheduler_thread_data { void Init(); int32 priority_penalty; + int32 forced_yield_count; + bool lost_cpu; bool cpu_bound; @@ -64,6 +66,8 @@ void scheduler_thread_data::Init() { priority_penalty = 0; + forced_yield_count = 0; + time_left = 0; stolen_time = 0; @@ -107,8 +111,14 @@ simple_get_effective_priority(Thread *thread) = reinterpret_cast(thread->scheduler_data); int32 effectivePriority = thread->priority; - if (effectivePriority < B_FIRST_REAL_TIME_PRIORITY) - effectivePriority -= schedulerThreadData->priority_penalty; + if (effectivePriority < B_FIRST_REAL_TIME_PRIORITY) { + if (schedulerThreadData->forced_yield_count + && schedulerThreadData->forced_yield_count % 16 == 0) { + TRACE("forcing thread %ld to yield\n", thread->id); + effectivePriority = B_LOWEST_ACTIVE_PRIORITY; + } else + effectivePriority -= schedulerThreadData->priority_penalty; + } ASSERT(schedulerThreadData->priority_penalty >= 0); ASSERT(effectivePriority >= B_LOWEST_ACTIVE_PRIORITY); @@ -132,8 +142,12 @@ simple_increase_penalty(Thread *thread) int32 oldPenalty = schedulerThreadData->priority_penalty++; ASSERT(thread->priority - oldPenalty >= B_LOWEST_ACTIVE_PRIORITY); - if (thread->priority - oldPenalty <= B_LOWEST_ACTIVE_PRIORITY) + const int kMinimalPriority + = min_c(thread->priority, 25) / 5; + if (thread->priority - oldPenalty <= kMinimalPriority) { schedulerThreadData->priority_penalty = oldPenalty; + schedulerThreadData->forced_yield_count++; + } }