<> <> DIRECTORY Allocator USING[bsiEscape], AllocatorOps USING[DoubleFreeHeader, Rover, DFHeaderP, DoCreateMediumSizedObject, DoFreeMediumSizedObject, nonNullType], VM USING[PagesForWords, AddressForPageNumber, Allocate, CantAllocate]; UnsafeAllocatorImpl: MONITOR <> IMPORTS AllocatorOps, VM EXPORTS AllocatorOps = BEGIN OPEN AllocatorOps; <> InsufficientVM: ERROR = CODE; <> UZHandle: TYPE = LONG POINTER TO UZObject; UZObject: TYPE = MACHINE DEPENDENT RECORD [ procs(0:0..31): LONG POINTER TO UZProcs ]; UZProcs: TYPE = MACHINE DEPENDENT RECORD [ new(0): PROC[self: UZHandle, size: CARDINAL] RETURNS[LONG POINTER], free(1): PROC[self: UZHandle, object: LONG POINTER] ]; <> <> ppzProcs: UZProcs _ [new: PPZNew, free: NIL]; ppzObject: UZObject _ [procs: @ppzProcs]; permanentPageZone: PUBLIC UNCOUNTED ZONE _ LOOPHOLE[LONG[@ppzObject]]; <> <> <> heapRoot: DoubleFreeHeader _ [ <> eh: [extendedSize: 0, normalHeader: [blockSizeIndex: Allocator.bsiEscape]], nextFree: @heapRoot, prevFree: @heapRoot ]; heapRover: Rover _ @heapRoot; <<>> <> <<>> <> PPZNew: PROC[self: UZHandle, size: CARDINAL] RETURNS[lp: LONG POINTER] = { nPages: INT = VM.PagesForWords[size]; lp _ VM.AddressForPageNumber [VM.Allocate[count: nPages, in64K: TRUE ! VM.CantAllocate => GOTO noVM].page]; EXITS noVM => ERROR InsufficientVM; }; <<>> <> <<>> <> <= SIZE[DoubleFreeHeader].>> <> <> CreateMediumSizedHeapObject: PUBLIC ENTRY PROC[size: NAT] RETURNS[LONG POINTER] = {ENABLE UNWIND => NULL; RETURN[ AllocatorOps.DoCreateMediumSizedObject[size, nonNullType, @heapRover, FALSE]]; }; <> <> FreeMediumSizedHeapObject: PUBLIC ENTRY PROC[ptr: DFHeaderP] = { ENABLE UNWIND => NULL; AllocatorOps.DoFreeMediumSizedObject[ptr, heapRover]; }; END.