|
|
DataMuseum.dkPresents historical artifacts from the history of: Bogika Butler |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Bogika Butler Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 15616 (0x3d00)
Types: TextFile
Names: »PIPE.SA«
└─⟦2322e079b⟧ Bits:30009789/_.ft.Ibm2.50006594.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »PIPE.SA«
└─⟦311ba069f⟧ Bits:30009789/_.ft.Ibm2.50006625.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »PIPE.SA«
└─⟦49237ce80⟧ Bits:30009789/_.ft.Ibm2.50006627.imd Mogens Pelles Zilog 80,000 / EOS projekt
└─⟦this⟧ »PIPE.SA«
æ*****************************************************************
Copyright 1984 by
NCR Corporation
Dayton, Ohio U.S.A.
All Rights Reserved
******************************************************************
EOS Software produced by:
NCR Systems Engineering - Copenhagen
Copenhagen
DENMARK
*****************************************************************å
æ PipeFs ver. 2.00 84-1-2
2.00 83-01-02 Navne skal slutte med 'r' eller 'w'
å
æ$Eå
OBJECT PROGRAM pipe;
æ **************************************************************
The program is an EOS filesystem used by the Unix pipe call.
The program creates a reader and a writer for each pipe.
Since the reader is the owner of the shared data segment,
the gates and conditions, the reader has to be created before
the corresponding writer.
When a reader is created it is checked that there does not
exists a reader with the same name.
When a writer is created it is checked that there exists a reader
with the same name. The writer is given an envelope pointer to the
corresponding reader. It is not checked if there already exists a
writer with the same name.
If the writer is closed before the reader, the reader is allowed
to empty the buffer. This is done by setting a condition in the shared
data segment (wrclosed) and signal the reader. Readers calling the pipe
when the buffer is empty and the writer is closed, are returned with
result = OK and bytecount = 0.
If the reader is closed before the writer, it is ensured that
all the writer processes are waiting on either a gate or a condition.
This is done by locking the pipegate in the closeread termination
procedure. The reason is to avoid a process to address the shared data
segment, which would be an error in a system without memory protection.
Writers calling the pipe after the reader is closed are returned
with result = pipechrash.
*********************************************************************** å
æ$L-å
æ$F=family.univ.idå
æ$Eå
æ$F=family.knel.idå
PROCEDURE PrintText (text: fullid); FORWARD;
PROCEDURE PrintVar (text: fullid; univ v: blockPtr); FORWARD;
æ$Eå
æ****** E X P O R T D E S C R I P T I O N ******å
æ*************************************************å
æ$F=family.iosys.idå
æ$Eå
æ****** I M P O R T D E S C R I P T I O N ******å
æ*************************************************å
æ$F=family.alloc.idå
æ$Eå
æ$F=family.sched.idå
æ$Eå
æ****** E X T E R N A L P R O C E D U R E S ******å
æ***************************************************å
æNONEå
æ$L+å
æ$Eå
æ****** C O N S T A N T S A N D T Y P E S ******å
æ***************************************************å
CONST
maxIdLength = 48;
orgNo = 00;
orgSys = 4006;
reject = -1;
status = 1;
space = ' ';
bufsize = 900;
bufsz = 9;
readRg = 1;
writeRg = 2;
NoControl = 0;
pipechrash = 11;
Type
PipeData = RECORD
Name : arrayÆ1..maxIdLengthÅ of char;
Namelength: integer;
Freelist,Writespace,Readspace: integer;
rdptr,wrptr: integer;
readlength,writelength: integer;
wrclosed: boolean;
buf: arrayÆ0..bufszÅ of byte;
END;
æ$Eå
æ****** G L O B A L P R O C E D U R E S ******å
æ***********************************************å
FUNCTION MakeRes (main, family, auxcause, argno: integer)
: ResultType;
var
r: resultType;
BEGIN
r.main := main;
r.family := family;
r.argno := argno;
r.auxcause := auxcause;
r.orgno := orgno;
r.orgsys := orgsys;
MakeRes := r;
END; æMakeReså
FUNCTION checkname (length: integer; univ dest, source: blockPtr): boolean;
VAR i,max1,max2: integer;
BEGIN
checkname := true;
max1:= elements(source);
max2:= length;
IF max1 <> max2 THEN
checkname:= false
ELSE
BEGIN
FOR i:= 1 to max1 DO
IF sourceÆiÅ <> destÆiÅ THEN
checkname:= false;
END;
END;
PROCEDURE Check (res: resultType);
BEGIN
IF res.main <> OK THEN printVar ('*** pipe check *** res = ',res);
æ#B# printvar ('*** PIPE CHECK *** RES = ',res); #E#å
IF res.main <> OK THEN Exception (res);
END;
PROCEDURE CopyBytes (univ source, dest: blockPtr);
var i, max: integer;
BEGIN
max := elements(source);
if max > elements (dest) then max := elements (dest);
for i := 1 to max do destÆiÅ := sourceÆiÅ;
END;
PROCEDURE FillBytes (univ b: byte; univ dest: blockPtr);
var i: integer;
BEGIN
for i := 1 to elements (dest) do destÆiÅ := b;
END;
æ$Eå
æ****** P A O L O C A L P O I N T E R S ******å
æ*************************************************å
TYPE
readref = ^^rdPaoLocals;
RdPaoLocals = RECORD
code : ^^;
pipe : ^^pipedata;
PipeGate : ^^Gate;
wrfifo : ^^Gate;
rdfifo : ^^Gate;
Rdcond : ^^Condition;
Wrcond : ^^Condition;
END;
writeref = ^^wrPaoLocals;
wrPaoLocals = RECORD
code : ^^;
readEnv : readref;
END;
æ$Eå
æ****** P I P E S Y S L O C A L P O I N T E R S ******å
æ*********************************************************å
pipeSysRef = ^^PipeSysLocals;
pipeSysLocals = RECORD
code : ^^;
allocref : ^^allocate;
schedref : ^^scheduler;
rdPaoMan : ^^;
wrPaoMan : ^^;
rdPaoEnv : readref;
wrPaoEnv : writeref;
END;
æ$Eå
æ****** I M P L E M E N T R E A D P A O ******å
æ***********************************************å
PROGRAM RDPAOIMPLEMENT OBJECT FAO WITH RDPAOLOCALS;
ENTRY readseq
æsegment; OUT bytecountå
WITH RECORD
t : ^^;
END;
VAR res: resultType;
BEGIN
æ#B# PrintText('---pipe.readseq---'); #E#å
check (propagate(propreject));
check(rdfifo.lock);
IN
check(pipegate.lock);
with p = pipe^^ ,S = segment^^ do
BEGIN
bytecount := 0;
p.readlength:= elements(S);
IN
WHILE bytecount < p.readlength do
BEGIN
IF bufsize - p.freelist > 0 THEN
BEGIN
æ#B# PrintText ('---buffer is NOT empty---'); #E#å
bytecount := bytecount + 1;
SÆbytecountÅ := p.bufÆp.rdptrÅ;
p.rdptr := (p.rdptr + 1) mod bufsize;
p.freelist := p.freelist + 1;
p.writespace := p.writespace - 1;
if p.writespace = 0 THEN
check(wrcond.signal);
END
ELSE
BEGIN æthe buffer is emptyå
IF p.wrclosed THEN
exception(okresult);
p.readspace := p.readlength - bytecount;
IF p.readspace > bufsize THEN
p.readspace := bufsize;
æ#B# PrintVar ('---buf EMPTY--- readspace = ',p.readspace); #E#å
check (rdcond.wait);
END;
END; æwhileå
DO
p.readspace := 0;
END; æwithå
check(pipegate.open);
DO ;
check(rdfifo.open);
END;
OTHERWISE rdpother
WITH RECORD
t : ^^;
END;
BEGIN
Exception (MakeRes(reject*EntryIllegal,universal,0,0));
END; æOTHERWISEå
END; æRDPAOIMPLEMENTå
æ$Eå
PROGRAM WRPAOIMPLEMENT OBJECT FAO WITH WRPAOLOCALS;
ENTRY writeseq
æsegment; OUT bytecountå
WITH RECORD
t : ^^;
END;
VAR res, ignore: resultType;
BEGIN
æ#B# PrintText('---pipe.writeseq---'); #E#å
check (propagate(propreject));
IN
check(readEnv^^.wrfifo.lock);
check(readEnv^^.pipegate.lock);
WITH p = readEnv^^.pipe^^ ,S = segment^^ do
BEGIN
bytecount:= 0;
p.writelength:= elements(S);
IN
WHILE bytecount < p.writelength do
BEGIN
IF p.freelist > 0 THEN
BEGIN
æ#B# PrintText ('---buffer is NOT full---'); #E#å
bytecount := bytecount + 1;
p.bufÆp.wrptrÅ := SÆbytecountÅ;
p.wrptr := (p.wrptr + 1) mod bufsize;
p.freelist := p.freelist - 1;
p.readspace := p.readspace - 1;
IF p.readspace = 0 THEN
check(readEnv^^.rdcond.signal);
END
ELSE
BEGIN æ the buffer is full å
p.writespace := p.writelength - bytecount;
IF p.writespace > bufsize THEN
p.writespace := bufsize;
æ#B# PrintVar ('---buf FULL--- writespace = ',p.writespace); #E#å
check(readEnv^^.wrcond.wait);
END;
END; æwhile å
DO BEGIN
p.writespace:= 0;
res:= getexception;
IF res.main <> speededup THEN
res:= makeres(status*pipechrash,iofamily,0,0);
ignore := readEnv^^.pipegate.open;
ignore := readEnv^^.wrfifo.open;
objreturn(res);
END;
END; æwithå
check(readEnv^^.pipegate.open);
DO BEGIN
res := getexception;
IF res.main <> speededup THEN
res := makeres(status*pipechrash,iofamily,0,0);
ObjReturn(res);
END;
check(readEnv^^.wrfifo.open);
END;
OTHERWISE wrpother
WITH RECORD
t : ^^;
END;
BEGIN
Exception (MakeRes(reject*EntryIllegal,Universal,0,0));
END; æotherwiseå
END; æ wrpaoimplement å
æ$Eå
æ****** I M P L E M E N T P I P E F I L E S Y S T E M ******å
æ****************************************************************å
PROGRAM pipesysImplement OBJECT iosys WITH pipesyslocals;
æ****** A S S I G N ******å
æ*************************å
PRIVATE closeread;
PRIVATE closewrite;
ENTRY assign
æOUT ownedfao; IN filename, IN iorights, OPTIONAL IN createmode,
volumeå
WITH RECORD
t : ^^;
tempEnv: readref;
END;
VAR res,ignore: resultType;
PROCEDURE readpao;
VAR nullSize,voidSize,Size: sizeType;
i,used: integer;
found: boolean;
BEGIN
æ The procedure creates a fao for reading a pipe,
a pipedata segment ,two gates and two conditions å
æ Allocate fao object å
æ#B# PrintText('---pipe.readpao---'); #E#å
æcheck if the file already exists å
found:= false;
res:= FirstInSet (rdpaoMan,tempEnv);
IF res.main = OK THEN
BEGIN
WHILE (res.main = OK) AND NOT found do
BEGIN
WITH p = tempEnv^^.pipe^^ do
BEGIN
IF checkname (p.namelength,p.name,
filenameÆ1..elements(filename)-1Å)
THEN found := true;
END; æ with å
res:= NextInSet (rdpaoMan,tempEnv);
END; æwhile å
IF found THEN
Exception (MakeRes(reject*4,iofamily,0,0));
END;
check (clearSize (size));
check (addGen (size,refs(rdpaolocals)));
check (addEmbSeg (size, bytes(pipedata)));
check(allocref.NewObj (OUT ownedfao; IN size, OUT i));
æ make fao a generel object å
check (clearSize (nullsize));
voidSize.user := -1; voidSize.kernel := -1;
check (DeclGen (ownedfao,rdpaoMan,rdpaoEnv,refs(rdpaoLocals),
closeread,nullSize,voidSize,refs(rdpaoImplement),
bytes(rdpaoImplement),nocontrol,addr(rdpaoImplement),
nullsize,true));
IN
æ create pipe data segment å
check (newSeg (rdpaoEnv^^.pipe, bytes(pipedata)));
æ copy code pointer å
check (copy (code, rdpaoEnv^^.code));
æ initialize pipedata variables å
WITH p = rdpaoEnv^^.pipe^^ do
BEGIN
fillBytes (' ',p.name);
copyBytes (filenameÆ1..elements(filename)-1Å,p.name);
IF elements(filename) > maxIdLength THEN
p.namelength := maxIdLength
ELSE
p.namelength := elements(filename)-1;
p.freeList := bufsize;
p.writespace := -1;
p.readspace := -1;
p.rdptr := 0;
p.wrptr := 0;
p.wrclosed := false;
END;
æ create gateobject and conditions å
check (schedref.NewGate (OUT rdpaoEnv^^.pipegate));
check (schedref.NewGate (OUT rdpaoEnv^^.wrfifo));
check (schedref.NewGate (OUT rdpaoEnv^^.rdfifo));
check (rdpaoEnv^^.pipeGate.NewCond (OUT rdpaoEnv^^.rdcond));
check (rdpaoEnv^^.pipeGate.NewCond (OUT rdpaoEnv^^.wrcond));
check (MakeReentrant(rdpaoEnv));
DO BEGIN
ignore := (DelEnv (ownedfao, rdpaoMan));
objreturn (GetException);
END;
END;
PROCEDURE writepao;
VAR nullSize,voidSize,size: sizeType;
i,used: integer;
found: boolean;
BEGIN
æ the procedure creates a fao for writing a pipe. The fao
is given access to the pipedata segment and the monitor
in the corresponding readfao å
æ Allocate fao object å
æ#B# PrintText('---pipe.writefao---'); #E#å
check (clearSize (size));
check (addGen (size, refs(wrpaolocals)));
check (allocref.NewObj (OUT ownedfao; IN size, OUT i));
æ make fao a general object å
check (clearSize (nullsize));
voidSize.user := -1; voidSize.kernel := -1;
check (DeclGen (ownedfao,wrpaoman,wrpaoEnv,refs(wrpaolocals),
closewrite,nullsize,voidsize,refs(wrpaoImplement),
bytes(wrpaoImplement),nocontrol,addr(wrpaoImplement),
nullsize,true));
æ copy code pointer å
check (copy (code,wrpaoEnv^^.code));
æ find the corresponding read fao å
found := false;
res:= FirstInSet (rdpaoMan, tempEnv);
WHILE (Res.main = OK) AND NOT found do
BEGIN
WITH p = tempEnv^^.pipe^^ do
BEGIN
IF checkname (p.namelength,p.name,
filenameÆ1..elements(filename)-1Å)
THEN BEGIN
res:= copy (tempEnv, wrpaoEnv^^.readEnv);
found := true;
END;
END; æ with å
res:= NextInSet (rdpaoMan, tempEnv);
END; æ while å
if NOT found THEN
BEGIN
ignore := (delEnv(ownedfao,wrpaoman));
Exception(Makeres(reject*FileNotFound,iofamily,0,0));
END;
check (MakeReentrant(wrpaoEnv));
END;
BEGIN
æ#B# PrintText ('---pipe.assign---'); #E#å
if fileNameÆelements(fileName)Å = 'r' THEN readpao
ELSE
IF fileNameÆelements(fileName)Å = 'w' THEN writepao
ELSE
Exception (makeres (reject*fileNotFound,IoFamily,0,-1));
END; æ assign å
PRIVATE closewrite
WITH RECORD
t: ^^;
END;
BEGIN
æ#B# PrintText ('---pipe.closewrite---'); #E#å
check (rdpaoEnv^^.pipegate.lock);
WITH p = rdpaoEnv^^.pipe^^ do
BEGIN
p.wrclosed := true;
check (rdpaoEnv^^.rdcond.signal);
END; æ with å
check (rdpaoEnv^^.pipegate.open);
END;
PRIVATE closeread
WITH RECORD
t: ^^;
END;
BEGIN
æ#B# PrintText ('---pipe.closeread---'); #E#å
check (rdpaoEnv^^.pipegate.lock);
END;
OTHERWISE pipeother
WITH RECORD
t: ^^;
END;
BEGIN
Exception (makeRes (reject*EntryIllegal,Universal,0,0));
END; æ otherwise å
END; æ pipe file system å
INITIALIZE
pipesysImplement 'pipefs':
allocref 'allocate',
schedref 'scheduler'
END.
«eof»