DataMuseum.dk

Presents historical artifacts from the history of:

Bogika Butler

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Bogika Butler

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦84951ca1f⟧ TextFile

    Length: 15616 (0x3d00)
    Types: TextFile
    Names: »PIPE.SA«

Derivation

└─⟦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« 

TextFile

 
æ*****************************************************************
                        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»