From 547b8c76c718b46174dbac0ae37d3ad6b9d803b5 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Tue, 8 Oct 2013 04:50:23 +0200 Subject: [PATCH] kernel: Cancel penalty only if the thread actually waits Require the thread to give up CPU for at least one time slice before cancelling its penalty. --- .../kernel/scheduler/scheduler_simple.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index 461c601f52..c8517b64e1 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -59,6 +59,8 @@ struct scheduler_thread_data { bigtime_t time_left; bigtime_t stolen_time; bigtime_t quantum_start; + + bigtime_t went_sleep; }; @@ -71,6 +73,8 @@ scheduler_thread_data::Init() time_left = 0; stolen_time = 0; + went_sleep = 0; + lost_cpu = false; cpu_bound = true; } @@ -156,9 +160,14 @@ simple_cancel_penalty(Thread *thread) { scheduler_thread_data* schedulerThreadData = reinterpret_cast(thread->scheduler_data); + + if (schedulerThreadData->went_sleep < 0 + || system_time() - schedulerThreadData->went_sleep <= kThreadQuantum) + return; if (schedulerThreadData->priority_penalty != 0) TRACE("cancelling thread %ld penalty\n", thread->id); schedulerThreadData->priority_penalty = 0; + schedulerThreadData->forced_yield_count = 0; } @@ -170,6 +179,8 @@ simple_enqueue_in_run_queue(Thread *thread) { thread->state = thread->next_state = B_THREAD_READY; + simple_cancel_penalty(thread); + int32 threadPriority = simple_get_effective_priority(thread); T(EnqueueThread(thread, threadPriority)); @@ -339,6 +350,8 @@ simple_reschedule(void) schedulerOldThreadData->cpu_bound = false; if (simple_quantum_ended(oldThread, oldThread->cpu->preempted)) { + schedulerOldThreadData->went_sleep = -1; + if (schedulerOldThreadData->cpu_bound) simple_increase_penalty(oldThread); else @@ -356,13 +369,13 @@ simple_reschedule(void) break; case B_THREAD_SUSPENDED: - simple_cancel_penalty(oldThread); + schedulerOldThreadData->went_sleep = system_time(); TRACE("reschedule(): suspending thread %ld\n", oldThread->id); break; case THREAD_STATE_FREE_ON_RESCHED: break; default: - simple_cancel_penalty(oldThread); + schedulerOldThreadData->went_sleep = system_time(); TRACE("not enqueueing thread %ld into run queue next_state = %ld\n", oldThread->id, oldThread->next_state); break;