1

add vorgabe05

This commit is contained in:
churl
2022-05-20 16:16:24 +02:00
parent 2b41893743
commit bdfe784340
11 changed files with 461 additions and 3 deletions

View 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
View 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(&regs, 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
View 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 &copy); // 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

View 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

View 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
View 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 &copy); // Verhindere Kopieren
public:
Chain* next;
Chain() {}
};
#endif

View File

@ -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
View 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
View 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
View 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
View 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