DIRECTORY Allocator USING[bsiEscape, ExtendedHeader, HeaderP, LastAddress, NHeaderP, NormalHeader, QuantumMap, QuantumIndex, wordsPerQuantum, BSIToSizeObj, SizeToBSIObj, BlockSizeIndex], Basics USING[BITAND, LowHalf], SafeStorage USING[nullType, Type, TypeIndex]; AllocatorOps: DEFINITIONS IMPORTS Basics = BEGIN OPEN Allocator; DFHeaderP: TYPE = LONG POINTER TO DoubleFreeHeader; Rover: TYPE = DFHeaderP; DoubleFreeHeader: TYPE = RECORD[ eh: ExtendedHeader, nextFree: DFHeaderP, prevFree: DFHeaderP ]; nonNullType: SafeStorage.Type = [LAST[SafeStorage.TypeIndex]]; permanentPageZone: UNCOUNTED ZONE; bsiToSize: LONG POINTER TO BSIToSizeObj; sizeToBSI: LONG POINTER TO SizeToBSIObj; quantumMap: QuantumMap; NewObject: PROC[type: SafeStorage.Type, size: CARDINAL, zone: ZONE _ NIL] RETURNS[REF ANY]; -- CLEARED PlausibleRef: PROC[lc: LONG CARDINAL] RETURNS[BOOL] = INLINE{ RETURN[ lc> SIZE[NormalHeader] AND Basics.BITAND[Basics.LowHalf[lc], 1] = 0 AND lc < LastAddress AND quantumMap[AddressToQuantumIndex[lc]] ]; }; AddressToQuantumIndex: PROC[addr: LONG CARDINAL] RETURNS[QuantumIndex] = INLINE{IF addr > LastAddress THEN ERROR ELSE RETURN[addr/wordsPerQuantum]}; ReferentType: PROC[ref: REF ANY] RETURNS[SafeStorage.Type] = INLINE{ RETURN[IF ref = NIL THEN SafeStorage.nullType ELSE (LOOPHOLE[ref, LONG POINTER TO SafeStorage.Type]-1)^]; }; BlockSize: PROC[hp: HeaderP] RETURNS[INT]; REFToHP: PROC[ref: REF ANY] RETURNS[HeaderP] = INLINE{ nhp: NHeaderP = LOOPHOLE[ref, NHeaderP] - SIZE[NormalHeader]; IF nhp.blockSizeIndex # bsiEscape THEN RETURN[LOOPHOLE[nhp]] ELSE RETURN[LOOPHOLE[ref, HeaderP] - SIZE[ExtendedHeader]]; }; REFToNHP: PROC[ref: REF ANY] RETURNS[NHeaderP] = INLINE{RETURN[LOOPHOLE[ref, NHeaderP] - SIZE[NormalHeader]]}; NHPToREF: PROC[nhp: NHeaderP] RETURNS[REF ANY] = INLINE{RETURN[LOOPHOLE[nhp + SIZE[NormalHeader], REF ANY]]}; HPToREF: PROC[hp: HeaderP] RETURNS[REF ANY] = INLINE{ nhp: NHeaderP = LOOPHOLE[hp]; IF nhp.blockSizeIndex # bsiEscape THEN RETURN[LOOPHOLE[hp + SIZE[NormalHeader]]] ELSE RETURN[LOOPHOLE[hp + SIZE[ExtendedHeader]]]; }; FreeObject: PROC[nhp: NHeaderP]; TAndSFreeObject: PROC[nhp: NHeaderP]; ExpandNormalFreeList: PROC[bsi: BlockSizeIndex]; Initialize: PROC; -- initializes the safe allocator. Reset: PROC; -- called by the TAndS. EnterAndCallBack: PROC[proc: PROC]; IsValidRef: PROC[p: LONG POINTER] RETURNS[BOOL]; -- NIL => TRUE DoCreateMediumSizedObject: PROC[ size: NAT, type: SafeStorage.Type, roverP: LONG POINTER TO--VAR-- Rover, counted: BOOL] RETURNS[p: LONG POINTER _ NIL]; DoFreeMediumSizedObject: PROC[ptr: DFHeaderP, rover: Rover]; CreateMediumSizedHeapObject: PROC[size: NAT] RETURNS[p: LONG POINTER _ NIL]; FreeMediumSizedHeapObject: PROC[ptr: DFHeaderP]; END. δAllocatorOps.mesa Definitions for the Cedar allocator: object prefix formats, ZONE formats Paul Rovner, December 6, 1983 3:29 pm TYPES doubly-linked free lists Stuff used by the TAndS Stuff for UnsafeAllocatorImpl Defined in AllocatorImpl Procs that actually do the work of manipulating and modifying DoubleFree lists Defined in UnsafeAllocatorImpl Procs called via NewHeapObject and FreeHeapObject to enter its monitor and then call the above guys to actually do the work Κ˜Jšœ™JšœH™HJšœ%™%J˜šΟk ˜ Jšœ œ‘˜°Jšœœœ ˜Jšœ œ˜-—J˜š œ œœ œœ ˜@J˜™Jšœ™Jš œ œœœœ˜3Jšœœ ˜šœœœ˜ Jšœ˜Jšœ˜Jšœ˜Jšœ˜———™Jšœ!œ˜>J˜Iprocšœ œœ˜"J˜Jšœ œœœ˜(Jšœ œœœ˜(Jšœ˜K˜š Οn œœœœœ˜IJšœœœΟc ˜J˜—Kš ž œœœœœœ˜5šœ˜šœ˜Kšœœ˜Kšœœ˜,Kšœ˜Kšœ&˜)Kšœ˜—Kšœ˜K˜—Jš žœœœœœ˜HJš œœœœœœ˜KJ˜Jš ž œœœœœ˜<šœ˜Jšœœœœœœœœœ˜iJšœ˜—J˜Jšž œœœœ˜*J˜Jš žœœœœœ ˜.šœ˜Jšœœœ˜=šœ˜!Jšœœœ˜Jšœœœœ˜;—Jšœ˜—J˜Jš žœœœœœ ˜0Jšœœœœ˜=J˜Jš žœœœœœ˜0Jš œœœœœœ˜