1

add vorgabe09

This commit is contained in:
2022-07-04 16:17:39 +02:00
parent 586fe3bb80
commit da6c5ab0b5
13 changed files with 231 additions and 40 deletions

View File

@ -17,9 +17,11 @@ Keyboard kb; // Tastatur
IntDispatcher intdis; // Unterbrechungsverteilung
PIC pic; // Interrupt-Controller
unsigned int total_mem; // RAM total
unsigned long systime = 0;
// BumpAllocator allocator;
// LinkedListAllocator allocator;
TreeAllocator allocator;
Scheduler scheduler;
BIOS bios; // Schnittstelle zum 16-Bit BIOS
VESA vesa; // VESA-Treiber
PIT pit(10000);

View File

@ -22,6 +22,7 @@
#include "kernel/interrupts/IntDispatcher.h"
#include "kernel/interrupts/PIC.h"
#include "kernel/threads/Scheduler.h"
#include "devices/PIT.h"
extern CPU cpu; // CPU-spezifische Funktionen
extern PCSPK pcspk; // PC-Lautsprecher
@ -29,7 +30,9 @@ extern CGA_Stream kout; // Ausgabe-Strom fuer Kernel
extern Keyboard kb; // Tastatur
extern IntDispatcher intdis; // Unterbrechungsverteilung
extern PIC pic; // Interrupt-Controller
extern PIT pit; // Zeitgeber
extern unsigned int total_mem; // RAM total
extern unsigned long systime; // wird all 10ms hochgezaehlt
// extern BumpAllocator allocator;
// extern LinkedListAllocator allocator;
extern TreeAllocator allocator;

View File

@ -22,6 +22,9 @@ public:
IdleThread() {}
void run() override {
// Idle-Thread läuft, ab jetzt ist der Scheduler fertig initialisiert
scheduler.setInitialized();
while (true) {
scheduler.yield();
// kout << "Idle!" << endl;

View File

@ -22,7 +22,8 @@ void Scheduler::schedule() {
/* hier muss Code eingefuegt werden */
Thread* idle = new IdleThread();
this->readyQueue.enqueue(idle);
// this->readyQueue.enqueue(idle);
this->ready(idle);
/* Bevor diese Methode anufgerufen wird, muss zumindest der Idle-Thread
* in der Queue eingefuegt worden sein.
@ -44,7 +45,13 @@ void Scheduler::ready(Thread* that) {
/* hier muss Code eingefuegt werden */
// Thread-Wechsel durch PIT verhindern
cpu.disable_int ();
this->readyQueue.enqueue(that);
// Thread-Wechsel durch PIT jetzt wieder erlauben
cpu.enable_int ();
}
/*****************************************************************************
@ -59,8 +66,14 @@ void Scheduler::exit() {
/* hier muss Code eingefuegt werden */
// Thread-Wechsel durch PIT verhindern
cpu.disable_int ();
Thread& next = *(Thread*)this->readyQueue.dequeue();
this->dispatch(next);
// Interrupts werden in Thread_switch in Thread.asm wieder zugelassen
// dispatch kehr nicht zurueck
}
/*****************************************************************************
@ -78,7 +91,13 @@ void Scheduler::kill(Thread* that) {
/* hier muss Code eingefuegt werden */
// Thread-Wechsel durch PIT verhindern
cpu.disable_int ();
this->readyQueue.remove(that);
// Thread-Wechsel durch PIT jetzt wieder erlauben
cpu.enable_int ();
}
/*****************************************************************************
@ -96,6 +115,9 @@ void Scheduler::yield() {
/* hier muss Code eingefuegt werden */
// Thread-Wechsel durch PIT verhindern
cpu.disable_int ();
// When only one thread exists (IdleThread) it can't yield as the readyqueue becomes empty
// and this is not handled anywhere else
if (this->readyQueue.isEmpty()) {
@ -106,4 +128,20 @@ void Scheduler::yield() {
Thread& next = *(Thread*)this->readyQueue.dequeue();
this->readyQueue.enqueue(this->get_active());
this->dispatch(next);
// Thread-Wechsel durch PIT jetzt wieder erlauben
cpu.enable_int ();
}
/*****************************************************************************
* Methode: Scheduler::preempt *
*---------------------------------------------------------------------------*
* Beschreibung: Diese Funktion wird aus der ISR des PITs aufgerufen und *
* schaltet auf den naechsten Thread um, sofern einer vor- *
* handen ist. *
*****************************************************************************/
void Scheduler::preempt () {
/* Hier muss Code eingefuegt werden */
}

View File

@ -22,8 +22,20 @@ private:
Queue readyQueue; // auf die CPU wartende Threads
// Scheduler wird evt. von einer Unterbrechung vom Zeitgeber gerufen,
// bevor er initialisiert wurde
bool initialized;
public:
Scheduler() {}
Scheduler() : initialized(false) {}
// Scheduler initialisiert?
// Zeitgeber-Unterbrechung kommt evt. bevor der Scheduler fertig
// intiialisiert wurde!
bool isInitialized() { return initialized; }
// ruft nur der Idle-Thread (erster Thread der vom Scheduler gestartet wird)
void setInitialized() { initialized = true; }
// Scheduler starten
void schedule();
@ -39,6 +51,10 @@ public:
// CPU freiwillig abgeben und Auswahl des naechsten Threads
void yield();
// Thread umschalten; wird aus der ISR des PITs gerufen
void preempt ();
};
#endif

View File

@ -70,6 +70,15 @@ void Thread_init(struct ThreadState* regs, unsigned int* stack, void (*kickoff)(
regs->edi = 0;
regs->ebp = 0;
regs->esp = sp; // esp now points to the location of the address of kickoff
// nachfolgend die fluechtige Register
// wichtig fuer preemptives Multitasking
regs->eax = 0;
regs->ecx = 0;
regs->edx = 0;
// flags initialisieren
regs->efl = (void*)0x200; // Interrupt-Enable
}
/*****************************************************************************

View File

@ -15,6 +15,13 @@
* ThreadState, in dem die Werte der nicht-fluechtigen *
* Register gesichert werden koennen. *
* *
* Zusaetzlich zum vorhandenen freiwilligen Umschalten der *
* CPU mit 'Thread_switch' gibt es nun ein forciertes Um- *
* durch den Zeitgeber-Interrupt ausgeloest wird und in *
* Assembler in startup.asm implementiert ist. Fuer das *
* Zusammenspiel mit dem Scheduler ist die Methode *
* 'prepare_preemption' in Scheduler.cc wichtig. *
* *
* Autor: Michael, Schoettner, HHU, 16.12.2016 *
*****************************************************************************/

View File

@ -24,3 +24,7 @@ esi_offset: resd 1
edi_offset: resd 1
ebp_offset: resd 1
esp_offset: resd 1
eax_offset: resd 1
ecx_offset: resd 1
edx_offset: resd 1
efl_offset: resd 1

View File

@ -34,6 +34,12 @@ struct ThreadState {
void* edi;
void* ebp;
void* esp;
// nachfolgend die fluechtige Register
// wichtig fuer preemptives Multitasking
void *eax;
void *ecx;
void *edx;
void *efl;
};
#endif