-- 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.