DIRECTORY VM USING [ Allocate, Interval, AddressForPageNumber, PageCount, PagesForWords, PageNumberForAddress, Pin, WordsForPages], VMInternal USING [Crash], VMStatistics USING []; VMLowCoreImpl: MONITOR IMPORTS VM, VMInternal EXPORTS VM, VMStatistics = BEGIN ZoneRep: TYPE = LONG POINTER TO ZoneObject; ZoneObject: TYPE = MACHINE DEPENDENT RECORD [ procs(0:0..31): LONG POINTER TO ZoneProcs, data(2:0..31): ZoneData ]; ZoneProcs: TYPE = MACHINE DEPENDENT RECORD [ allocate(0): PROC [UNCOUNTED ZONE, WordCount] RETURNS [LONG POINTER], free(1): PROC [UNCOUNTED ZONE, LONG POINTER] ]; ZoneData: TYPE = ZoneChunk; ZoneChunk: TYPE = LONG POINTER TO ZoneChunkObject; ZoneChunkObject: TYPE = RECORD [ seal: INT _ chunkSeal, nextChunk: ZoneChunk, -- could be a 16-bit relative pointer, but why bother? wordsInChunk: INT, wordsInUse: INT ]; WordCount: TYPE = CARDINAL; lowCoreZone: ZoneObject _ [procs: @lowCoreZoneProcs, data: NIL]; lowCoreZoneProcs: ZoneProcs _ [allocate: Allocate, free: Free]; chunkSeal: INT = 32415; alignment: WordCount = 16; chunkOverhead: WordCount = Align[SIZE[ZoneChunkObject]]; lowCoreAllocations, lowCoreWords, lowCorePages: PUBLIC INT _ 0; lowCore: PUBLIC UNCOUNTED ZONE; Align: PROC [w: WordCount] RETURNS [WordCount] = INLINE { RETURN[((w + alignment - 1) / alignment) * alignment]}; Allocate: ENTRY PROC [z: UNCOUNTED ZONE, nWords: WordCount] RETURNS [p: LONG POINTER] = { previousChunk: ZoneChunk _ NIL; chunk: ZoneChunk; IF z ~= lowCore THEN VMInternal.Crash[]; nWords _ Align[MAX[nWords, 1]]; FOR chunk _ lowCoreZone.data, chunk.nextChunk UNTIL chunk = NIL DO IF chunk.seal ~= chunkSeal THEN VMInternal.Crash[]; IF chunk.wordsInUse + nWords <= chunk.wordsInChunk AND ( -- verify block would lie in a single page VM.PageNumberForAddress[chunk + chunk.wordsInUse] = VM.PageNumberForAddress[chunk + chunk.wordsInUse + nWords - 1] OR VM.PagesForWords[nWords+chunkOverhead] > 1 ) THEN EXIT; previousChunk _ chunk; REPEAT FINISHED => { pages: VM.PageCount = VM.PagesForWords[nWords]; interval: VM.Interval = VM.Allocate[count: pages, partition: $lowCore]; --*stats*-- lowCorePages _ lowCorePages + pages; VM.Pin[interval]; chunk _ VM.AddressForPageNumber[interval.page]; chunk^ _ [ nextChunk: IF previousChunk = NIL THEN NIL ELSE previousChunk.nextChunk, wordsInChunk: VM.WordsForPages[interval.count], wordsInUse: chunkOverhead ]; IF previousChunk = NIL THEN lowCoreZone.data _ chunk ELSE previousChunk.nextChunk _ chunk; }; ENDLOOP; p _ chunk + chunk.wordsInUse; chunk.wordsInUse _ chunk.wordsInUse + nWords; --*stats*-- lowCoreAllocations _ lowCoreAllocations.SUCC; --*stats*-- lowCoreWords _ lowCoreWords + nWords; }; Free: ENTRY PROC [z: UNCOUNTED ZONE, p: LONG POINTER] = {}; lowCore _ LOOPHOLE[LONG[@lowCoreZone]]; END. ธVMLowCoreImpl.mesa last edited by Levin on November 9, 1983 1:07 pm Global "Variables" Exports to VMStatistics Exports to VMSideDoor Internal Procedures Initialization สC– "Cedar" style˜Jšœ™Jšœ0™0J˜šฯk ˜ šœœ˜ Jšœn˜n—Jšœ œ ˜Jšœ œ˜J˜J˜—šœ˜Jšœœ ˜Jšœœ˜J˜—Jš˜J˜Jš œ œœœœ ˜+š œ œœ œœ˜-Jšœœœœ ˜*Jšœ˜J˜—š œ œœ œœ˜,Jš œ œ œœ œœœ˜EJš œ œ œœœœ˜,J˜—Jšœ œ ˜Jš œ œœœœ˜2šœœœ˜ Jšœœ ˜Jšœฯc6˜NJšœœ˜Jšœ ˜J˜—Jšœ œœ˜J˜J™J™J˜Jšœ;œ˜@Jšœ?˜?J˜Jšœ œ ˜J˜Jšœ˜Jšœ!œ˜9J™J™J™J˜Jšœ0œœ˜?J˜J™J˜Jšœ œ œœ˜J™J™J™šฯnœœœœ˜9Jšœ1˜7—J˜š Ÿœœœ œœ˜;Jšœœœ˜Jšœœ˜Jšœ˜Jšœœ˜(Jšœœ ˜šœ+œ œ˜BJšœœ˜3Jšœ0˜2šœž*˜0šœ1˜3Jšœ<˜>—Jšœœ(˜-J˜—Jšœœ˜ Jšœ˜š˜šœ˜ Jšœœ œ˜/Jšœ œ œ-˜GJšž œ%˜0Jšœ˜Jšœœ%˜/šœ ˜ Jš œ œœœœœ˜HJšœœ˜/Jšœ˜Jšœ˜—Jšœœœ˜4Jšœ!˜%J˜——Jšœ˜—Jšœ˜Jšœ-˜-Jšž œ)œ˜9Jšž œ&˜1J˜—J˜JšŸœœœ œœœœ˜;J™J™J™J™J˜Jšœ œœ˜'J˜Jšœ˜J™J™—…— าอ