<> <> <> <> <> <> <<>> <> DIRECTORY SafeStorage USING[nullType, Type]; Allocator: DEFINITIONS = BEGIN <> HeaderP: TYPE = LONG POINTER TO Header; -- always even-word aligned NHeaderP: TYPE = LONG POINTER TO NormalHeader; -- always even-word aligned EHeaderP: TYPE = LONG POINTER TO ExtendedHeader; -- always even-word aligned FHeaderP: TYPE = LONG POINTER TO free Header; FEHeaderP: TYPE = LONG POINTER TO extended free Header; FNHeaderP: TYPE = LONG POINTER TO normal free Header; UHeaderP: TYPE = LONG POINTER TO inUse Header; UEHeaderP: TYPE = LONG POINTER TO extended inUse Header; UNHeaderP: TYPE = LONG POINTER TO normal inUse Header; Header: TYPE = MACHINE DEPENDENT RECORD[ -- 2, 4 or 6 words SELECT COMPUTED FreeOrInUse FROM << (LOOPHOLE[ref, NHeaderP]-SIZE[NormalHeader]).type = nullType>> << OR (coming from the top, parsing, starting from QMap)>> << (IF hp.blockSizeIndex = bsiEscape>> << THEN LOOPHOLE[hp, EHeaderP].normalHeader.type = nullType>> << ELSE LOOPHOLE[hp, NHeaderP].type = nullType)>> free => [ SELECT COMPUTED ExtendedOrNormal FROM << LOOPHOLE[ref-SIZE[NormalHeader], NHeaderP].blockSizeIndex = bsiEscape>> << OR>> << hp.blockSizeIndex = bsiEscape>> extended => [feh: ExtendedHeader, nextFree: FNHeaderP], -- 6 words normal => [fnh: NormalHeader, nextFree: FNHeaderP] -- 4 words ENDCASE ], inUse => [ SELECT COMPUTED ExtendedOrNormal --ditto-- FROM extended => [ueh: ExtendedHeader], -- 4 words normal => [unh: NormalHeader] -- 2 words ENDCASE ] ENDCASE ]; FreeOrInUse: TYPE = {free, inUse}; ExtendedOrNormal: TYPE = {extended, normal}; ExtendedSizeTag: TYPE = MACHINE DEPENDENT {unused(0), words(1), pages(2), bsi(3)}; ExtendedHeader: TYPE = MACHINE DEPENDENT RECORD[ -- 4 words, always even-word aligned sizeTag(0: 0..1): ExtendedSizeTag _ words, blockSizeIndex(0: 2..7): BlockSizeIndex _ bsiEscape, <> owner(0: 8..15): Owner _ 0, <> extendedSize(1): CARDINAL, <> normalHeader(2): NormalHeader ]; NormalHeader: TYPE = MACHINE DEPENDENT RECORD[ -- 2 words, always even-word aligned inZCT(0: 0..0): BOOL _ FALSE, maybeOnStack(0: 1..1): BOOL _ FALSE, blockSizeIndex(0: 2..7): BlockSizeIndex, -- size includes the header overhead f(0: 8..8): BOOL _ FALSE, < q this object for finalization if refCount = 0 AND NOT rcOverflowed>> < reclaim this object if refCount = 0 AND NOT rcOverflowed>> refCount(0: 9..14): RefCount _ 0, rcOverflowed(0: 15..15): BOOL _ FALSE, < the rcOverflow bank has a deposit for this object>> typePad(1: 0..1): [0..3] _ 0, -- TEMPORARY for compatibility type(1: 2..15): SafeStorage.Type _ SafeStorage.nullType ]; SizeToBSIObj: TYPE = PACKED ARRAY [0..maxSmallBlockSize] OF BlockSizeIndex; BSIToSizeObj: TYPE = ARRAY BlockSizeIndex OF NAT; BSIToFreeListObj: TYPE = ARRAY BlockSizeIndex OF FNHeaderP; BlockSizeIndex: TYPE = [0..77B]; -- assumed in ZCT.ZCTObject to be less than wordsPerPage/2 maxSmallBlockSize: NAT = 1076B; -- requested. i.e. does not include overhead minLargeBlockSize: NAT = 3375B; -- requested. i.e. does not include overhead bsiEscape: BlockSizeIndex = LAST[BlockSizeIndex]; -- used to identify extended headers <> <> <> <> RefCount: TYPE = [0..77B]; Owner: TYPE = [0..377B]; <> Zone: TYPE = REF ZoneObject; ZoneObject: TYPE = MACHINE DEPENDENT RECORD[ new(0): PROC[self: Zone, size: CARDINAL, type: SafeStorage.Type] RETURNS[REF ANY], free(1): PROC[self: Zone, object: REF ANY] ]; PUZone: TYPE = LONG POINTER TO UZone; UZone: TYPE = LONG POINTER TO UZoneObject; UZoneObject: TYPE = MACHINE DEPENDENT RECORD[ new(0): PROC[self: PUZone, size: CARDINAL] RETURNS[LONG POINTER], free(1): PROC[self: PUZone, object: LONG POINTER] ]; <> LastAddress: LONG CARDINAL = 77777777B; -- 24 bits wordsPerQuantum: NAT = 256; pagesPerQuantum: NAT = 1; logPagesPerQuantum: NAT = 0; QuantumIndex: TYPE = [0..177777B--LastAddress/wordsPerQuantum--]; QuantumCount: TYPE = CARDINAL; QuantumMap: TYPE = LONG POINTER TO QMObject; QMObject: TYPE = PACKED ARRAY QuantumIndex OF BOOL; < the indexed quantum is assigned to the Cedar (collectible) allocator>> END.