-- Transport Mechanism Filestore - Heap reader allocation -- -- [Juniper]MS>ReaderAlloc.mesa -- Randy Gobbel 19-May-81 11:56:01 -- -- Andrew Birrell 24-Feb-81 16:24:23 -- DIRECTORY HeapDefs USING[ objectStart ], HeapXDefs USING[ ReaderData, RestartReader, StopReader ], LogDefs USING[ DisplayNumber, WriteChar ], ObjectDirDefs USING[ UseObject, FreeObject, noObject ], ObjectDirXDefs USING[ ObjectNumber, ObjectBase ], Process USING[ InitializeMonitor, InitializeCondition, DisableTimeout ], Storage USING[ Node ], VMDefs USING[ ReadPage, Release ]; ReaderAlloc: MONITOR IMPORTS HeapXDefs, LogDefs, ObjectDirDefs, ObjectDirXDefs, Process, Storage, VMDefs EXPORTS HeapDefs, HeapXDefs = BEGIN ReaderData: PUBLIC TYPE = HeapXDefs.ReaderData; Handle: TYPE = POINTER TO ReaderData; Allocate: PROCEDURE[CARDINAL] RETURNS[POINTER] = Storage.Node; noReader: Handle = NIL; readerChain, freeChain: Handle _ noReader; readerCount: CARDINAL _ 0; HeapStartRead: PUBLIC ENTRY PROCEDURE[ from: ObjectDirXDefs.ObjectNumber ] RETURNS[ res: Handle ] = BEGIN IF freeChain = noReader THEN BEGIN res _ Allocate[SIZE[HeapXDefs.ReaderData]]; Process.InitializeMonitor[@(res.LOCK)]; END ELSE BEGIN res _ freeChain; freeChain _ freeChain.next; END; res.next _ readerChain; readerChain _ res; res.object _ from; ObjectDirDefs.UseObject[from]; res.end _ FALSE; res.stopped _ from=compactorNumber; Process.InitializeCondition[@res.canStart,0]; Process.DisableTimeout[@res.canStart]; res.offset _ HeapDefs.objectStart; res.where _ ObjectDirXDefs.ObjectBase[from]; res.page _ VMDefs.ReadPage[ res.where.page, 0--lookAhead-- ]; readerCount _ readerCount + 1; LogDefs.WriteChar['{]; END; HeapEndRead: PUBLIC ENTRY PROCEDURE[ from: Handle ] = BEGIN -- Note that, in the unlikely event that the user was calling -- -- 'HeapReadData' from several processes, he must have returned from -- -- all such calls before calling 'HeapEndRead', or else one of the -- -- calls may commence after the reader has been freed. Hence, we may -- -- update fields of the 'Handle' without invoking the lock on -- -- its monitored record -- VMDefs.Release[from.page]; ObjectDirDefs.FreeObject[from.object]; BEGIN -- remove from 'readerChain' -- prev: POINTER TO Handle _ @readerChain; WHILE prev^ # from DO prev _ @(prev^.next) ENDLOOP; prev^ _ from.next; END; from.next _ freeChain; freeChain _ from; readerCount _ readerCount - 1; LogDefs.WriteChar['}]; END; -- interlock with compactor -- compactorNumber: ObjectDirXDefs.ObjectNumber _ ObjectDirDefs.noObject; StopAllReaders: PUBLIC ENTRY PROCEDURE[ obj: ObjectDirXDefs.ObjectNumber ] = BEGIN ptr: Handle _ readerChain; UNTIL ptr = noReader DO IF ptr.object = obj THEN HeapXDefs.StopReader[ptr]; ptr _ ptr.next ENDLOOP; compactorNumber _ obj; END; RestartAllReaders: PUBLIC ENTRY PROCEDURE[ obj: ObjectDirXDefs.ObjectNumber ] = BEGIN ptr: Handle _ readerChain; UNTIL ptr = noReader DO IF ptr.object = obj THEN HeapXDefs.RestartReader[ptr]; ptr _ ptr.next ENDLOOP; IF obj = compactorNumber THEN compactorNumber _ ObjectDirDefs.noObject; END; LogDefs.DisplayNumber[ "Readers"L, [short[@readerCount]] ]; END.