kernel: Use the new runqueue in non-MP scheduler

This commit is contained in:
Pawel Dziepak
2013-10-05 20:22:59 +02:00
parent b8c1df9b00
commit 9ad558f01c
@@ -1,4 +1,5 @@
/* /*
* Copyright 2013, Paweł Dziepak, [email protected]
* Copyright 2008-2011, Ingo Weinhold, [email protected]. * Copyright 2008-2011, Ingo Weinhold, [email protected].
* Copyright 2002-2010, Axel Dörfler, [email protected]. * Copyright 2002-2010, Axel Dörfler, [email protected].
* Copyright 2002, Angelo Mottola, [email protected]. * Copyright 2002, Angelo Mottola, [email protected].
@@ -25,6 +26,7 @@
#include <timer.h> #include <timer.h>
#include <util/Random.h> #include <util/Random.h>
#include "RunQueue.h"
#include "scheduler_common.h" #include "scheduler_common.h"
#include "scheduler_tracing.h" #include "scheduler_tracing.h"
@@ -41,23 +43,23 @@ const bigtime_t kThreadQuantum = 3000;
// The run queue. Holds the threads ready to run ordered by priority. // The run queue. Holds the threads ready to run ordered by priority.
static Thread *sRunQueue = NULL; static RunQueue<Thread, THREAD_MAX_SET_PRIORITY>* sRunQueue;
static int static int
dump_run_queue(int argc, char **argv) dump_run_queue(int argc, char **argv)
{ {
Thread *thread; RunQueue<Thread, THREAD_MAX_SET_PRIORITY>::ConstIterator iterator;
iterator = sRunQueue->GetConstIterator();
thread = sRunQueue; if (!iterator.HasNext())
if (!thread)
kprintf("Run queue is empty!\n"); kprintf("Run queue is empty!\n");
else { else {
kprintf("thread id priority name\n"); kprintf("thread id priority name\n");
while (thread) { while (iterator.HasNext()) {
Thread *thread = iterator.Next();
kprintf("%p %-7" B_PRId32 " %-8" B_PRId32 " %s\n", thread, kprintf("%p %-7" B_PRId32 " %-8" B_PRId32 " %s\n", thread,
thread->id, thread->priority, thread->name); thread->id, thread->priority, thread->name);
thread = thread->queue_next;
} }
} }
@@ -73,24 +75,9 @@ simple_enqueue_in_run_queue(Thread *thread)
{ {
thread->state = thread->next_state = B_THREAD_READY; thread->state = thread->next_state = B_THREAD_READY;
Thread *curr, *prev; //T(EnqueueThread(thread, prev, curr));
for (curr = sRunQueue, prev = NULL; curr
&& curr->priority >= thread->next_priority;
curr = curr->queue_next) {
if (prev)
prev = prev->queue_next;
else
prev = sRunQueue;
}
T(EnqueueThread(thread, prev, curr));
thread->queue_next = curr;
if (prev)
prev->queue_next = thread;
else
sRunQueue = thread;
sRunQueue->PushBack(thread, thread->next_priority);
thread->next_priority = thread->priority; thread->next_priority = thread->priority;
// notify listeners // notify listeners
@@ -127,23 +114,8 @@ simple_set_thread_priority(Thread *thread, int32 priority)
NotifySchedulerListeners(&SchedulerListener::ThreadRemovedFromRunQueue, NotifySchedulerListeners(&SchedulerListener::ThreadRemovedFromRunQueue,
thread); thread);
// find thread in run queue // remove thread from run queue
Thread *item, *prev; sRunQueue->Remove(thread);
for (item = sRunQueue, prev = NULL; item && item != thread;
item = item->queue_next) {
if (prev)
prev = prev->queue_next;
else
prev = sRunQueue;
}
ASSERT(item == thread);
// remove the thread
if (prev)
prev->queue_next = item->queue_next;
else
sRunQueue = item->queue_next;
// set priority and re-insert // set priority and re-insert
thread->priority = thread->next_priority = priority; thread->priority = thread->next_priority = priority;
@@ -185,8 +157,8 @@ reschedule_event(timer *unused)
static void static void
simple_reschedule(void) simple_reschedule(void)
{ {
Thread *oldThread = thread_get_current_thread(); Thread* oldThread = thread_get_current_thread();
Thread *nextThread, *prevThread; Thread* nextThread;
// check whether we're only supposed to reschedule, if the current thread // check whether we're only supposed to reschedule, if the current thread
// is idle // is idle
@@ -220,64 +192,48 @@ simple_reschedule(void)
break; break;
} }
nextThread = sRunQueue; while (true) {
prevThread = NULL; // select thread with the biggest priority
nextThread = sRunQueue->PeekMaximum();
if (!nextThread)
panic("reschedule(): run queue is empty!\n");
while (nextThread) {
// select next thread from the run queue
while (nextThread && nextThread->priority > B_IDLE_PRIORITY) {
#if 0 #if 0
if (oldThread == nextThread && nextThread->was_yielded) { if (oldThread == nextThread && nextThread->was_yielded) {
// ignore threads that called thread_yield() once // ignore threads that called thread_yield() once
nextThread->was_yielded = false; nextThread->was_yielded = false;
prevThread = nextThread; prevThread = nextThread;
nextThread = nextThread->queue_next; nextThread = nextThread->queue_next;
} }
#endif #endif
// always extract real time threads // always extract real time threads
if (nextThread->priority >= B_FIRST_REAL_TIME_PRIORITY) if (nextThread->priority >= B_FIRST_REAL_TIME_PRIORITY)
break; break;
// find next thread with lower priority // find thread with the second biggest priority
Thread *lowerNextThread = nextThread->queue_next; Thread* lowerNextThread = sRunQueue->PeekSecondMaximum();
Thread *lowerPrevThread = nextThread;
int32 priority = nextThread->priority;
while (lowerNextThread != NULL // never skip last non-idle normal thread
&& priority == lowerNextThread->priority) { if (lowerNextThread == NULL
lowerPrevThread = lowerNextThread; || lowerNextThread->priority == B_IDLE_PRIORITY)
lowerNextThread = lowerNextThread->queue_next; break;
}
// never skip last non-idle normal thread
if (lowerNextThread == NULL
|| lowerNextThread->priority == B_IDLE_PRIORITY)
break;
int32 priorityDiff = priority - lowerNextThread->priority; int32 priorityDiff = nextThread->priority - lowerNextThread->priority;
if (priorityDiff > 15) if (priorityDiff > 15)
break; break;
// skip normal threads sometimes // skip normal threads sometimes
// (twice as probable per priority level) // (twice as probable per priority level)
if ((fast_random_value() >> (15 - priorityDiff)) != 0) if ((fast_random_value() >> (15 - priorityDiff)) != 0)
break; break;
nextThread = lowerNextThread; nextThread = lowerNextThread;
prevThread = lowerPrevThread;
}
break; break;
} }
if (!nextThread) sRunQueue->Remove(nextThread);
panic("reschedule(): run queue is empty!\n");
// extract selected thread from the run queue
if (prevThread)
prevThread->queue_next = nextThread->queue_next;
else
sRunQueue = nextThread->queue_next;
T(ScheduleThread(nextThread, oldThread)); T(ScheduleThread(nextThread, oldThread));
@@ -375,6 +331,8 @@ static scheduler_ops kSimpleOps = {
void void
scheduler_simple_init() scheduler_simple_init()
{ {
sRunQueue = new(std::nothrow) RunQueue<Thread, THREAD_MAX_SET_PRIORITY>;
gScheduler = &kSimpleOps; gScheduler = &kSimpleOps;
add_debugger_command_etc("run_queue", &dump_run_queue, add_debugger_command_etc("run_queue", &dump_run_queue,