merge dispatcher into scheduler
This commit is contained in:
@ -1,46 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* *
|
|
||||||
* D I S P A T C H E R *
|
|
||||||
* *
|
|
||||||
*---------------------------------------------------------------------------*
|
|
||||||
* Beschreibung: Implementierung des Dispatchers. *
|
|
||||||
* Der Dispatcher verwaltet den 'active'-Pointer, der den *
|
|
||||||
* jeweils aktiven Thread angibt. Mit 'start()' wird der *
|
|
||||||
* 'active' Pointer initialisiert und der erste Thread ge- *
|
|
||||||
* startet, alle weiteren Kontextwechsel werden mit *
|
|
||||||
* 'dispatch()' ausgeloest. 'get_active()' liefert den *
|
|
||||||
* 'active' Pointer zurueck. *
|
|
||||||
* *
|
|
||||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include "kernel/threads/Dispatch.h"
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* Methode: Dispatcher::start *
|
|
||||||
*---------------------------------------------------------------------------*
|
|
||||||
* Beschreibung: Thread starten. *
|
|
||||||
* *
|
|
||||||
* Parameter: *
|
|
||||||
* first Zu startender Thread. *
|
|
||||||
*****************************************************************************/
|
|
||||||
void Dispatcher::start(Thread& first) {
|
|
||||||
if (!active) {
|
|
||||||
active = &first;
|
|
||||||
active->start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* Methode: Dispatcher::dispatch *
|
|
||||||
*---------------------------------------------------------------------------*
|
|
||||||
* Beschreibung: Auf einen gegebenen Thread wechseln. *
|
|
||||||
* *
|
|
||||||
* Parameter: *
|
|
||||||
* next Thread der die CPU erhalten soll. *
|
|
||||||
*****************************************************************************/
|
|
||||||
void Dispatcher::dispatch(Thread& next) {
|
|
||||||
Thread* current = active;
|
|
||||||
active = &next;
|
|
||||||
current->switchTo(next);
|
|
||||||
}
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* *
|
|
||||||
* D I S P A T C H E R *
|
|
||||||
* *
|
|
||||||
*---------------------------------------------------------------------------*
|
|
||||||
* Beschreibung: Implementierung des Dispatchers. *
|
|
||||||
* Der Dispatcher verwaltet den 'active'-Pointer, der den *
|
|
||||||
* jeweils aktiven Thread angibt. Mit 'start()' wird der *
|
|
||||||
* 'active' Pointer initialisiert und der erste Thread ge- *
|
|
||||||
* startet, alle weiteren Kontextwechsel werden mit *
|
|
||||||
* 'dispatch()' ausgeloest. 'get_active()' liefert den *
|
|
||||||
* 'active' Pointer zurueck. *
|
|
||||||
* *
|
|
||||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
|
||||||
*****************************************************************************/
|
|
||||||
#ifndef __dispatch_include__
|
|
||||||
#define __dispatch_include__
|
|
||||||
|
|
||||||
#include "kernel/threads/Thread.h"
|
|
||||||
|
|
||||||
class Dispatcher {
|
|
||||||
private:
|
|
||||||
Thread* active; // aktiver Thread
|
|
||||||
|
|
||||||
Dispatcher(const Dispatcher& copy) = delete; // Verhindere Kopieren
|
|
||||||
|
|
||||||
public:
|
|
||||||
Dispatcher() : active(0) {}
|
|
||||||
void start(Thread& first);
|
|
||||||
void dispatch(Thread& next);
|
|
||||||
Thread* get_active() { return active; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -24,6 +24,35 @@
|
|||||||
#include "kernel/threads/Scheduler.h"
|
#include "kernel/threads/Scheduler.h"
|
||||||
#include "kernel/threads/IdleThread.h"
|
#include "kernel/threads/IdleThread.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Methode: Dispatcher::start *
|
||||||
|
*---------------------------------------------------------------------------*
|
||||||
|
* Beschreibung: Thread starten. *
|
||||||
|
* *
|
||||||
|
* Parameter: *
|
||||||
|
* first Zu startender Thread. *
|
||||||
|
*****************************************************************************/
|
||||||
|
void Scheduler::start(Thread& first) {
|
||||||
|
if (active == nullptr) {
|
||||||
|
active = &first;
|
||||||
|
active->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Methode: Dispatcher::dispatch *
|
||||||
|
*---------------------------------------------------------------------------*
|
||||||
|
* Beschreibung: Auf einen gegebenen Thread wechseln. *
|
||||||
|
* *
|
||||||
|
* Parameter: *
|
||||||
|
* next Thread der die CPU erhalten soll. *
|
||||||
|
*****************************************************************************/
|
||||||
|
void Scheduler::dispatch(Thread& next) {
|
||||||
|
Thread* current = active;
|
||||||
|
active = &next;
|
||||||
|
current->switchTo(next);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Methode: Scheduler::schedule *
|
* Methode: Scheduler::schedule *
|
||||||
*---------------------------------------------------------------------------*
|
*---------------------------------------------------------------------------*
|
||||||
@ -75,14 +104,14 @@ void Scheduler::exit() {
|
|||||||
// Thread-Wechsel durch PIT verhindern
|
// Thread-Wechsel durch PIT verhindern
|
||||||
cpu.disable_int();
|
cpu.disable_int();
|
||||||
if (this->ready_queue.empty()) {
|
if (this->ready_queue.empty()) {
|
||||||
log << ERROR << "Can't exit last thread, active ID: " << dec << this->get_active()->tid << endl;
|
log << ERROR << "Can't exit last thread, active ID: " << dec << this->active->tid << endl;
|
||||||
cpu.enable_int();
|
cpu.enable_int();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Thread& next = *(Thread*)this->ready_queue.remove_first();
|
Thread& next = *(Thread*)this->ready_queue.remove_first();
|
||||||
|
|
||||||
log << DEBUG << "Exiting thread, ID: " << dec << this->get_active()->tid << " => " << next.tid << endl;
|
log << DEBUG << "Exiting thread, ID: " << dec << this->active->tid << " => " << next.tid << endl;
|
||||||
delete this->get_active();
|
delete this->active;
|
||||||
|
|
||||||
this->dispatch(next);
|
this->dispatch(next);
|
||||||
|
|
||||||
@ -169,15 +198,15 @@ void Scheduler::yield() {
|
|||||||
// Thread-Wechsel durch PIT verhindern
|
// Thread-Wechsel durch PIT verhindern
|
||||||
cpu.disable_int();
|
cpu.disable_int();
|
||||||
if (this->ready_queue.empty()) {
|
if (this->ready_queue.empty()) {
|
||||||
// log << TRACE << "Skipping yield as no thread is waiting, active ID: " << dec << this->get_active()->tid << endl;
|
// log << TRACE << "Skipping yield as no thread is waiting, active ID: " << dec << this->active->tid << endl;
|
||||||
cpu.enable_int();
|
cpu.enable_int();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread& next = *(Thread*)this->ready_queue.remove_first();
|
Thread& next = *(Thread*)this->ready_queue.remove_first();
|
||||||
this->ready_queue.insert_last(this->get_active());
|
this->ready_queue.insert_last(this->active);
|
||||||
|
|
||||||
// log << TRACE << "Yielding, ID: " << dec << this->get_active()->tid << " => " << next.tid << endl;
|
// log << TRACE << "Yielding, ID: " << dec << this->active->tid << " => " << next.tid << endl;
|
||||||
|
|
||||||
this->dispatch(next);
|
this->dispatch(next);
|
||||||
}
|
}
|
||||||
@ -215,15 +244,15 @@ void Scheduler::block() {
|
|||||||
|
|
||||||
cpu.disable_int();
|
cpu.disable_int();
|
||||||
if (this->ready_queue.empty()) {
|
if (this->ready_queue.empty()) {
|
||||||
log << ERROR << "Can't block last thread, active ID: " << dec << this->get_active()->tid << endl;
|
log << ERROR << "Can't block last thread, active ID: " << dec << this->active->tid << endl;
|
||||||
cpu.enable_int();
|
cpu.enable_int();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->block_queue.insert_last(this->get_active()); // Thread that will be blocked waits in block_queue, so the scheduler can also
|
this->block_queue.insert_last(this->active); // Thread that will be blocked waits in block_queue, so the scheduler can also
|
||||||
// kill blocked threads (for example keyboard demo needs this)
|
// kill blocked threads (for example keyboard demo needs this)
|
||||||
Thread& next = *(Thread*)this->ready_queue.remove_first();
|
Thread& next = *(Thread*)this->ready_queue.remove_first();
|
||||||
log << TRACE << "Blocking thread, ID: " << dec << this->get_active()->tid << " => " << next.tid << endl;
|
log << TRACE << "Blocking thread, ID: " << dec << this->active->tid << " => " << next.tid << endl;
|
||||||
|
|
||||||
this->dispatch(next);
|
this->dispatch(next);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,14 +13,13 @@
|
|||||||
#define __Scheduler_include__
|
#define __Scheduler_include__
|
||||||
|
|
||||||
#include "devices/CGA_Stream.h"
|
#include "devices/CGA_Stream.h"
|
||||||
#include "kernel/threads/Dispatch.h"
|
|
||||||
#include "kernel/threads/Thread.h"
|
#include "kernel/threads/Thread.h"
|
||||||
#include "lib/Queue.h"
|
#include "lib/Queue.h"
|
||||||
#include "lib/SpinLock.h"
|
#include "lib/SpinLock.h"
|
||||||
#include "user/lib/ArrayList.h"
|
#include "user/lib/ArrayList.h"
|
||||||
#include "user/lib/Logger.h"
|
#include "user/lib/Logger.h"
|
||||||
|
|
||||||
class Scheduler : public Dispatcher {
|
class Scheduler {
|
||||||
private:
|
private:
|
||||||
Scheduler(const Scheduler& copy) = delete; // Verhindere Kopieren
|
Scheduler(const Scheduler& copy) = delete; // Verhindere Kopieren
|
||||||
|
|
||||||
@ -28,6 +27,7 @@ private:
|
|||||||
|
|
||||||
// Scheduler wird evt. von einer Unterbrechung vom Zeitgeber gerufen,
|
// Scheduler wird evt. von einer Unterbrechung vom Zeitgeber gerufen,
|
||||||
// bevor er initialisiert wurde
|
// bevor er initialisiert wurde
|
||||||
|
Thread* active;
|
||||||
bool has_idle_thread;
|
bool has_idle_thread;
|
||||||
|
|
||||||
Logger log;
|
Logger log;
|
||||||
@ -42,9 +42,16 @@ private:
|
|||||||
ArrayList<Thread*> ready_queue;
|
ArrayList<Thread*> ready_queue;
|
||||||
ArrayList<Thread*> block_queue;
|
ArrayList<Thread*> block_queue;
|
||||||
|
|
||||||
|
void start(Thread& first);
|
||||||
|
void dispatch(Thread& next);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Scheduler() : has_idle_thread(false), log("SCHED") {}
|
Scheduler() : has_idle_thread(false), log("SCHED") {}
|
||||||
|
|
||||||
|
Thread* get_active() const {
|
||||||
|
return this->active;
|
||||||
|
}
|
||||||
|
|
||||||
// Scheduler initialisiert?
|
// Scheduler initialisiert?
|
||||||
// Zeitgeber-Unterbrechung kommt evt. bevor der Scheduler fertig
|
// Zeitgeber-Unterbrechung kommt evt. bevor der Scheduler fertig
|
||||||
// intiialisiert wurde!
|
// intiialisiert wurde!
|
||||||
|
|||||||
Reference in New Issue
Block a user