home *** CD-ROM | disk | FTP | other *** search
- ⓪ MODULE MultiTask; (*$E MOS *)
- ⓪ (*$R-*)
- ⓪
- ⓪ (*
- ⓪ >>> Das Ganze geht aus einem Grunde nicht:
- ⓪"Wenn z.b. der Timer-IR auftritt, während gerade der VBL-IR läuft,
- ⓪"würde durch den IOTRANSFER der VBL unterbrochen werden. Das darf
- ⓪"aber nicht sein, stattdessen müßte erst der VBL beendet und erst
- ⓪"dann der timer-IR zugelassen werden. Dies wird bei Multitask-Systemen
- ⓪"i.a. so gelöst, daß der scheduler-IR eine niedrigere Priorität als
- ⓪"alle System-IRs bekommt. Oder eben so, daß durch Semaphore o.ä.
- ⓪"dafür gesorgt wird, daß der Timer-IR bis zum Ende der System-IRs
- ⓪"wartet.
- ⓪"Hier könnte man es entweder so lösen, daß als timer-IR der VBL-
- ⓪"Hardware-Vektor verwendet wird oder daß man sich in alle Sytem-IRs
- ⓪"hängt und semaphore setzt.
- ⓪ *)
- ⓪
- ⓪ (*
- ⓪!* Demo für Modula-Coroutinen, die per Interrupt umgeschaltet werden
- ⓪!* ("Time Slice").
- ⓪!*
- ⓪!* Das Demo-Programm geht nur von zwei Coroutinen aus, die abwechselnd
- ⓪!* aktiviert werden sollen. Ein richtiger Scheduler (Prozeß-Verwalter/
- ⓪!* Umschalter) würde stattdessen eine erweiterbare Liste für beliebig
- ⓪!* viele Coroutinen verwalten und sie alle abwechselnd aktivieren.
- ⓪!*
- ⓪!* Die Coroutinen werden folgendermaßen abwechselnd aktiviert: Zuerst
- ⓪!* einmal läuft das Hauptprogramm (Prozedur 'mainProgram'). Jede zwanzigstel
- ⓪!* Sekunde wird die erste Coroutine für eine fünfzigstel Sekunde aktiviert.
- ⓪!* Nach Ablauf einer Sekunde wird dann stattdessen die zweite Coroutine
- ⓪!* alle 1/20s für jeweils 1/50s aktiviert. Nach einer weiteren Sekunde
- ⓪!* wieder die erste, usw.
- ⓪!*
- ⓪!* Das bedeutet:
- ⓪!
- ⓪!* Die scheduler-Funktion (s.u.) benutzt den 200Hz-Interrupt-Vektor,
- ⓪!* sie wird also 200 mal pro Sekunde aufgerufen. Die Funktion installiert
- ⓪!* sich auf den Vektor mit IOTRANSFER. Jedesmal, wenn der Vektor ange-
- ⓪!* sprungen wird, wird die unterbrochene Coroutine (bzw. das unterbrochene
- ⓪!* Programm) im ersten Parameter zu IOTRANSFER ('suspendedCor') gespeichert.
- ⓪!* Der Scheduler zählt nun einen Zähler herunter. Ist er nicht abgelaufen,
- ⓪!* wird gleich wieder mit IOTRANSFER zur unterbrochenen Routine zurückgekehrt.
- ⓪!* Andernfalls wird eine der zwei wartenden Coroutinen
- ⓪!*
- ⓪!Ist der Zähler abgelaufen, wird jeweils
- ⓪!* eine der wartenden Coroutinen aktiviert. Der Zähler zählt 400 Werte,
- ⓪!* die Coroutinen werden demnach alle 2 Sekunden umgeschaltet.
- ⓪!*
- ⓪!* Zur Sichtbarmachung der Aktionen der beiden Coroutinen
- ⓪!* sie beide an verschiedenen Stellen auf dem Bildschirm herum. Dies
- ⓪!* geschieht durch Direktzugriff auf den Bildschirmspeicher, weil
- ⓪!* ein Aufruf von Ein-/Ausgabe-Funktionen (GEM, GEMDOS, BIOS) in
- ⓪!* Interrupts so einfach nicht erlaubt ist.
- ⓪!!Info-Line raus!
- ⓪!*)
- ⓪
- ⓪ FROM SYSTEM IMPORT ADDRESS, ADR, IOTRANSFER, TRANSFER, NEWPROCESS, IOCALL;
- ⓪ FROM SYSTEM IMPORT ASSEMBLER;
- ⓪ (*
- ⓪ FROM SysVars IMPORT etv_timer;
- ⓪ *)
- ⓪ FROM XBIOS IMPORT ScreenLogicalBase;
- ⓪ FROM Terminal IMPORT WriteString, WriteLn, Write;
- ⓪
- ⓪ CONST etv_timer =$114;
- ⓪
- ⓪ VAR mainCor: ADDRESS; (* Hauptprogramm *)
- ⓪%schedCor: ADDRESS; (* Scheduler-Coroutine *)
- ⓪%cor1, cor2: ADDRESS; (* die Hintergrund-Coroutinen *)
- ⓪
- ⓪%screen: POINTER TO ARRAY [0..399] OF ARRAY [0..39] OF BITSET;
- ⓪%seconds: CARDINAL;
- ⓪%terminate: BOOLEAN;
- ⓪
- ⓪ PROCEDURE lauflicht (offset: CARDINAL; VAR pos: CARDINAL);
- ⓪"VAR b: BITSET;
- ⓪"BEGIN
- ⓪$b:= {};
- ⓪$INCL (b, pos);
- ⓪$IF pos=0 THEN pos:= 15; ELSE DEC (pos) END;
- ⓪$screen^[1,offset]:= b;
- ⓪$screen^[2,offset]:= b;
- ⓪$screen^[3,offset]:= b;
- ⓪$screen^[4,offset]:= b;
- ⓪"END lauflicht;
- ⓪
- ⓪ PROCEDURE funktion1;
- ⓪"VAR pos: CARDINAL;
- ⓪"BEGIN
- ⓪$pos:= 0;
- ⓪$LOOP
- ⓪&lauflicht (4, pos);
- ⓪$END
- ⓪"END funktion1;
- ⓪
- ⓪ PROCEDURE funktion2;
- ⓪"VAR pos: CARDINAL;
- ⓪"BEGIN
- ⓪$pos:= 0;
- ⓪$LOOP
- ⓪&lauflicht (8, pos);
- ⓪$END
- ⓪"END funktion2;
- ⓪
- ⓪ PROCEDURE mainProgram;
- ⓪"(*
- ⓪#* Diese Prozedur läuft als Hauptprogramm, also nicht im Interrupt.
- ⓪#*)
- ⓪"VAR last: CARDINAL; l: LONGCARD;
- ⓪"BEGIN
- ⓪$seconds:= 0; (* Sekundenzähler, wird vom Scheduler erhöht *)
- ⓪$last:= seconds;
- ⓪$REPEAT
- ⓪&(* Gibt jede Sekunde ein Zeichen aus: *)
- ⓪&IF last # seconds THEN
- ⓪(last:= seconds;
- ⓪(Write ('#');
- ⓪&END
- ⓪$UNTIL FALSE (*seconds = 6; (* Ende nach 6 Sekunden *)*)
- ⓪"END mainProgram;
- ⓪ ə
- (* $FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$00000D26$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DC$FFEE50DCÇ$00000027T.......T.......T.......T.......T.......T.......T.......T.......T.......T.......$00000027$000000EA$FFEE50DC$00000EA4$00000B77$00001031$0000105B$FFEE50DC$FFEE50DC$000002F0$00000091$0000006B$000002F0$000002E1$00000031$000002F0êÇé*)
-