Die Erfindung betrifft ein Verfahren zum Synchronisieren von
Programmabschnitten eines Computerprogramms, dessen Programmab
schnitte parallel auf unterschiedlichen Prozessoren eines Com
puters ablaufen können.
In "Win 372 Multithreaded Programming, Aaron Cohen und Mike
Woodring, O'Reilly & Associates Inc., ISBN 1-56592-296-4" ist
insbesondere auf den Seiten 258 bis 269 und 301 bis 303 die
Programmierung und Synchronisierung von Threads erläutert.
Nachfolgend werden derartige Threads auch als Programmabschnit
te bezeichnet.
Programmabschnitte, die Daten für einen anderen Programmab
schnitt erzeugen, werden als Erzeuger oder Schreiber und Pro
grammabschnitte, die derartige Daten verarbeiten, als Verbrau
cher oder Leser bezeichnet. Um beim Aufteilen der Arbeit zwi
schen den einzelnen Programmabschnitten die Rechenleistung ei
nes Computers mit mehreren Prozessoren optimal auszunutzen ist
es notwendig, dass die einzelnen Programmabschnitte asynchron
betrieben werden. Dies bedeutet, dass der Erzeuger-
Programmabschnitt soviel Daten erzeugen kann, wie er wünscht,
und der Lese-Programmabschnitt soviel Daten lesen kann, wie zur
Verfügung stehen, ohne dass hierbei Rücksicht auf den anderen
Programmabschnitt genommen werden muss. Die Daten eines Erzeu
ger-Programmabschnittes werden von diesen in Pakete (Messages)
gepackt und in eine Reihe (Queue) eingereiht, aus der der Lese-
Programmabschnitt die Pakete aufnehmen und weiterverarbeiten
kann.
Die einzelnen Programmabschnitte sind mit Funktionen versehen,
die warten, bis sie ein entsprechendes Paket in einer Reihe ab
legen können, oder bis ein entsprechendes Paket zum Lesen ange
kommen ist, damit immer die korrekte Zuordnung der Daten zu den
sie verarbeitenden Funktionen sichergestellt ist. Hierdurch
wird der Transport der Daten synchronisiert.
Die Synchronisation des Datentransfers zwischen einzelnen Pro
grammabschnitten kann intern oder extern ausgeführt werden. Un
ter einer internen Synchronisation versteht man eine Synchroni
sation, bei der die einzelnen Synchronisationsvorgänge von den
Programmabschnitten ausgeführt werden, wohingegen eine externe
Synchronisation mittels außerhalb der Programmabschnitte gebil
deter Programme ausgeführt wird. Eine externe Synchronisation
wird vorzugsweise für Datenstrukturen verwendet, welche von
mehreren Programmabschnitten gleichzeitig benutzt werden. Für
den Datentransfer zwischen einzelnen Programmabschnitten ist es
üblich, diese intern zu synchronisieren. Es wird davon ausge
gangen, dass hier eine interne Synchronisation einfacher zu
realisieren ist und die entsprechenden Programme kürzer sind.
Ein Ziel derartiger Synchronisationsmechanismen ist es, dass
sie möglichst vielfältig eingesetzt werden können, das heißt,
dass sie von unterschiedlichsten Programmabschnitten verwendet
werden können. Die oben erläuterten Reihen (Queues) sind ein
Beispiel für sehr vielfältig einsetzbare Kommunikationsmecha
nismen. Sie erzeugen jedoch einen erheblichen Verwaltungsauf
wand, da die Daten in entsprechende Pakete gepackt, diese Pake
te mit entsprechenden Informationen versehen, von den Erzeuger-
Programmabschnitten entsprechend versandt, von der Queue aufge
nommen und vom Lese-Programmabschnitt wieder aufgenommen, aus
gelesen und zusammengesetzt werden müssen. Diese allgemeine
Einsatzfähigkeit der Reihen wird durch einen hohen Verwaltungs
aufwand erkauft.
Am schnellsten laufen Programmabschnitte auf unterschiedlichen
Prozessoren ab, wenn sie mit einem asynchronen Datentransfer
programmiert sind. Bei einem derartigen asynchronen Datentrans
fer kann z. B. ein Programmabschnitt eine Anfrage nach Daten
ausgeben und während er auf den Empfang der Daten wartet, be
reits eine andere Verarbeitung von Daten aufnehmen. Ein derart
asynchroner Datentransfer ist hoch effizient, aber sehr schwer
zu programmieren.
Ein Problem dieser auf mehrere Programmabschnitte verteilten
Computerprogrammen ist, dass ein Test, bei welchem die Pro
grammabschnitte auf mehreren Prozessoren gleichzeitig laufen,
schwer durchführbar ist, da je nachdem, wie sich die Verarbei
tungsvorgang der einzelnen Programmabschnitte zeitlich über
lappt, unterschiedliche Fehler einstellen können. Hierdurch
kann es sein, dass ein Computerprogramm tausende Male richtig
funktioniert und dann wieder ein nicht ohne weiteres vorherseh
barer Fehler auftritt. Für einen zuverlässigen Praxistest ist
es deshalb notwendige Voraussetzung derartige Synchronisations
verfahren mit einem Multi-CPU-Computer zu testen. Das sind Com
puter, die mehrere Prozessoren aufweisen, die gleichzeitig un
terschiedliche Programmabschnitte abarbeiten können.
Ein Verfahren zum Synchronisieren von Programmabschnitten muß
deshalb nicht nur einen effizienten Datentransfer und vielsei
tig einsetzbar sein, sondern möglichst einfach ausgebildet
sein, damit kein unverhältnismäßig großer Einsatz beim Testen
des Computerprogramms notwendig ist.
Der Erfindung liegt deshalb die Aufgabe zugrunde, ein Verfahren
zum Synchronisieren von Programmabschnitten eines Computerpro
grammes zu schaffen, das vielfältig einsetzbar ist, einen sehr
effizienten Datentransfer zwischen den Programmabschnitten er
laubt und zudem einfach ausgebildet ist.
Die Aufgabe wird durch ein Verfahren mit den Merkmalen des An
spruchs 1 gelöst. Vorteilhafte Ausgestaltungen der Erfindung
sind in den Unteransprüchen angegeben.
In dem erfindungsgemäßen Verfahren werden Programmabschnitte
eines Computerprogramms synchronisiert. Das Computerprogramm
ist derart aufgebaut, daß die Programmabschnitte parallel auf
unterschiedlichen Prozessoren eines Computers ablaufen können.
Erzeuger-Programmabschnitte, die Daten für einen anderen Pro
grammabschnitt erzeugen, schreiben diese jeweils in einen Puf
fer. Lese-Programmabschnitte, die Daten von einem anderen Pro
grammabschnitt lesen, lesen die Daten aus einem Puffer aus.
Pufferabschnitte des Puffers sind mit jeweils einem Flag verse
hen, das ein unerlaubtes Schreiben und Lesen der entsprechenden
Pufferabschnitte verhindert, wobei das Flag von Puffer-
Dienstprogrammen selbstätig gesetzt wird.
Das erfindungsgemäße Verfahren zum Synchronisieren von Pro
grammabschnitten sieht somit einen Puffer vor, bei dem das Le
sen und Schreiben mittels Flags gesteuert wird. Die erfindungs
gemäße Programmstruktur ist sehr einfach ausgebildet, weshalb
es auch auf Computern mit mehreren Prozessoren mit einem rela
tiv geringen Aufwand getestet werden kann. Das erfindungsgemäße
Verfahren ist sehr effizient, denn die Daten können von einem
Erzeuger-Programmabschnitt direkt in den Puffer geschrieben
bzw. von einem Lese-Programmabschnitt direkt aus diesem gelesen
werden. Eine Vor- bzw. Nachverarbeitung der geschriebenen bzw.
gelesenen Daten ist nicht notwendig. Das erfindungsgemäße Ver
fahren ist zudem sehr effizient, da nur ein geringer Verwal
tungsaufwand mit dem Setzen bzw. Löschen des Flags anfällt, so
daß die Prozessorleistung eines Computers auf die wesentlichen
Arbeiten des Datentransfers bzw. der Ausführung der Programmab
schnitte konzentriert wird.
Nach einer bevorzugten Ausführungsform der Erfindung sind die
einzelnen Pufferabschnitte im Speicherbereich des Computers un
mittelbar hintereinander liegend angeordnet und zu den jeweili
gen Pufferabschnitten sind zugeordnete Verwaltungsdaten, wie
z. B. das Flag, die Größe des Pufferabschnittes oder der Daten
typ in einem davon unabhängigen Speicherbereich gespeichert.
Hierdurch wird ein durchgehender mit Daten belegter Speicherbe
reich geschaffen, der schnell und einfach ausgelesen bzw. mit
neuen Daten beschrieben werden kann. Zudem erlaubt diese Aus
bildung des Puffers, daß dieser mit Blöcken einer bestimmten
Größe beschrieben und Blöcken einer anderen Größe gelesen wer
den kann. Hierdurch kann die Datentransferrate, die durch die
Größe der Blöcke beeinflußt wird, an die entsprechenden Anfor
derungen, die sowohl auf der Seite der Erzeuger-
Programmabschnitte als auch auf der Seite der Lese-
Programmabschnitte hoch oder niedrig sein kann, entsprechend
angepaßt werden.
Die Erfindung wird nachfolgend beispielhaft anhand der beilie
genden Zeichnungen näher erläutert. In den Zeichnungen zeigen:
Fig. 1 den Betrieb eines in mehrere Programmabschnitte auf
gespalteten Computerprogramms gemäß dem erfindungsgemäßen
Verfahren schematisch in einem Blockschaltbild,
Fig. 2 den Betrieb des Computerprogramms aus Fig. 1, wobei
ein Programmabschnitt weggelassen wird,
Fig. 3 schematisch ein Beispiel für einen Puffer mit dem den
jeweiligen Pufferabschnitten zugeordneten Flags in einer
tabellarischen Darstellung,
Fig. 4 das Schreiben in den Puffer und das Lesen aus dem
Puffer mit unterschiedlichen Blöcken schematisch in einem
Blockschaltbild,
Fig. 5 das Lesen und Schreiben schematisch vereinfacht in
einem Blockschaltbild, wobei das Blockschaltbild in drei
Bereiche, den Bereich des Erzeuger-Programmabschnittes,
der Synchronisations-Puffer-Klasse und dem Bereich des
Lese-Programmabschnittes unterteilt ist und die Blöcke
jeweils in dem Bereich angeordnet sind, in dem sie ausge
führt werden,
Fig. 6 bis 10 einzelne Puffer-Dienstprogramme nach einem er
sten Ausführungsbeispiel jeweils in einem Flußdiagramm,
Fig. 11a und 11b ein gegenüber dem ersten Ausführungsbei
spiel abgewandeltes Puffer-Dienstprogramm gemäß einem
zweiten Ausführungsbeispiel der Erfindung in einem Fluß
diagramm,
Fig. 12 ein weiteres gegenüber dem ersten Ausführungsbeispiel
abgewandeltes Puffer-Dienstprogramm gemäß dem zweiten
Ausführungsbeispiel der Erfindung in einem Flußdiagramm,
Fig. 13 einen Computer mit einem Prozessor in einem schema
tisch vereinfachten Blockschaltbild und
Fig. 14 einen Computer mit zwei Prozessoren in einem schema
tisch vereinfachten Blockschaltbild.
In Fig. 1 ist schematisch der Betrieb eines in mehrere Pro
grammabschnitte P0 bis P3 aufgeteilten Computerprogramms darge
stellt. Zur Veranschaulichung ist lediglich ein einfaches Com
puterprogramm schematisch dargestellt, dessen Programmabschnit
te die Initialisierung P0, das Datenlesen P1, das Datenverar
beiten P2 und das Datenschreiben P3 ausführen. Der Programmab
schnitt "Daten lesen" P1 muß Daten an den Programmabschnitt
"Daten verarbeiten" P2 und dieser muß Daten an den Programmab
schnitt "Daten schreiben" P3 weitergeben, weshalb zwischen den
Programmabschnitten P1 und P2 ein Puffer PU1 und den Pro
grammabschnitten P2 und P3 ein Puffer PU2 angeordnet sind.
Aus Sicht des Programmabschnittes "Daten verarbeiten" P2 ist
der Puffer PU1 ein Eingabepuffer, der Daten in den Programmab
schnitt P2 eingibt, und der Puffer PU2 ein Ausgabepuffer, der
Daten des Programmabschnittes P2 aufnimmt. Mit dem erfindungs
gemäßen Verfahren wird der Datentransfer DT von einem Pro
grammabschnitt zu einem Puffer - z. B. von P1 zu PU1 oder von P2
zu PU2 - bzw. von einem Puffer zu einem Programmabschnitt -
z. B. von PU1 zu P2 - lediglich durch eine Kommunikation zwi
schen dem jeweiligen Puffer und dem jeweiligen Programmab
schnitt gesteuert. Dies ist in Fig. 1 durch die entgegen zum
Datenhauptstrom verlaufenden Pfeile PF dargestellt.
Die Grundprinzipien der erfindungsgemäßen Steuerung des Daten
transfers DT zwischen den Programmabschnitten und den Puffern
werden nachfolgend anhand der Fig. 3 bis 5 näher erläutert.
Diese Steuerung bzw. Synchronisation des Datentransfers DT er
folgt mit einer Synchronisations-Puffer-Klasse. Der Begriff der
"Klasse" ist in der objektorientierten Programmierung geprägt
worden und bedeutet im Sinne der vorliegenden Patentanmeldung
eine geschlossene Einheit, die in Feldern und Variablen gespei
cherte Daten sowie Programme umfaßt. Die Synchronisations-
Puffer-Klasse weist einen Speicherbereich, den Puffer, in dem
ein oder mehrere Pufferabschnitte gespeichert sind, einen wei
teren Speicherbereich, das Kontrollfeld, in dem Verwaltungsda
ten für den Puffer gespeichert sind, und Puffer-Dienstprogramme
auf. Die Puffer-Dienstprogramme sind Funktionen, d. h. ausführ
bare Programmteile. Beim erfindungsgemäßen Verfahren sind jedem
Pufferabschnitt jeweils eine Gruppe von Verwaltungsdaten zuge
ordnet, die ein Flag (Fig. 3), eine Angabe über die Größe des
Pufferabschnittes und eine Angabe über den Inhalt der im Puffer
gespeicherten Daten umfaßt. Das Flag ist eine Zustandsvariable,
die drei Zustände einnehmen kann, nämlich "ungültig", "gültig"
und "reserviert".
Ist das Flag "ungültig", so bedeutet dies, daß in dem zugehöri
gen Pufferabschnitt keine zum Lesen durch den Erzeuger-
Programmabschnitt vorgesehene Daten enthalten sind. Ist das
Flag "gültig" sind Daten in den zugehörigen Pufferabschnitt ge
schrieben worden, die vom Lese-Programmabschnitt gelesen werden
können. Ist das Flag "reserviert", so bedeutet dies, daß der
Erzeuger-Programmabschnitt bereits Daten in den zugehörigen
Pufferabschnitt geschrieben hat, aber diese Daten noch nicht
zum Lesen durch den Lese-Programmabschnitt freigegeben sind.
Hierzu muß das Flag auf "gültig" gesetzt werden.
Die Synchronisations-Puffer-Klasse umfaßt ferner einige Puffer-
Dienstprogramme wie z. B. GetToBufPntr, GetFromBufPntr, Release-
ToBufPntr und ReleaseFromBufPntr.
Fig. 3 zeigt die Flags und Pufferabschnitte einer erfindungsge
mäßen Synchronisations-Puffer-Klasse schematisch in einer ta
bellarischen Darstellung. Es sind insgesamt 8 Pufferabschnitte
vorgesehen, welchen jeweils ein Flag zugeordnet ist. Der Puf
ferabschnitt 0 (oberster Pufferabschnitt in Fig. 3) enthält
keine zum Lesen vorgesehenen Daten, weshalb dem zugehörigen
Flag der Wert "ungültig" zugewiesen ist. Die weiteren Pufferab
schnitte 1 bis 5 enthalten Daten, wobei die Pufferabschnitte 1
bis 3 gelesen werden können und die Pufferabschnitte 4 bis 5
vom Erzeuger-Programmabschnitt noch nicht freigegeben sind.
Dementsprechend ist den den Pufferabschnitten 1 bis 3 zugeord
neten Flags der Wert "gültig" und den den Pufferabschnitten 4
und 5 zugeordneten Flags der Wert "reserviert" zugeordnet. Die
weiteren Pufferabschnitte 6 und 7 enthalten keine zum Lesen
freigegebenen Daten, weshalb die ihnen zugeordneten Flags den
Wert "ungültig" aufweisen. Ein Erzeuger-Programmabschnitt kann
in die Pufferabschnitte 6, 7 und 0 Daten schreiben und ein Le
se-Programmabschnitt kann aus den Pufferabschnitten 1 bis 3 Da
ten auslesen.
Fig. 5 zeigt schematisch das Zusammenwirken eines Erzeuger-
Programmabschnittes und eines Lese-Programmabschnittes, der
vom Erzeuger-Programmabschnitt in einer erfindungsgemäßen Syn
chronisations-Puffer-Klasse zwischengespeicherte Daten emp
fängt. Mit einem Schritt S1 startet der Erzeuger-Programm
abschnitt. Mit einem Schritt S2 ist in Fig. 5 schematisch der
Ablauf eines vorbestimmten Bereichs des Programmabschnitts dar
gestellt, mit dem Daten für den Lese-Programmabschnitt erzeugt
werden. Im Schritt S3 wird das Puffer-Dienstprogramm GetTo
BufPntr aufgerufen, das Bestandteil der Synchronisations-
Puffer-Klasse ist. Mit dem Aufruf dieses Puffer-Dienstprogramms
wird abgefragt, ob im Puffer ein Pufferabschnitt mit der Größe
M1 zum Schreiben von Daten frei ist. Das Puffer-Dienstprogramm
GetToBufPntr(M1) führt diese Abfrage aus und wartet gegebenen
falls solange bis der entsprechende Speicherbereich frei ist.
Sobald der gewünschte Speicherbereich zur Verfügung steht,
übergibt dieses Puffer-Dienstprogramm an den Erzeuger-Programm
abschnitt einen Schreib-Zeiger und den Parameter M2, der die
Größe des zur Verfügung stehenden Speicherbereichs angibt. M2
ist zumindest so groß wie M1. Der Schreib-Zeiger enthält die
Adresse des Anfangs des zur Verfügung stehenden Speicherbe
reichs.
Mit der Anfangsadresse des zur Verfügung stehenden Speicherbe
reichs und dem maximal zur Verfügung stehenden Speicherbereich
kann der Erzeuger-Programmabschnitt im Schritt S4 Daten direkt
in den zur Verfügung stehenden Speicherbereich schreiben.
Wenn alle Daten in den Speicherbereich geschrieben sind, stellt
dieser Speicherbereich einen Pufferabschnitt dar und wird im
Schritt S5 das Puffer-Dienstprogramm ReleaseToBufPntr aufgeru
fen, mit dem das Flag des geschriebenen Pufferabschnittes ent
weder auf "gültig" oder auf "reserviert" gesetzt wird, je nach
dem, ob die Daten zum Lesen durch den Lese-Programmabschnitt
freigegeben sind oder nicht.
Mit den Schritten S6 und S8 sind weitere Verarbeitungsvorgänge
des Erzeuger-Programmabschnittes symbolisch dargestellt. Mit
dem dazwischen liegenden Schritt S7 wird das Puffer-
Dienstprogramm SetResBufState (<Flagtyp<) aufgerufen, mit dem
der im Schritt S5 beschriebene aber noch nicht freigegebene
Pufferabschnitt entweder zum Lesen freigegeben wird, in dem das
entsprechende Flag von "reserviert" auf "gültig" gesetzt wird,
oder für den Lese-Programmabschnitt "gelöscht" wird, indem das
entsprechende Flag von "reserviert" auf "ungültig" gesetzt
wird, wodurch dieser Speicherbereich erneut vom Erzeuger-
Programmabschnitt beschrieben werden kann. Mit dem Schritt S9
wird der Programmablauf des Erzeuger-Programmabschnittes been
det.
Der Programmablauf des Lese-Programmabschnittes ist in Fig. 5
auf der rechten Seite dargestellt und beginnt mit dem Schritt
S10. Die Darstellung in Fig. 5 ist rein schematisch und gibt
nicht den korrekten Zeitablauf wider. Im Schritt S11 ist ein
Abschnitt des Programmablaufs dargestellt, in dem ein Bedarf
nach Daten des Erzeuger-Programmabschnittes entsteht. Der Lese-
Programmabschnitt ruft deshalb das Puffer-Dienstprogramm Get
FromBufPntr S12 auf. Dieses Puffer-Dienstprogramm fragt ab, ob
im Puffer ein Pufferabschnitt mit Daten beschrieben ist, die
zum Lesen durch den Lese-Programmabschnitt freigegeben sind.
Falls keine Daten freigegeben sind, wartet dieses Puffer-
Dienstprogramm solange bis eine entsprechende Anzahl von Daten
geschrieben und freigegeben ist. Danach wird an den Lese-
Programmabschnitt ein Lese-Zeiger und die Größe des Pufferab
schnittes, der mit zum Lesen freigegebenen Daten beschrieben
ist, ausgegeben. Der Lese-Zeiger enthält die Adresse des An
fangs des zum Lesen freigegebenen Pufferabschnittes.
Anhand dieses Lese-Zeigers und der Größe des zum Lesen freige
gebenen Pufferabschnittes kann der Lese-Programmabschnitt im
Schritt S13 die Daten unmittelbar aus dem Puffer auslesen.
Ist der Lesevorgang abgeschlossen, so ruft der Lese-
Programmabschnitt das Puffer-Dienstprogramm ReleaseFromBufPntr
S4 auf, mit dem der vom Lese-Programmabschnitt ausgelesene Puf
ferabschnitt zum erneuten Beschreiben freigegeben wird, das
heißt, daß das entsprechende Flag von "gültig" auf "ungültig"
gesetzt wird.
Der weitere vom Lese-Programmabschnitt ausgeführte Pro
grammablauf ist schematisch mit S15 dargestellt. Mit dem
Schritt S16 endet der Programmablauf des Lese-
Programmabschnittes.
Nachfolgend werden anhand der Fig. 6 bis 12 die einzelnen Puf
fer-Dienstprogramme näher erläutert.
In Fig. 6 ist das Puffer-Dienstprogramm GetToBufPntr (M1) als
Flußdiagramm dargestellt. Es beginnt mit dem Schritt S17, auf
dem im Programmablauf der Beginn der Puffer-Synchronisation S18
folgt. Im Schritt S18 wird eine Standardfunktion des verwende
ten Betriebssystems aufgerufen, mit dem ein gleichzeitiger Zu
griff auf den Puffer und die zugehörigen internen Variablen der
Synchronisations-Puffer-Klasse durch ein anderes Puffer-
Dienstprogramm verhindert wird. Im darauffolgenden Schritt S19
wird der vom Erzeuger-Programmabschnitt übergebene Parameter
M1, der den zum Schreiben benötigten Speicherplatz im Pufferab
schnitt angibt, eingelesen.
Im Schritt S20 wird abgefragt, ob im Puffer ein Pufferabschnitt
zum Beschreiben zur Verfügung steht. Ergibt die Abfrage im
Schritt S20, dass grundsätzlich ein Pufferabschnitt zum Be
schreiben frei ist, so geht der Programmablauf auf den Schritt
S21 über, mit dem die Größe des freien Speicherplatzes im be
schreibbaren Pufferabschnitt berechnet wird.
Im Schritt S22 wird abgefragt, ob der berechnete freie Spei
cherplatz M2 größer als oder gleich dem angefragten Speicher
platz M1 ist.
Ergibt diese Abfrage im Schritt S22, dass genügend freier Spei
cherplatz zur Verfügung steht, so wird im Schritt S23 an den
Erzeuger-Programmabschnitt die erste Adresse des Pufferab
schnittes als Schreib-Zeiger sowie die ermittelte Größe an
freien Speicherplatz M2 ausgegeben.
Danach wird im Schritt S24 die Puffer-Synchronisation beendet,
wodurch auch andere Puffer-Dienstprogramm wieder auf den Puffer
und die internen Variablen der Synchronisations-Puffer-Klasse
zugreifen können. Mit dem Schritt S25 wird das Puffer-
Dienstprogramm GetToBufPntr beendet.
Ergibt die Abfrage im Schritt S20, dass grundsätzlich kein Puf
ferabschnitt zum Beschreiben frei ist, oder die Abfrage im
Schritt S22, dass der zur Verfügung stehende freie Speicher
platz kleiner als der benötigte Speicherplatz ist, so geht der
Programmablauf auf den Schritt S26 über, in dem abgefragt wird,
ob der Schreib-Zeiger, das heißt, die erste Adresse des zu be
schreibenden Pufferabschnittes, plus der angefragte Speicher
platz M1 das physikalische Ende des Puffers erreicht oder über
schritten haben.
Falls das physikalische Ende erreicht ist, geht der Pro
grammablauf auf den Schritt S27 über, in dem der Schreib-Zeiger
auf den physikalischen Anfang des Puffers, das heißt, dass die
erste Adresse des Puffers als physikalischer Anfang gespeichert
wird. Im darauffolgenden Schritt S28 wird die Puffer-
Synchronisation beendet und der Programmablauf geht zurück auf
den Schritt S18, wodurch das Puffer-Dienstprogramm GetToBufPntr
erneut begonnen wird.
Ergibt die Abfrage im Schritt S26, dass die Summe der Adresse
des Schreib-Zeigers und des angefragten Speicherplatzes M1
nicht auf das physikalische Ende des Puffers oder darüber hin
aus zeigt, so geht der Programmablauf auf den Schritt S29 über,
mit dem die Puffer-Synchronisation beendet wird, da im Schritt
S20 oder S22 bereits festgestellt worden ist, daß kein ausrei
chender Speicherplatz vorhanden ist. Im Schritt S30 wird ein
Warteprogramm durchlaufen, das auf vorbestimmte Ereignisse
(events) der weiteren Puffer-Dienstprogramme wartet und so lan
ge den Programmablauf des Puffer-Dienstprogramms GetToBufPntr
anhält. Im vorliegenden Fall wartet das Warteprogramm bis das
Puffer-Dienstprogramm ReleaseToBufPntr einen Pufferabschnitt
wieder freigibt. Beim Warten wird das Puffer-Dienstprograrrtm
GetToBufPntr eingeschläfert (angehalten). Das Puffer-
Dienstprogramm ReleaseToBufPntr erzeugt ein Signal (event), das
das Puffer-Dienstprogramm GetToBufPntr wieder weckt (fort
setzt). Somit wird durch das Warten die Rechenleistung der CPU
nicht beansprucht.
Da im Schritt S29 die Puffer-Synchronisation beendet worden
ist, kann während des Warteprogramms ein anderer Programmab
schnitt, insbesondere der Lese-Programmabschnitt auf den Puffer
und die internen Variablen der Synchronisations-Puffer-Klasse
zugreifen und im Puffer gespeicherte Daten auslesen. Hierdurch
kann beschreibbarer Speicherplatz im Puffer geschaffen werden.
Am Ende des Warteprogramms geht der Programmablauf wieder auf
den Schritt S18 über, mit dem das Puffer-Dienstprogramm GetTo
BufPntr von Neuem beginnt. Der Programmablauf ist identisch zu
dem oben erläuterten Programmablauf, weshalb eine erneute Be
schreibung nicht notwendig ist.
Mit dem Dienstprogramm GetToBufPntr werden der Schreib-Zeiger
und die zum Beschreiben zur Verfügung stehende Menge an Spei
cherplatz dem Erzeuger-Programmabschnitt mitgeteilt. Dieser
kann dann direkt in diesen Speicherbereich die Daten schreiben
(S4).
Mit dem Puffer-Dienstprogramm ReleaseToBufPntr (M3, <Datentyp<,
<Flagtyp<) wird der Schreibvorgang beendet (Fig. 8). Dieses
Puffer-Dienstprogramm beginnt mit dem Schritt S31 und startet
die Puffer-Synchronisation im Schritt S32. Dieser Schritt ent
spricht dem Schritt S18 des Puffer-Dienstprogramms GetToBufPntx
aus (Fig. 6). Im Schritt S33 werden die vom Erzeuger-
Programmabschnitt gelieferten Parameter, wie der beschriebene
Speicherplatz M3, Datentyp, Flagtyp eingelesen. Im Schritt S34
wird das Flag dieses Pufferabschnittes entsprechend dem einge
lesenen Parameter auf "gültig" oder "reserviert" gesetzt. Da
nach wird im Schritt S35 der Datentyp im Kontrollfeld gespei
chert. Typische Datentypen sind z. B. Daten, end of buffer, end
of file oder dergleichen.
Im Schritt S36 wird der Schreib-Zeiger aktualisiert, indem zu
dem bisherigen Schreib-Zeiger der Wert des beschriebenen Spei
cherplatzes addiert wird. Diese im Schreib-Zeiger abgespeicher
te Adresse ist nun die erste freie Adresse nach dem beschriebe
nen Pufferabschnitt.
Im Schritt S37 wird die Puffer-Synchronisation beendet und dar
aufhin wird im Schritt S38 das Puffer-Dienstprogramm ReleaseTo
BufPntr beendet.
Mit dem Puffer-Dienstprogramm ReleaseToBufPntr wird somit der
zuvor beschriebene Pufferabschnitt durch Setzen des Flags auf
"gültig" oder "reserviert" entweder zum Lesen durch den Lese-
Programmabschnitt freigegeben oder zunächst reserviert, um dann
später festzulegen, ob die Daten für das Lesen freigegeben wer
den oder verworfen werden.
Mit dem Puffer-Dienstprogramin SetResBufState kann ein oder meh
rere reservierte Pufferabschnitte für das Lesen freigegeben
oder verworfen werden (Fig. 10). Mit den Schritten S39 und S40
wird das Puffer-Dienstprogramm SetResBufState gestartet und die
Puffer-Synchronisation begonnen. Mit dem Schritt S41 wird der
Flagwert "gültig" oder "ungültig" vom Erzeuger-
Programznabschnitt übernommen. Danach wird S42 der oder die mit
dem Flag "reserviert" markierten Pufferabschnitte mit dem im
Schritt S41 übernommenen Flagwert markiert, so dass die darin
gespeicherten Daten entweder zum Lesen freigegeben werden
(Flag: gültig) oder verworfen werden (Flag: ungültig). Mit den
Schritten S43 und S44 wird die Puffer-Synchronisation beendet
und das Puffer-Dienstprogramn SetResBufState beendet.
Mit den drei oben erläuterten Puffer-Dienstprogrammen GetTo
BufPntr, ReleaseToBufPntr, SetResBufState kann ein Erzeuger-
Programmabschnitt, die von ihm erzeugten Daten in die Synchro
nisations-Puffer-Klasse schreiben und zum Lesen durch einen Le
se-Programmabschnitt freigeben.
Das Lesen von Daten beginnt der Lese-Programmabschnitt durch
Aufrufen des Puffer-Dienstprogramms GetFromBufPntr (Fig. 7).
Das Dienstprogramm GetFromBufPntr beginnt mit dem Schritt S45
und startet im Schritt S46 die Puffer-Synchronisation, so dass
kein anderer Programmabschnitt auf den Puffer und die internen
Variablen der Synchronisations-Puffer-Klasse zugreifen kann.
Mit dem Schritt S47 wird überprüft, ob der Lese-Zeiger auf das
Ende des physikalischen Puffers zeigt. Hierbei ist zu berück
sichtigen, dass am Ende des physikalischen Puffers immer ein
Pufferabschnitt ohne Daten steht, dem als Datentyp ein "end of
buffer" zugeordnet ist. Dies bedeutet, dass die Abfrage im
Schritt S47 lediglich abfragt, ob der Pufferabschnitt, auf dem
der Lese-Zeiger zeigt, den Datentyp "end of buffer" enthält.
Ist dies der Fall, so geht der Programmablauf auf den Anfang
des Puffers über, das heißt, der Lese-Zeiger wird auf die erste
Adresse des Puffers und somit den ersten Pufferabschnitt ge
setzt S48. Danach geht der Programmablauf auf den Schritt S49
über. Falls sich bei der Abfrage aus S47 ergeben hat, dass der
Lese-Zeiger nicht auf das Ende des Puffers zeigt, so geht der
Programmablauf direkt auf den Schritt S49 über.
Im Schritt S49 wird abgefragt, ob das Flag des Pufferabschnit
tes, auf den der Lese-Zeiger zeigt, den Wert "gültig" besitzt.
Falls dies der Fall ist, bedeutet dies, dass die in diesem Puf
ferabschnitt gespeicherten Daten zum Lesen freigegeben sind. In
diesem Fall geht der Programmablauf auf den Schritt S50 über,
mit dem der Lese-Zeiger, die Größe des Pufferabschnittes und
der Datentyp an den Lese-Programmabschnitt übergeben wird. Dies
erfolgt durch schreiben der entsprechenden Werte in drei Varia
blen, die beim Aufrufen von GetFromBufPntr vom Lese-
Programmabschnitt an die Synchronisations-Puffer-Klasse überge
ben werden.
Im darauffolgenden Schritt S51 wird die Puffer-Synchronisation
und danach das Puffer-Dienstprogramm GetFromBufPntr beendet
S52.
Sollte die Abfrage im Schritt S49 ergeben, dass die im Puf
ferabschnitt gespeicherten Daten nicht gültig sind, so geht der
Programmablauf auf den Schritt S53 über, mit dem die Puffer-
Synchronisation beendet wird. Im darauffolgenden Schritt S54
wird ein Warteprogramm ausgeführt. Da im vorhergegangenen
Schritt S53 die Puffer-Synchronisation beendet worden ist, kann
während der Ausführung des Warteprogramms der Erzeuger-
Programmabschnitt Daten in den Puffer schreiben bzw. Daten zum
Lesen freigeben, so dass es möglich ist, dass während des War
teprogramms für den Lese-Programmabschnitt lesbare Daten im
Puffer erzeugt werden. Dieses Warteprogramm arbeitet genauso
wie das des Puffer-Dienstprogramms GetToBufPntr, wobei es je
doch auf die Freigabe eines Pufferabschnittes durch das Puffer-
Dienstprogramm ReleaseFromBufPntr wartet.
Nach Beendigung des Warteprogramms geht der Programmablauf zu
rück auf den Schritt S46, womit dieses Puffer-Dienstprogramm
erneut begonnen wird. Der Ablauf ist der gleiche, wie er oben
beschrieben ist, weshalb eine erneute Beschreibung nicht not
wendig ist. Der Lese-Zeiger zeigt auf die zuerst eingeschriebe
nen Daten, die dementsprechend als erstes ausgelesen werden
(FIFO-Puffer).
Mit dem Puffer-Dienstprogramm GetFromBufPntr wird somit vom Le
se-Programmabschnitt die zum Lesen der Daten notwendigen Para
meter, wie der Lese-Zeiger, die Größe des Pufferabschnittes und
der Datentyp abgefragt. Anhand dieser Parameter kann der Lese-
Programmabschnitt die Daten aus dem Puffer lesen.
Der Lesevorgang wird vom Lese-Programmabschnitt durch Aufrufen
des Puffer-Dienstprogramms ReleaseFromBufPntr (Fig. 9) beendet.
Dieses Puffer-Dienstprogramm startet im Schritt S55 und beginnt
die Puffer-Synchronisation im Schritt S56. Im Schritt S57 wird
das Flag des zuletzt beschriebenen Pufferabschnittes auf "un
gültig" gesetzt, das heißt, dass der Pufferabschnitt zum Be
schreiben durch den Erzeuger-Programmabschnitt freigegeben ist.
Im Schritt S58 wird der Lese-Zeiger aktualisiert, das heißt,
dass zu der Adresse des bisherigen Lese-Zeigers der Betrag der
gelesenen Datenmenge addiert wird. Der Lese-Zeiger zeigt somit
auf die erste Adresse des nächsten, noch nicht gelesenen Puf
ferabschnittes.
Im Schritt S59 wird die Puffer-Synchronisation und im Schritt
S60 das Puffer-Dienstprogramm ReleaseFromBufPntr beendet.
In Fig. 11a und 11b und Fig. 12 sind Flussdiagramme der beiden
Puffer-Dienstprogramme GetFromBufPntr und ReleaseFromBufPntr
gezeigt, die das Lesen der Daten in Blöcken erlauben, deren
Länge variabel ist und bezüglich der Länge der Pufferabschnitte
abweicht.
Das Puffer-Dienstprogramm GetFromBufPntr startet mit dem
Schritt S61 und beginnt im Schritt S62 die Puffer-
Synchronisation. Im Schritt S63 wird vom Lese-Programmabschnitt
der Parameter einer relativen Position eingelesen. Im folgenden
Schritt S64 wird abgefragt, ob die Daten des Pufferabschnittes
(auf den der Lese-Zeiger zeigt) gültig sind und ob das Ende des
Puffers erreicht ist. Falls beides zutrifft geht der Pro
grammablauf auf den Schritt S65 über, mit dem der Programmzei
ger auf den physikalischen Anfang des Puffers gesetzt wird. Da
nach geht der Programmablauf auf den Schritt S66 über.
Ergibt die Abfrage im Schritt S64 hingegen, dass entweder die
Daten ungültig sind oder das Ende vom Puffer erreicht ist, so
geht der Programmablauf direkt auf den Schritt S66 über.
Im Schritt S66 wird abgefragt, ob die Daten gültig sind und ob
die relative Position größer als oder gleich zu diesem Puf
ferabschnitt ist. Die relative Position ist eine relative
Adresse bzw. Sprungadresse, die den Adresssprung vom Lese-
Zeiger zum Beginn des jeweils auszulesenden Bereichs angibt.
Diese relative Adresse entspricht einer Datenmenge, die in die
sem Adressbereich gespeichert werden kann. Im Schritt S66 wird
diese Datenmenge mit der Datenmenge des Pufferabschnittes ver
glichen. Ergibt die Abfrage im Schritt S66, dass die Daten gül
tig sind und die relative Position größer als oder gleich zum
Pufferabschnitt ist, so bedeutet dies, dass der Lesevorgang die
Grenze von einem zu einem anderen Pufferabschnitt überschritten
hat, und dass Daten eines weiteren Pufferabschnittes ausgelesen
werden sollen. Da das Flag dieses weiteren Pufferabschnittes
bisher nicht geprüft worden ist, wird der Lese-Zeiger auf den
Anfang des nächsten Pufferabschnittes gesetzt und die relative
Position angepaßt S67 und die Puffer-Synchronisation beendet
S68. Der Programmablauf geht dann vom Schritt S68 wieder auf
den Schritt S62, so daß die oben erläuterten Verfahrensschritte
von neuem ausgeführt und die Daten des weiteren Pufferabschnit
tes auf ihre Gültigkeit überprüft werden.
Ergibt die Abfrage im Schritt S66, dass die Daten nicht gültig
sind, oder dass die relative Position kleiner als die Größe des
Pufferabschnitts ist, so geht der Programmablauf auf den
Schritt S69 über, in dem erneut die Gültigkeit der Daten über
prüft wird. Sind die Daten nicht gültig, so geht der Pro
grammablauf auf die Schritte S70 und S71 über, mit welchen die
Puffer-Synchronisation beendet und ein Warteprogramm ausgeführt
wird, das die Freigabe des Pufferabschnittes durch das Puffer-
Dienstprogramm ReleaseToBufPntr abwartet. Die Schritte S69 bis
S71 entsprechen den Schritten S43, S53, S54 der ersten Ausfüh
rungsform des Puffer-Dienstprogrammes GetFromBufPntr.
Ergibt die Abfrage im Schritt S69, dass die Daten gültig sind,
so geht der Programmablauf auf den Schritt S72 über, in dem ab
gefragt wird, ob die Datenmenge des auszulesenden Datenblocks
größer als der Pufferabschnitt ist. Ergibt die Abfrage im
Schritt S72, dass die Datenmenge des auszulesenden Datenblocks
nicht größer als der auszulesende Pufferabschnitt ist, so geht
der Programmablauf auf den Schritt S73 über, mit dem die Para
meter der Größe des auszulesenden Datenblocks und der Datentyp
an den Lese-Programmabschnitt ausgegeben werden. Danach wird im
Schritt S74 die Puffer-Synchronisation und im Schritt S75 das
Puffer-Dienstprogramm GetFromBufPntr beendet.
Ergibt die Abfrage im Schritt S72, dass der auszulesende Daten
block größer als der Pufferabschnitt ist, so bedeutet dies,
dass mit einem einzigen Datenblock Daten eines Pufferabschnit
tes und Daten eines weiteren Pufferabschnittes ausgelesen wer
den. Es wird deshalb im Schritt S76 abgefragt, ob die Daten des
nächsten Pufferabschnittes gültig sind. Ergibt die Abfrage,
dass die Daten nicht gültig sind, so geht der Programmablauf
auf den Schritt S70 über, ansonsten geht der Programmablauf auf
den Schritt S77 über, mit dem abgefragt wird, ob das Ende des
Puffers erreicht ist. Ist das Ende des Puffers noch nicht er
reicht, so können die Daten unmittelbar ausgelesen werden und
der Programmablauf geht auf den Schritt S73 über. Ansonsten
geht der Programmablauf auf den Schritt S78 über, mit dem ge
prüft wird, ob die Daten am Anfang des Puffers gültig sind.
Sind diese Daten nicht gültig, so geht der Programmablauf wie
der auf den Schritt S70 über, der zur Warteschlange im Schritt
S71 führt. Ansonsten geht der Programmablauf auf den Schritt
S79 über, mit dem die Daten vom Anfang des Puffers in den letz
ten an sich leeren Pufferabschnitt kopiert werden, der das Ende
des Puffers bildet und mit einem "end of buffer" markiert ist.
Hierdurch kann über das Ende des letzten Puffers hinaus ein
vollständiger Datenblock ausgelesen werden, weshalb der Pro
grammablauf wieder auf den Schritt S73 übergeht, mit dem die
entsprechenden Parameter an den Lese-Programmabschnitt ausgege
ben werden.
Nach dem Ausführen von GetFromBufPntr kann der Lese-
Programmabschnitt einen Block aus dem Puffer lesen.
Nach dem Lesen eines Blockes wird das Puffer-Dienstprogramm Re
leaseFromBufPntr (Fig. 12) aufgerufen. Dieses Puffer-
Dienstprogramm beginnt im Schritt S80 und startet im Schritt
S81 die Puffer-Synchronisation. Im Schritt S82 werden vom Lese-
Programmabschnitt die Parameter der relativen Position und der
Größe des gelesenen Blockes eingelesen. Daraufhin wird abge
fragt S83, ob die relative Position plus der Größe des eingele
senen Blockes größer als der Pufferabschnitt sind. Ist dies der
Fall, so bedeutet dies, dass ein gesamter Pufferabschnitt gele
sen worden ist. Der Programmablauf verzweigt dann auf den
Schritt S84, in dem das Flag des gelesenen Pufferabschnittes
auf "ungültig" gesetzt wird.
Im darauffolgenden Schritt S85 werden der Lese-Zeiger und die
relative Position aktualisiert, wobei in den Lese-Zeiger die
erste Adresse des auf den ausgelesenen Pufferabschnitt folgen
den Pufferabschnitts eingesetzt wird und als relative Position
die Differenz zwischen der auf den aus dem Puffer ausgelesenen
Pufferabschnitt folgenden Adresse und dem neuen Lese-Zeiger ge
speichert wird. Die Summe des neuen Lese-Zeigers und die rela
tiven Position zeigen somit auf die erste Adresse des auf den
ausgelesenen Pufferabschnitts folgenden Speicherbereiches im
Puffer.
Im Schritt S86 wird die Puffer-Synchronisation und im Schritt
S87 das Puffer-Dienstprogramm beendet.
Ergibt die Abfrage im Schritt S83, dass die Summe aus der rela
tiven Position und der Größe des ausgelesenen Blockes kleiner
als oder gleich zum Pufferabschnitt ist, so bedeutet dies, dass
der Pufferabschnitt, aus dem ein Block gelesen worden ist, noch
nicht vollständig ausgelesen ist. Deshalb kann das Flag des
Pufferabschnittes noch nicht auf "ungültig" gesetzt werden, wo
durch der Pufferabschnitt zur weiteren Beschreibung freigegeben
werden würde und nicht mehr vollständig ausgelesen werden könn
te.
Mit den in Fig. 11, 11b und Fig. 12 gezeigten Puffer-
Dienstprogrammen können somit Datenblöcke ausgelesen werden,
deren Größe sich von den gespeicherten Pufferabschnitten unter
scheidet. Dies ist in Fig. 4 beispielhaft dargestellt. Fig. 4
zeigt einen Puffer mit insgesamt sechs Pufferabschnitten PA1
bis PA6. Im vorliegenden Ausführungsbeispiel weisen alle Puf
ferabschnitte die gleiche Größe auf. Es ist jedoch auch mög
lich, dass die einzelnen Pufferabschnitte unterschiedliche Grö
ßen besitzen. In die Pufferabschnitte PA4, PA5, PA1 und PA2
sind vom Erzeuger-Programmabschnitt Dateneinheiten N, N+1, N+2
und N+3 geschrieben worden. Dementsprechend sind die Flags die
ser Pufferabschnitte PA4, PA5, PA1 und PA2 auf "gültig" ge
setzt. Der Pufferabschnitt PA3 enthält keine zum lesen vorgese
henen Daten, weshalb dessen Flag auf "ungültig" gesetzt ist.
Der Pufferabschnitt PA6 enthält zunächst keine Daten und ist
mit einem "end of buffer" markiert, das heißt, dass er das phy
sikalische Ende des Puffers darstellt.
Zu Beginn des Lesevorgangs durch den Lese-Programmabschnitt
steht der Lese-Zeiger auf der ersten Adresse des Pufferab
schnittes PA4, der die ersten eingeschriebenen Daten enthält.
In Fig. 4 ist gezeigt, dass der Lese-Programmabschnitt Daten
mittels vier Blöcken X, X+1, X+2 und X+3 ausliest. Diese Blöcke
sind kleiner als die Pufferabschnitte. Nach dem Auslesen der
Blöcke X und X+1 werden Daten aus dem Pufferabschnitt PA1 in
den Pufferabschnitt PA6 kopiert, damit beim nächsten Lesen des
Blockes X+2 beim Überschreiten der Grenze zwischen den Puf
ferabschnitten PA5 und PA6 eine durchgehende Datenmenge gelesen
werden kann. Dieses Kopieren der Daten von PA1 auf PA6 wird im
Schritt S79 des Puffer-Dienstprogrammes GetFromBufPntr (Fig.
11) ausgeführt. Ist der Block X+2 gelesen, so wird festge
stellt, dass der Lese-Zeiger auf das physikalische Ende des
Puffers zeigt S64, weshalb der Lese-Zeiger auf den Anfang des
Puffers gesetzt wird S65. Durch die relative Position wird si
chergestellt, dass vom Pufferabschnitt PA1 lediglich die Daten
ausgelesen werden, die nicht bereits durch den Block X+2 aus
dem Pufferabschnitt PA6 gelesen worden sind.
Das obige Ausführungsbeispiel zeigt Blöcke, die kleiner als die
Pufferabschnitte sind. Grundsätzlich ist es jedoch auch mög
lich, mit Blöcken auszulesen, die größer als die Pufferab
schnitte sind. Die Blöcke können am obigen Ausführungsbeispiel
die doppelte Größe der Pufferabschnitte besitzen.
Anhand der oben erläuterten Ausführungsbeispiele kann man gut
erkennen, dass die Steuerung des Datentransfers zwischen zwei
Programmabschnitten alleine durch die Synchronisations-Puffer-
Klasse, das heißt dem Puffer, den dem Puffer zugeordneten Ver
waltungsdaten, wie dem Flag, und den Puffer-Dienstprogrammen
ausgeführt wird. Die Programmabschnitte müssen zur Gewährlei
stung eines fehlerfreien Datentransfers zum Schreiben und zum
Lesen lediglich die Puffer-Dienstprogramme aufrufen, mit wel
chen in den Programmabschnitten die zum Lesen und Schreiben
notwendigen Parameter übergeben werden und die einen unerlaub
ten Zugriff auf den Puffer verhindern.
Ein weiterer Vorteil des erfindungsgemäßen Verfahrens ist, dass
durch die separate Datenschnittstelle zwischen jedem Puffer und
dem Programmabschnitt das gesamte Computerprogramm schnell um
strukturiert werden kann, indem lediglich ein Programmabschnitt
die Daten in einen anderen Puffer schreibt oder aus einem ande
ren Puffer liest. Dies lässt sich einfach und schnell durch Än
dern eines entsprechenden Klassen-Zeigers bewerkstelligen. Fig.
2 zeigt eine derartige Änderung, bei der der Daten verarbeiten
de Programmabschnitt einfach entfernt worden ist, indem der
Programmabschnitt "Daten schreiben" P3 seine Daten unmittelbar
aus dem Eingabepuffer ausliest. Dies wird einfach durch Ändern
des Zeigers des Programmabschnittes "Daten schreiben" P3 auf
den Eingabepuffer ausgeführt.
Die Erfindung ist oben anhand von Ausführungsbeispielen näher
erläutert worden, bei welchen jeweils ein Puffer zwischen zwei
Programmabschnitten angeordnet ist, wobei jeweils ein Erzeuger-
Programmabschnitt in dem Puffer Daten schreiben und ein Lese-
Programmabschnitt aus dem Puffer Daten lesen kann. Im Rahmen
der Erfindung ist es jedoch möglich, dass beispielsweise mehre
re Programmabschnitte in einen Puffer schreiben bzw. aus einem
Puffer lesen. Hierzu müssen die einzelnen Puffer-
Dienstprogramme lediglich dahingehend abgewandelt werden, dass
die Programmabschnitte nicht gleichzeitig auf den Puffer zu
greifen können. Gegebenenfalls kann es zweckmäßig sein, mit dem
Flag anzugeben, welche Daten für welchen Programmabschnitt vor
gesehen sind.
Das erfindungsgemäße Verfahren ist zum Synchronisieren von Pro
grammabschnitten vorgesehen, die auf einen Computer mit mehre
ren Prozessoren auf den einzelnen Prozessoren parallel ablaufen
können. Das erfindungsgemäße Verfahren kann selbstverständlich
auch auf einem Computer mit einem einzigen Prozessor ausgeführt
werden.
Die Erfindung ist oben anhand eines Ausführungsbeispiels be
schrieben, bei welchem Daten reserviert werden können. Im Rah
men der Erfindung ist es selbstverständlich auch möglich, daß
das Flag lediglich auf die beiden Zustände "gültig" oder "un
gültig" gesetzt werden kann. Bei einer solchen vereinfachten
Ausführungsform entfällt das Puffer-Dienstprogramm SetResBuf
State.
Zum Initialisieren des Puffers ist ein entsprechendes Initiali
sationsprogramm vorgesehen. Mit diesem Initialisationsprogramm
wird der Speicherbereich festgelegt, den der Puffer in Anspruch
nimmt. Er kann je nach Bedarf eingestellt werden. Die Anzahl
der Pufferabschnitte kann dementsprechend variieren, zumal die
Länge der einzelnen Pufferabschnitte unterschiedlich sein kann.
Das erfindungsgemäße Verfahren kann als Bestandteil eines Be
triebssystems eines Computers realisiert sein. Es kann daher
als auf einem Datenträger speicherbares oder über ein Datennetz
übertragbares Computerprogramm ausgebildet sein. Die Pufferein
richtung kann insbesondere als Speicherbaustein ausgebildet
sein. Es ist jedoch auch möglich, eine Puffereinrichtung mit
einer Hardwareschaltung vorzusehen, z. B. einen anwenderspezifi
schen integrierten Schaltkreis (ASIC) mit entsprechend inte
grierten Pufferspeichern, die das erfindungsgemäße Verfahren
ausführt.
In den Fig. 13 und 14 ist jeweils schematisch vereinfacht
ein Computer Co mit einem Betriebssystem BS dargestellt, worin
das erfindungsgemäße Verfahren integriert ist. Der Computer
weist entweder einen einzigen Prozessor (CPU in Fig. 13) oder
zwei Prozessoren (CPU1 und CPU2 in Fig. 14) auf. Die Computer
besitzen jeweils einen Permanentspeicher P-Sp und einen Ar
beitsspeicher RAM. Der Permanentspeicher P-Sp wird beispiels
weise durch ein Festplattenlaufwerk, ein Diskettenlaufwerk
und/oder einen ROM-Speicher dargestellt. Der Arbeitsspeicher
RAM ist typischerweise ein Halbleiterspeicher. Der bzw. die
Prozessoren kommunizieren in den dargestellten Ausführungsbei
spielen mit dem Permanentspeicher P-Sp und dem Arbeitsspeicher
RAM über einen Datenbus B.
Bevor einer der beiden Computer gestartet wird, ist das Be
triebssystem BS und das vollständige Computerprogramm Co-Pr im
Permanentspeicher P-Sp gespeichert. Beim Starten des Computers
Co und beim Aufrufen des Computerprogramms Co-Pr durch einen
Benutzer werden die zur Ausführung benötigten Teile des Be
triebssystems BS und des Computerprogramms Co-Pr in den Ar
beitsspeicher RAM geladen, auf den der bzw. die Prozessoren
CPU, CPU1, CPU2 zum Ausführen derselben zugreifen.
Das Betriebssystem umfaßt Puffer-Programme Pu-Pr, wie z. B. ein
Initialisationsprogramm und die Puffer-Dienstprogramme. Das In
itialisationsprogramm wird z. B. nach dem Starten des Computers
aufgerufen, wodurch im Arbeitsspeicher ein Abschnitt für den
Puffer Pu reserviert wird. In den dargestellten Ausführungsfor
men ist der Puffer Pu im Bereich des Betriebssystems BS ange
ordnet. Es ist jedoch auch möglich, den Puffer in einem vom Be
triebssystem BS unabhängigen Speicherabschnitt des Arbeitsspei
chers auszubilden.
Bei dem Computer Co nach Fig. 13, der einen einzigen Prozessor
aufweist, werden alle Programmabschnitte auf dem einen einzigen
Prozessor ausgeführt. Bei dem Computer Co nach Fig. 14 mit zwei
Prozessoren werden die Programmabschnitte auf die beiden Pro
zessoren verteilt, d. h. ein Teil der Programmabschnitte wird
auf einem Prozessor und der andere Teil auf dem anderen Prozes
sor ausgeführt. Diese Aufteilung auf unterschiedliche Prozesso
ren erfolgt selbsttätig durch das Betriebssystem BS.
Die Software (Betriebssystem BS und Computer-Programm Co-PR)
der beiden in Fig. 13 und 14 dargestellten Computer ist iden
tisch. Das Betriebssystem erkennt die mehreren Prozessoren ge
mäß Fig. 14 und führt dann diese Aufteilung selbsttätig durch.
Geeignete Betriebssysteme, in die das erfindungsgemäße Verfah
ren integriert werden kann bzw. unter denen Programmabschnitte
zur Durchführung des erfindungsgemäßen Verfahrens ablaufen kön
nen, sind Windows NT und Mehrprozessor-Versionen von UNIX.
Obwohl in den oben beschriebenen Ausführungsbeispielen die Pro
grammabschnitte hauptsächlich als Threads ausgeführt werden,
können diese Programmabschnitte auch durch andere Teile von
Software,- oder Firmwareprogrammen umgesetzt werden.
Bezugszeichenliste
P0. .P3 Programmabschnitte
PU1, PU2 Puffer
DT Datentransfer
PF Pfeil
PA1. .PA6 Pufferabschnitte
P-Sp Permanentspeicher
RAM Arbeitsspeicher
B Datenbus
CPU Prozessor
CPU1 Prozessor
CPU2 Prozessor
Co-Pr Computerprogramm
Bs Betriebssystem
Pu-Pr Puffer-Programme
FU Puffer
Verfahrensschritte
S1 Anfang
S2 Teil einer Programmausführung
S3 GetToBufPntr
S4 Daten in den Puffer schreiben
S5 ReleaseToBufPntr
S6 Teil einer Programmausführung
S7 SetResBufState
S8 Teil einer Programmausführung
S9 Ende
S10 Anfang
S11 Teil einer Programmausführung
S12 GetFromBufPntr
S13 Daten vom Puffer lesen
S14 ReleaseFromBufPntr
S15 Teil einer Programmausführung
S16 Ende
S17 Anfang
S18 Beginn der Puffer-Synchronisation
S19 Parameterübergabe
S20 Abfrage: Steht ein Pufferabschnitt zum Beschreiben zur
Verfügung?
S21 Berechnung der Größe des zur Verfügung stehenden Speicher
platzes
S22 Abfrage: Zur Verfügung stehender Speicherplatz < = ange
fragter Speicherplatz?
S23 Ausgabe von Parametern
S24 Ende der Puffer-Synchronisation
S25 Ende
S26 Abfrage: Ende vom Puffer?
S27 Gehe zum Anfang vom Puffer
S28 Ende der Puffer-Synchronisation
S29 Ende der Puffer-Synchronisation
S30 Warteprogramm
S31 Anfang
S32 Beginn der Puffer-Synchronisation
S33 Einlesen von Parameter
S34 Setze Flag (gültig/reserviert)
S35 Speicherdatentyp
S36 Aktualisiere Schreib-Zeiger
S37 Ende Puffer-Synchronisation
S38 Ende
S39 Anfang
S40 Beginn der Puffer-Synchronisation
S41 Einlesen von Parametern
S42 Setze Flag (gültig/ungültig)
S43 Ende der Puffer-Synchronisation
S44 Ende
S45 Anfang
S46 Beginn der Puffer-Synchronisation
S47 Abfrage: Ende vom Puffer?
S48 Gehe zum Anfang vom Puffer
S49 Abfrage: Daten gültig?
S50 Parameter ausgeben
S51 Ende der Puffer-Synchronisation
S52 Ende
S53 Ende der Puffer-Synchronisation
S54 Warteprogramm
S55 Anfang
S56 Beginn der Puffer-Synchronisation
S57 Setze Flag auf "ungültig"
S58 Aktualisiere Lese-Zeiger
S59 Ende der Puffer-Synchronisation
S60 Ende
S61 Anfang
S62 Beginn der Puffer-Synchronisation
S63 Parameter einlesen
S64 Abfrage: Daten gültig & Ende von Puffer?
S65 Gehe zum Anfang vom Puffer
S66 Daten gültig & relative Position < = Pufferabschnitt?
S67 Aktualisiere Schreib-Zeiger
S68 Ende der Puffer-Synchronisation
S69 Abfrage: Daten gültig?
S70 Ende der Puffer-Synchronisation
S71 Warteprogramm
S72 Abfrage: Größe des auszulesenden Datenblocks < Pufferab
schnitt?
S73 Übergabe von Parametern
S74 Ende der Puffer-Synchronisation
S75 Ende
S76 Abfrage: Sind die Daten des nächsten Pufferabschnittes
gültig?
S77 Abfrage: Ende vom Puffer?
S78 Abfrage: Sind die Daten am Anfang des Puffers gültig?
S79 Kopiere Daten vom Anfang des Puffers zum Ende
S80 Anfang
S81 Beginn der Puffer-Synchronisation
S82 Einlesen von Parametern
S83 Abfrage: Relative Position & Blockgröße < Pufferabschnitt?
S84 Setze Flag auf "ungültig"
S85 Aktualisiere Lese-Zeiger und relative Position
S86 Ende der Puffer-Synchronisation
S87 Ende