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+chunkOverhead]; 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 Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) April 9, 1986 2:31:19 pm PST Types Global "Variables" Exports to VMStatistics Exports to VMSideDoor Internal Procedures Initialization ΚL– "Cedar" style˜codešœ™Kšœ Οmœ7™BJ™0—˜šΟk ˜ Kšžœžœp˜xKšœ žœ ˜Kšœ žœ˜——headšœž˜Kšžœžœ ˜Kšžœžœž˜ —K˜™K™Kš œ žœžœžœžœ ˜+š œ žœžœž œžœ˜-Kšœžœžœžœ ˜*Kšœ˜K˜K˜—š œ žœžœž œžœ˜,Kš œ žœž œžœ žœžœžœ˜EKš œ žœž œžœžœžœ˜,K˜K˜—Kšœ žœ ˜Kš œ žœžœžœžœ˜2šœžœžœ˜ Kšœžœ ˜KšœΟc6˜NKšœžœ˜Kšœ ž˜K˜K˜—Kšœ žœžœ˜K˜—™K˜Kšœ;žœ˜@Kšœ?˜?K˜Kšœ žœ ˜K˜Kšœ˜Kšœ!žœ˜9K™—™K˜Kšœ0žœžœ˜?K˜—™K˜Kšœ žœž œžœ˜K™—™K™šΟnœžœžœžœ˜9Kšžœ0˜6Kšœ˜—K˜š œžœžœž œžœžœžœžœ˜YKšœžœ˜Kšœ˜Kšžœžœ˜(Kšœžœ ˜šžœ+žœ žœž˜BKšžœžœ˜3Kšžœ0˜2šžœŸ*˜0šžœ1˜3Kšžœ<˜>—Kšžœžœ(˜-K˜—Kšžœžœ˜ Kšœ˜šž˜šžœ˜ Kšœžœ žœ%˜=Kšœ žœ žœ-˜GKšŸ œ%˜0Kšžœ˜Kšœžœ%˜/šœ ˜ Kš œ žœžœžœžœžœ˜HKšœžœ˜/Kšœ˜Kšœ˜—Kšžœžœžœ˜4Kšžœ!˜%K˜——Kšžœ˜—Kšœ˜Kšœ-˜-KšŸ œ)žœ˜9KšŸ œ&˜1K˜—K˜Kš œžœžœž œžœžœžœ˜;K™—™K™Kšœ žœžœ˜'K˜—Kšžœ˜K™K™—…— ΰ,