add vorgabe05
This commit is contained in:
51
c_os/kernel/corouts/Coroutine.asm
Executable file
51
c_os/kernel/corouts/Coroutine.asm
Executable file
@ -0,0 +1,51 @@
|
||||
;*****************************************************************************
|
||||
;* *
|
||||
;* C O R O U T I N E *
|
||||
;* *
|
||||
;*---------------------------------------------------------------------------*
|
||||
;* Beschreibung: Assemblerdarstellung der 'struct CoroutineState' aus *
|
||||
;* CoroutineState.h *
|
||||
;* *
|
||||
;* Die Reihenfolge der Registerbezeichnungen muss unbedingt *
|
||||
;* mit der von 'struct CoroutineState' uebereinstimmen. *
|
||||
;* *
|
||||
;* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
;*****************************************************************************
|
||||
|
||||
%include "kernel/corouts/Coroutine.inc"
|
||||
|
||||
; EXPORTIERTE FUNKTIONEN
|
||||
|
||||
[GLOBAL Coroutine_switch]
|
||||
[GLOBAL Coroutine_start]
|
||||
|
||||
; IMPLEMENTIERUNG DER FUNKTIONEN
|
||||
|
||||
[SECTION .text]
|
||||
|
||||
; COROUTINE_START : Startet die erste Coroutine ueberhaupt.
|
||||
;
|
||||
; C Prototyp: void Coroutine_start (struct CoroutineState* regs);
|
||||
|
||||
Coroutine_start:
|
||||
|
||||
; *
|
||||
; * Hier muss Code eingefuegt werden
|
||||
; *
|
||||
|
||||
|
||||
; COROUTINE_SWITCH : Coroutinenumschaltung. Der aktuelle Registersatz wird
|
||||
; gesichert und der Registersatz der neuen Coroutine
|
||||
; wird in den Prozessor eingelesen.
|
||||
;
|
||||
; C Prototyp: void Coroutine_switch (struct CoroutineState* regs_now,
|
||||
; struct CoroutineState* reg_then);
|
||||
;
|
||||
; Achtung: Die Parameter werden von rechts nach links uebergeben.
|
||||
;
|
||||
Coroutine_switch:
|
||||
|
||||
; *
|
||||
; * Hier muss Code eingefuegt werden
|
||||
; *
|
||||
|
130
c_os/kernel/corouts/Coroutine.cc
Executable file
130
c_os/kernel/corouts/Coroutine.cc
Executable file
@ -0,0 +1,130 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C O R O U T I N E *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Implementierung eines Koroutinen-Konzepts. *
|
||||
* Die Koroutinen sind miteinander verkettet, weswegen die *
|
||||
* Klasse Coroutine ein Subtyp von 'Chain' ist. *
|
||||
* *
|
||||
* Im Konstruktor wird der initialie Kontext der Koroutine *
|
||||
* eingerichtet. Mit 'start' wird ein Koroutine aktiviert. *
|
||||
* Das Umschalten auf die naechste Koroutine erfolgt durch *
|
||||
* Aufruf von 'switchToNext'. *
|
||||
* *
|
||||
* Um bei einem Koroutinenwechsel den Kontext sichern zu *
|
||||
* koennen, enthaelt jedes Koroutinenobjekt eine Struktur *
|
||||
* CoroutineState, in dem die Werte der nicht-fluechtigen *
|
||||
* Register gesichert werden koennen. *
|
||||
* *
|
||||
* Autor: Michael, Schoettner, HHU, 13.08.2020 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "kernel/corouts/Coroutine.h"
|
||||
|
||||
// Funktionen, die auf der Assembler-Ebene implementiert werden, muessen als
|
||||
// extern "C" deklariert werden, da sie nicht dem Name-Mangeling von C++
|
||||
// entsprechen.
|
||||
extern "C" {
|
||||
void Coroutine_start(struct CoroutineState* regs);
|
||||
void Coroutine_switch(struct CoroutineState* regs_now, struct CoroutineState* reg_then);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Prozedur: Coroutine_init *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Bereitet den Kontext der Koroutine fuer den ersten *
|
||||
* Aufruf vor. *
|
||||
*****************************************************************************/
|
||||
void Coroutine_init(struct CoroutineState* regs, unsigned int* stack, void (*kickoff)(Coroutine*), void* object) {
|
||||
|
||||
register unsigned int** sp = (unsigned int**)stack;
|
||||
|
||||
// Stack initialisieren. Es soll so aussehen, als waere soeben die
|
||||
// eine Funktion aufgerufen worden, die als Parameter den Zeiger
|
||||
// "object" erhalten hat.
|
||||
// Da der Funktionsaufruf simuliert wird, kann fuer die Ruecksprung-
|
||||
// adresse nur ein unsinniger Wert eingetragen werden. Die aufgerufene
|
||||
// Funktion muss daher dafuer sorgen, dass diese Adresse nie benoetigt
|
||||
// wird, sie darf also nicht terminieren, sonst kracht's.
|
||||
|
||||
*(--sp) = (unsigned int*)object; // Parameter
|
||||
*(--sp) = (unsigned int*)0x131155; // Ruecksprungadresse
|
||||
|
||||
// Nun legen wir noch die Adresse der Funktion "kickoff" ganz oben auf
|
||||
// den Stack. Wenn dann bei der ersten Aktivierung dieser Koroutine der
|
||||
// Stackpointer so initialisiert wird, dass er auf diesen Eintrag
|
||||
// verweist, genuegt ein ret, um die Funktion kickoff zu starten.
|
||||
// Genauso sollen auch alle spaeteren Threadwechsel ablaufen.
|
||||
|
||||
*(--sp) = (unsigned int*)kickoff; // Adresse
|
||||
|
||||
// Initialisierung der Struktur ThreadState mit den Werten, die die
|
||||
// nicht-fluechtigen Register beim ersten Starten haben sollen.
|
||||
// Wichtig ist dabei nur der Stackpointer.
|
||||
|
||||
regs->ebx = 0;
|
||||
regs->esi = 0;
|
||||
regs->edi = 0;
|
||||
regs->ebp = 0;
|
||||
regs->esp = sp;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Funktion: kickoff *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Funktion zum Starten einer Korutine. Da diese Funktion *
|
||||
* nicht wirklich aufgerufen, sondern nur durch eine *
|
||||
* geschickte Initialisierung des Stacks der Koroutine *
|
||||
* angesprungen wird, darf er nie terminieren. Anderenfalls *
|
||||
* wuerde ein sinnloser Wert als Ruecksprungadresse *
|
||||
* interpretiert werden und der Rechner abstuerzen. *
|
||||
*****************************************************************************/
|
||||
void kickoff(Coroutine* object) {
|
||||
object->run();
|
||||
|
||||
// object->run() kehrt hoffentlich nie hierher zurueck
|
||||
for (;;) {}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Coroutine::Coroutine *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Initialer Kontext einer Koroutine einrichten. *
|
||||
* *
|
||||
* Parameter: *
|
||||
* stack Stack für die neue Koroutine *
|
||||
*****************************************************************************/
|
||||
Coroutine::Coroutine(unsigned int* stack) {
|
||||
Coroutine_init(®s, stack, kickoff, this);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Coroutine::switchToNext *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Auf die nächste Koroutine umschalten. *
|
||||
*****************************************************************************/
|
||||
void Coroutine::switchToNext() {
|
||||
|
||||
/* hier muss Code eingefügt werden */
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Coroutine::start *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Aktivierung der Koroutine. *
|
||||
*****************************************************************************/
|
||||
void Coroutine::start() {
|
||||
|
||||
/* hier muss Code eingefügt werden */
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: Coroutine::start *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Verweis auf nächste Koroutine setzen. *
|
||||
*****************************************************************************/
|
||||
void Coroutine::setNext(Chain* next) {
|
||||
|
||||
/* hier muss Code eingefügt werden */
|
||||
}
|
54
c_os/kernel/corouts/Coroutine.h
Executable file
54
c_os/kernel/corouts/Coroutine.h
Executable file
@ -0,0 +1,54 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C O R O U T I N E *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Implementierung eines Koroutinen-Konzepts. *
|
||||
* Die Koroutinen sind miteinander verkettet, weswegen die *
|
||||
* Klasse Coroutine ein Subtyp von 'Chain' ist. *
|
||||
* *
|
||||
* Im Konstruktor wird der initialie Kontext der Koroutine *
|
||||
* eingerichtet. Mit 'start' wird ein Koroutine aktiviert. *
|
||||
* Das Umschalten auf die naechste Koroutine erfolgt durch *
|
||||
* Aufruf von 'switchToNext'. *
|
||||
* *
|
||||
* Um bei einem Koroutinenwechsel den Kontext sichern zu *
|
||||
* koennen, enthaelt jedes Koroutinenobjekt eine Struktur *
|
||||
* CoroutineState, in dem die Werte der nicht-fluechtigen *
|
||||
* Register gesichert werden koennen. *
|
||||
* *
|
||||
* Autor: Michael, Schoettner, HHU, 13.08.2020 *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __Coroutine_include__
|
||||
#define __Coroutine_include__
|
||||
|
||||
#include "kernel/corouts/CoroutineState.h"
|
||||
#include "lib/Chain.h"
|
||||
|
||||
class Coroutine : public Chain {
|
||||
|
||||
private:
|
||||
Coroutine(const Coroutine ©); // Verhindere Kopieren
|
||||
|
||||
private:
|
||||
struct CoroutineState regs;
|
||||
|
||||
public:
|
||||
Coroutine (unsigned int* stack);
|
||||
|
||||
// Coroutine aktivieren
|
||||
void start ();
|
||||
|
||||
// Auf die naechste Coroutine umschalten
|
||||
void switchToNext ();
|
||||
|
||||
// Methode der Coroutine, muss in Sub-Klasse implementiert werden
|
||||
virtual void run () = 0;
|
||||
|
||||
// Verweis auf nächste Coroutine setzen
|
||||
void setNext (Chain* next);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
26
c_os/kernel/corouts/Coroutine.inc
Executable file
26
c_os/kernel/corouts/Coroutine.inc
Executable file
@ -0,0 +1,26 @@
|
||||
;*****************************************************************************
|
||||
;* *
|
||||
;* C O R O U T I N E *
|
||||
;* *
|
||||
;*---------------------------------------------------------------------------*
|
||||
;* Beschreibung: Assemblerdarstellung der 'struct CoroutineState' aus *
|
||||
;* CoroutineState.h *
|
||||
;* *
|
||||
;* Die Reihenfolge der Registerbezeichnungen muss unbedingt *
|
||||
;* mit der von 'struct CoroutineState' uebereinstimmen. *
|
||||
;* *
|
||||
;* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
;*****************************************************************************
|
||||
|
||||
; Nicht-fluechtige Register des Intel 80386 Prozessors
|
||||
|
||||
; Die folgenden Angaben belegen ebx_offset mit dem Wert 0, esi_offset mit 4
|
||||
; edi_offset mit 8 usw. Dies entspricht den Abstaenden der Elemente ebx, esi,
|
||||
; edi usw. der Struktur CoroutineState zum Anfang der Struktur (in Bytes).
|
||||
|
||||
[ABSOLUTE 0]
|
||||
ebx_offset: resd 1
|
||||
esi_offset: resd 1
|
||||
edi_offset: resd 1
|
||||
ebp_offset: resd 1
|
||||
esp_offset: resd 1
|
40
c_os/kernel/corouts/CoroutineState.h
Executable file
40
c_os/kernel/corouts/CoroutineState.h
Executable file
@ -0,0 +1,40 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C O R O U T I N E S T A T E *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Die Struktur CoroutineState dient dazu, bei einem *
|
||||
* Koroutinenwechsel die Werte der nicht-fluechtigen *
|
||||
* Register zu sichern. Beim GNU C Compiler sind eax, ecx *
|
||||
* und edx fluechtige Register, die bei Funktionsaufrufen *
|
||||
* und somit auch bei einem Koroutinenwechsel keine spaeter *
|
||||
* noch benoetigten Werte haben duerfen. Daher muss in der *
|
||||
* Struktur CoroutineState auch kein Platz fuer sie bereit- *
|
||||
* gestellt werden. *
|
||||
* *
|
||||
* Achtung: Fuer den Zugriff auf die Elemente von *
|
||||
* struct CoroutineState aus einer Assemblerfunktion *
|
||||
* heraus werden in der Datei Coroutine.inc Namen fuer die *
|
||||
* benoetigten Abstaende der einzelnen Elemente zum Anfang *
|
||||
* der Struktur definiert. Damit dann auch auf die richtigen*
|
||||
* Elemente zugegriffen wird, sollten sich die Angaben von *
|
||||
* CoroutineState.h und Coroutine.inc exakt entsprechen. *
|
||||
* Wer also CoroutineState.h aendert, muss auch *
|
||||
* Coroutine.inc anpassen (und umgekehrt.) *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __CoroutineState_include__
|
||||
#define __CoroutineState_include__
|
||||
|
||||
struct CoroutineState {
|
||||
void *ebx;
|
||||
void *esi;
|
||||
void *edi;
|
||||
void *ebp;
|
||||
void *esp;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
26
c_os/lib/Chain.h
Executable file
26
c_os/lib/Chain.h
Executable file
@ -0,0 +1,26 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C H A I N *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Implementierung einer einfach verketteten Liste von *
|
||||
* Chain Objekten. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __Chain_include__
|
||||
#define __Chain_include__
|
||||
|
||||
class Chain {
|
||||
|
||||
private:
|
||||
Chain(const Chain ©); // Verhindere Kopieren
|
||||
|
||||
public:
|
||||
Chain* next;
|
||||
|
||||
Chain() {}
|
||||
};
|
||||
|
||||
#endif
|
17
c_os/main.cc
17
c_os/main.cc
@ -19,10 +19,21 @@ int main() {
|
||||
kout.clear();
|
||||
|
||||
// Speicherverwaltung initialisieren
|
||||
allocator.init();
|
||||
// allocator.init(); // NOTE: Disabled for coroutines
|
||||
|
||||
// Initialize scrollback buffer after allocator.init()
|
||||
kout.init(5);
|
||||
// kout.init(5); // NOTE: Disabled for coroutines
|
||||
|
||||
// Startmeldung
|
||||
kout << "HHUos 0.5" << endl
|
||||
<< "=========" << endl
|
||||
<< "Unterstuetzte Funktionen:" << endl
|
||||
<< " - Bildschirmausgaben" << endl
|
||||
<< " - Sound ueber den PC-Lautsprecher" << endl
|
||||
<< " - Tastatureingaben per Interrupt" << endl
|
||||
// << " - Einfache Heap verwaltung" << endl
|
||||
<< " - Koroutinen" << endl
|
||||
<< endl;
|
||||
|
||||
// Tastatur-Unterbrechungsroutine 'einstoepseln'
|
||||
/* hier muss Code eingefuegt werden */
|
||||
@ -35,7 +46,7 @@ int main() {
|
||||
// text_demo();
|
||||
// sound_demo();
|
||||
// keyboard_demo();
|
||||
heap_demo();
|
||||
// heap_demo();
|
||||
// key_irq_demo();
|
||||
|
||||
while (1) {};
|
||||
|
34
c_os/user/CoroutineDemo.cc
Executable file
34
c_os/user/CoroutineDemo.cc
Executable file
@ -0,0 +1,34 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C O R O U T I N E D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Einstieg in eine Anwendung. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 15.8.2016 *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "kernel/Globals.h"
|
||||
#include "user/CoroutineDemo.h"
|
||||
#include "user/CoroutineLoop.h"
|
||||
|
||||
|
||||
// Stacks (koennen alternative auch per 'new' alloziert werden)
|
||||
static unsigned int stack[3][1024];
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CoroutineDemo::main *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: main-Methode der Anwendung. *
|
||||
*****************************************************************************/
|
||||
void CoroutineDemo::main () {
|
||||
|
||||
/*
|
||||
* Hier muss Code eingefuegt werden
|
||||
*
|
||||
* Die 3 Koroutinen einrichten, verketten und die 1. starten
|
||||
*
|
||||
*/
|
||||
|
||||
}
|
25
c_os/user/CoroutineDemo.h
Executable file
25
c_os/user/CoroutineDemo.h
Executable file
@ -0,0 +1,25 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C O R O U T I N E D E M O *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Einstieg in eine Anwendung. *
|
||||
* *
|
||||
* Autor: Michael Schoettner, HHU, 15.8.2016 *
|
||||
*****************************************************************************/
|
||||
#ifndef __coroutinedemo_include__
|
||||
#define __coroutinedemo_include__
|
||||
|
||||
class CoroutineDemo {
|
||||
|
||||
private:
|
||||
CoroutineDemo(const CoroutineDemo& copy); // Verhindere Kopieren
|
||||
|
||||
public:
|
||||
CoroutineDemo() {}
|
||||
|
||||
// Koroutine-Startmethode
|
||||
void main();
|
||||
};
|
||||
|
||||
#endif
|
27
c_os/user/CoroutineLoop.cc
Executable file
27
c_os/user/CoroutineLoop.cc
Executable file
@ -0,0 +1,27 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C O R O U T I N E L O O P *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Loop ist eine Koroutine, die nichts weiter tut als einen *
|
||||
* Zaehler hochzuzaehlen und diesen auf dem Bildschirm *
|
||||
* anzuzeigen und dann auf die naechste Korotuine umzu- *
|
||||
* schalten. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
*****************************************************************************/
|
||||
|
||||
#include "user/CoroutineLoop.h"
|
||||
#include "kernel/Globals.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Methode: CoroutineLoop::run *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Einstiegsfunktion der Koroutine. *
|
||||
*****************************************************************************/
|
||||
void CoroutineLoop::run () {
|
||||
|
||||
/* Hier muss Code eingefuegt werden */
|
||||
|
||||
}
|
34
c_os/user/CoroutineLoop.h
Executable file
34
c_os/user/CoroutineLoop.h
Executable file
@ -0,0 +1,34 @@
|
||||
/*****************************************************************************
|
||||
* *
|
||||
* C O R O U T I N E L O O P *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* Beschreibung: Loop ist eine Koroutine, die nichts weiter tut als einen *
|
||||
* Zaehler hochzuzaehlen und diesen auf dem Bildschirm *
|
||||
* anzuzeigen und dann auf die naechste Korotuine umzu- *
|
||||
* schalten. *
|
||||
* *
|
||||
* Autor: Olaf Spinczyk, TU Dortmund *
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __coroutineloop_include__
|
||||
#define __coroutineloop_include__
|
||||
|
||||
#include "kernel/corouts/Coroutine.h"
|
||||
|
||||
class CoroutineLoop : public Coroutine {
|
||||
|
||||
private:
|
||||
int id;
|
||||
|
||||
CoroutineLoop(const CoroutineLoop& copy); // Verhindere Kopieren
|
||||
|
||||
public:
|
||||
// Gibt der Loop einen Stack und eine Id.
|
||||
CoroutineLoop(unsigned int* stack, int i) : Coroutine(stack) { id = i; }
|
||||
|
||||
// Zaehlt einen Zaehler hoch und gibt ihn auf dem Bildschirm aus.
|
||||
void run();
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user