-- Copyright (C) 1981, 1984, 1985 by Xerox Corporation. All rights reserved. -- ReaderAlloc.mesa, Transport Mechanism Filestore - Heap reader allocation -- HGM, 15-Sep-85 3:34:47 -- Randy Gobbel 19-May-81 11:56:01 -- -- Andrew Birrell 24-Feb-81 16:24:23 -- -- Brenda Hankins 14-Aug-84 10:02:50 add unwind on HeapStartRead 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 = LONG 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 ENABLE UNWIND => NULL; IF freeChain = noReader THEN { res ¬ Allocate[SIZE[HeapXDefs.ReaderData]]; Process.InitializeMonitor[@(res.LOCK)]} ELSE {res ¬ freeChain; freeChain ¬ freeChain.next}; 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: LONG 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.