kernel: Minor improvements, separate priority and yield logic
This commit is contained in:
@@ -120,42 +120,52 @@ dump_run_queue(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
simple_yield(Thread* thread)
|
|
||||||
{
|
|
||||||
TRACE("thread %ld yielded\n", thread->id);
|
|
||||||
sYieldedThreadPriority = max_c(sYieldedThreadPriority, thread->priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline int32
|
static inline int32
|
||||||
simple_get_effective_priority(Thread* thread)
|
simple_get_effective_priority(Thread* thread)
|
||||||
{
|
{
|
||||||
if (thread->priority == B_IDLE_PRIORITY)
|
if (thread->priority == B_IDLE_PRIORITY)
|
||||||
return thread->priority;
|
return thread->priority;
|
||||||
|
if (thread->priority >= B_FIRST_REAL_TIME_PRIORITY)
|
||||||
|
return thread->priority;
|
||||||
|
|
||||||
scheduler_thread_data* schedulerThreadData
|
scheduler_thread_data* schedulerThreadData
|
||||||
= reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data);
|
= reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data);
|
||||||
|
|
||||||
int32 effectivePriority = thread->priority;
|
int32 effectivePriority = thread->priority;
|
||||||
if (effectivePriority < B_FIRST_REAL_TIME_PRIORITY) {
|
effectivePriority -= schedulerThreadData->priority_penalty;
|
||||||
const int kYieldFrequency = 1 << (min_c(thread->priority, 25) / 5 + 1);
|
|
||||||
if (schedulerThreadData->forced_yield_count != 0
|
|
||||||
&& schedulerThreadData->forced_yield_count % kYieldFrequency == 0) {
|
|
||||||
TRACE("forcing thread %ld to yield\n", thread->id);
|
|
||||||
simple_yield(thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
effectivePriority -= schedulerThreadData->priority_penalty;
|
ASSERT(effectivePriority < B_FIRST_REAL_TIME_PRIORITY);
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(schedulerThreadData->priority_penalty >= 0);
|
|
||||||
ASSERT(effectivePriority >= B_LOWEST_ACTIVE_PRIORITY);
|
ASSERT(effectivePriority >= B_LOWEST_ACTIVE_PRIORITY);
|
||||||
|
|
||||||
return effectivePriority;
|
return effectivePriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
simple_yield(Thread* thread)
|
||||||
|
{
|
||||||
|
TRACE("thread %ld yielded\n", thread->id);
|
||||||
|
int32 effectivePriority = simple_get_effective_priority(thread);
|
||||||
|
sYieldedThreadPriority = max_c(sYieldedThreadPriority, effectivePriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
simple_should_force_yield(Thread* thread)
|
||||||
|
{
|
||||||
|
if (thread->priority >= B_FIRST_REAL_TIME_PRIORITY)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
scheduler_thread_data* schedulerThreadData
|
||||||
|
= reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data);
|
||||||
|
|
||||||
|
const int kYieldFrequency = 1 << (min_c(thread->priority, 25) / 5 + 1);
|
||||||
|
|
||||||
|
return schedulerThreadData->forced_yield_count != 0
|
||||||
|
&& schedulerThreadData->forced_yield_count % kYieldFrequency == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
simple_increase_penalty(Thread* thread)
|
simple_increase_penalty(Thread* thread)
|
||||||
{
|
{
|
||||||
@@ -186,9 +196,6 @@ simple_cancel_penalty(Thread* thread)
|
|||||||
scheduler_thread_data* schedulerThreadData
|
scheduler_thread_data* schedulerThreadData
|
||||||
= reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data);
|
= reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data);
|
||||||
|
|
||||||
if (schedulerThreadData->went_sleep < 0
|
|
||||||
|| system_time() - schedulerThreadData->went_sleep <= kThreadQuantum)
|
|
||||||
return;
|
|
||||||
if (schedulerThreadData->priority_penalty != 0)
|
if (schedulerThreadData->priority_penalty != 0)
|
||||||
TRACE("cancelling thread %ld penalty\n", thread->id);
|
TRACE("cancelling thread %ld penalty\n", thread->id);
|
||||||
schedulerThreadData->priority_penalty = 0;
|
schedulerThreadData->priority_penalty = 0;
|
||||||
@@ -196,22 +203,24 @@ simple_cancel_penalty(Thread* thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Enqueues the thread into the run queue.
|
|
||||||
Note: thread lock must be held when entering this function
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
simple_enqueue_in_run_queue(Thread* thread)
|
simple_enqueue(Thread* thread, bool newOne)
|
||||||
{
|
{
|
||||||
thread->state = thread->next_state = B_THREAD_READY;
|
thread->state = thread->next_state = B_THREAD_READY;
|
||||||
|
|
||||||
simple_cancel_penalty(thread);
|
scheduler_thread_data* schedulerThreadData
|
||||||
|
= reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data);
|
||||||
|
|
||||||
|
bigtime_t hasSlept = system_time() - schedulerThreadData->went_sleep;
|
||||||
|
if (newOne && hasSlept > kThreadQuantum)
|
||||||
|
simple_cancel_penalty(thread);
|
||||||
|
|
||||||
|
if (simple_should_force_yield(thread))
|
||||||
|
simple_yield(thread);
|
||||||
|
|
||||||
int32 threadPriority = simple_get_effective_priority(thread);
|
int32 threadPriority = simple_get_effective_priority(thread);
|
||||||
T(EnqueueThread(thread, threadPriority));
|
T(EnqueueThread(thread, threadPriority));
|
||||||
|
|
||||||
scheduler_thread_data* schedulerThreadData
|
|
||||||
= reinterpret_cast<scheduler_thread_data*>(thread->scheduler_data);
|
|
||||||
|
|
||||||
if (threadPriority <= sYieldedThreadPriority)
|
if (threadPriority <= sYieldedThreadPriority)
|
||||||
sExpiredQueue->PushBack(thread, threadPriority);
|
sExpiredQueue->PushBack(thread, threadPriority);
|
||||||
else
|
else
|
||||||
@@ -226,7 +235,7 @@ simple_enqueue_in_run_queue(Thread* thread)
|
|||||||
thread);
|
thread);
|
||||||
|
|
||||||
Thread* currentThread = thread_get_current_thread();
|
Thread* currentThread = thread_get_current_thread();
|
||||||
if (threadPriority > currentThread->priority) {
|
if (newOne && threadPriority > currentThread->priority) {
|
||||||
scheduler_thread_data* schedulerCurrentThreadData
|
scheduler_thread_data* schedulerCurrentThreadData
|
||||||
= reinterpret_cast<scheduler_thread_data*>(
|
= reinterpret_cast<scheduler_thread_data*>(
|
||||||
currentThread->scheduler_data);
|
currentThread->scheduler_data);
|
||||||
@@ -238,6 +247,16 @@ simple_enqueue_in_run_queue(Thread* thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Enqueues the thread into the run queue.
|
||||||
|
Note: thread lock must be held when entering this function
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
simple_enqueue_in_run_queue(Thread* thread)
|
||||||
|
{
|
||||||
|
simple_enqueue(thread, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Sets the priority of a thread.
|
/*! Sets the priority of a thread.
|
||||||
Note: thread lock must be held when entering this function
|
Note: thread lock must be held when entering this function
|
||||||
*/
|
*/
|
||||||
@@ -406,8 +425,6 @@ simple_reschedule(void)
|
|||||||
schedulerOldThreadData->cpu_bound = false;
|
schedulerOldThreadData->cpu_bound = false;
|
||||||
|
|
||||||
if (simple_quantum_ended(oldThread, oldThread->cpu->preempted)) {
|
if (simple_quantum_ended(oldThread, oldThread->cpu->preempted)) {
|
||||||
schedulerOldThreadData->went_sleep = -1;
|
|
||||||
|
|
||||||
if (schedulerOldThreadData->cpu_bound)
|
if (schedulerOldThreadData->cpu_bound)
|
||||||
simple_increase_penalty(oldThread);
|
simple_increase_penalty(oldThread);
|
||||||
else
|
else
|
||||||
@@ -415,11 +432,10 @@ simple_reschedule(void)
|
|||||||
|
|
||||||
if (oldThread->was_yielded)
|
if (oldThread->was_yielded)
|
||||||
simple_yield(oldThread);
|
simple_yield(oldThread);
|
||||||
oldThread->was_yielded = false;
|
|
||||||
|
|
||||||
TRACE("enqueueing thread %ld into run queue priority = %ld\n",
|
TRACE("enqueueing thread %ld into run queue priority = %ld\n",
|
||||||
oldThread->id, simple_get_effective_priority(oldThread));
|
oldThread->id, simple_get_effective_priority(oldThread));
|
||||||
simple_enqueue_in_run_queue(oldThread);
|
simple_enqueue(oldThread, false);
|
||||||
} else {
|
} else {
|
||||||
TRACE("putting thread %ld back in run queue priority = %ld\n",
|
TRACE("putting thread %ld back in run queue priority = %ld\n",
|
||||||
oldThread->id, simple_get_effective_priority(oldThread));
|
oldThread->id, simple_get_effective_priority(oldThread));
|
||||||
@@ -441,6 +457,7 @@ simple_reschedule(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldThread->was_yielded = false;
|
||||||
schedulerOldThreadData->lost_cpu = false;
|
schedulerOldThreadData->lost_cpu = false;
|
||||||
|
|
||||||
// select thread with the biggest priority
|
// select thread with the biggest priority
|
||||||
@@ -449,6 +466,8 @@ simple_reschedule(void)
|
|||||||
panic("reschedule(): run queues are empty!\n");
|
panic("reschedule(): run queues are empty!\n");
|
||||||
sRunQueue->Remove(nextThread);
|
sRunQueue->Remove(nextThread);
|
||||||
|
|
||||||
|
TRACE("reschedule(): next thread = %ld\n", nextThread->id);
|
||||||
|
|
||||||
T(ScheduleThread(nextThread, oldThread));
|
T(ScheduleThread(nextThread, oldThread));
|
||||||
|
|
||||||
// notify listeners
|
// notify listeners
|
||||||
|
|||||||
Reference in New Issue
Block a user