<<>> <> <> <> <> <<>> DIRECTORY BasicTime USING [GMT, Now, nullGMT], File USING [wordsPerPage], MimZones USING [], MobDefs USING [NullVersion, VersionStamp], OSMiscOps USING [Address], ProcessorFace USING [ProcessorID, processorID], SafeStorage USING [GetSystemZone], UnsafeStorage USING [GetSystemUZone], VM USING [AddressForPageNumber, Free, Interval, PagesForWords, PageNumber, PageNumberForAddress, SimpleAllocate]; OSMiscOpsImpl: PROGRAM IMPORTS BasicTime, ProcessorFace, SafeStorage, UnsafeStorage, VM EXPORTS MimZones, OSMiscOps = { OPEN OSMiscOps; <> <<>> permZone: PUBLIC ZONE ¬ SafeStorage.GetSystemZone[]; <> <<(we should use GetPermanentZone sometime)>> tempZone: PUBLIC ZONE ¬ SafeStorage.GetSystemZone[]; <> <<(provided that the temp zone is UNCOUNTED)>> permUZ: PUBLIC UNCOUNTED ZONE ¬ UnsafeStorage.GetSystemUZone[]; <> tempUZ: PUBLIC UNCOUNTED ZONE ¬ UnsafeStorage.GetSystemUZone[]; <> ResetTempZone: PUBLIC PROC = {}; <> <<(provided that the temp zone is UNCOUNTED)>> RegisterForReset: PUBLIC PROC [resetProc: PROC] = {}; <> <<(provided that the temp zone is UNCOUNTED)>> <> <<>> intervals: LIST OF VM.Interval ¬ NIL; Pages: PUBLIC PROC [n: CARD] RETURNS [base: Address] = { IF n = 0 THEN base ¬ NIL ELSE { interval: VM.Interval = VM.SimpleAllocate[n]; intervals ¬ CONS[interval, intervals]; base ¬ VM.AddressForPageNumber[interval.page]; }; }; FreePages: PUBLIC PROC [base: Address] = { IF base # NIL THEN { page: VM.PageNumber = VM.PageNumberForAddress[base]; last: LIST OF VM.Interval ¬ NIL; FOR list: LIST OF VM.Interval ¬ intervals, list.rest UNTIL list = NIL DO IF list.first.page = page THEN { VM.Free[list.first]; IF last = NIL THEN intervals ¬ list.rest ELSE last.rest ¬ list.rest; EXIT; }; last ¬ list; ENDLOOP; }; }; Units: PUBLIC PROC [nUnits: CARD] RETURNS [base: Address] = { RETURN [Pages[VM.PagesForWords[nUnits]]]; }; FreeUnits: PUBLIC PROC [base: Address] = { FreePages[base]; }; bytesPerFilePage: PUBLIC NAT ¬ File.wordsPerPage*BYTES[WORD]; <> lastTime: BasicTime.GMT ¬ BasicTime.nullGMT; GenerateUniqueId: PUBLIC PROC RETURNS [MobDefs.VersionStamp] = { stamp: MobDefs.VersionStamp ¬ MobDefs.NullVersion; id: ProcessorFace.ProcessorID ¬ ProcessorFace.processorID; time: BasicTime.GMT; { words: NAT = MIN[MobDefs.VersionStamp.WORDS, ProcessorFace.ProcessorID.WORDS]; Ptr: TYPE = POINTER TO ARRAY [0..words) OF WORD; LOOPHOLE[@stamp, Ptr]­ ¬ LOOPHOLE[@id, Ptr]­; }; DO time ¬ BasicTime.Now[]; IF lastTime = BasicTime.nullGMT OR time # lastTime THEN EXIT; ENDLOOP; lastTime ¬ time; stamp[1] ¬ stamp[1] + LOOPHOLE[time, CARD]; RETURN [stamp]; }; <> <<>> WordPtr: TYPE = LONG POINTER TO WORD; BlockPtr: TYPE = LONG POINTER TO Block; Block: TYPE = ARRAY [0..8) OF WORD; blockWords: NAT = Block.WORDS; blockSize: NAT = Block.SIZE; Copy: PUBLIC PROC [from: LONG POINTER, nwords: CARD, to: LONG POINTER] = { <> IF nwords > CARD[INT.LAST] THEN ERROR; WHILE nwords >= blockWords DO nwords ¬ nwords - blockWords; LOOPHOLE[to, BlockPtr]­ ¬ LOOPHOLE[from, BlockPtr]­; to ¬ to + blockSize; from ¬ from + blockSize; ENDLOOP; WHILE nwords # 0 DO nwords ¬ nwords - 1; LOOPHOLE[to, WordPtr]­ ¬ LOOPHOLE[from, WordPtr]­; to ¬ to + WORD.SIZE; from ¬ from + WORD.SIZE; ENDLOOP; }; Fill: PUBLIC PROC [where: LONG POINTER, nWords: CARD, value: WORD] = { IF nWords > CARD[INT.LAST] THEN ERROR; WHILE nWords >= blockWords DO nWords ¬ nWords - blockWords; LOOPHOLE[where, BlockPtr]­ ¬ ALL[value]; where ¬ where + blockSize; ENDLOOP; WHILE nWords # 0 DO nWords ¬ nWords - 1; LOOPHOLE[where, WordPtr]­ ¬ value; where ¬ where + WORD.SIZE; ENDLOOP; }; <<>> <> stampElements: NAT = BITS[MobDefs.VersionStamp]/BITS[CARD32]; Stamp: PUBLIC TYPE = ARRAY [0..stampElements) OF CARD32; TimeToStamp: PUBLIC PROC [time: MobDefs.VersionStamp] RETURNS [Stamp] = { RETURN [time]; }; StampToTime: PUBLIC PROC [s: Stamp] RETURNS [MobDefs.VersionStamp] = { RETURN [s]; }; AddStamps: PROC [s1, s2: Stamp] RETURNS [sum: Stamp] = { carry: CARD32 ¬ 0; FOR i: NAT DECREASING IN [0..stampElements) DO w1: CARD32 ¬ s1[i]; w2: CARD32 ¬ s2[i]; w: CARD32 ¬ w1+w2+carry; sum[i] ¬ w; IF w < w1 OR w < carry THEN carry ¬ 1 ELSE carry ¬ 0; ENDLOOP; IF carry = 1 THEN <> FOR i: NAT DECREASING IN [0..stampElements) DO w: CARD32 ¬ sum[i]+1; sum[i] ¬ w; IF w # 0 THEN EXIT; ENDLOOP; }; MergeStamps: PUBLIC PROC [sum, item: Stamp] RETURNS [Stamp] = { RETURN [AddStamps[AddStamps[sum, sum], item]]; }; }.