<> <> <> <> <> <<>> DIRECTORY Basics: TYPE USING [LongNumber], BasicTime: TYPE USING [GMT, Now, nullGMT], BcdDefs: TYPE USING [VersionStamp], OSMiscOps: TYPE USING [Address], PrincOpsUtils: TYPE USING [BITXOR], ProcessorFace: TYPE USING [processorID], VM: TYPE USING [AddressForPageNumber, Allocate, Free, Interval, PageNumber, PageNumberForAddress]; OSMiscOpsImpl: PROGRAM IMPORTS BasicTime, PrincOpsUtils, ProcessorFace, VM EXPORTS OSMiscOps = { <> <<>> intervals: LIST OF VM.Interval _ NIL; Pages: PUBLIC PROC[n: CARDINAL] RETURNS[base: OSMiscOps.Address] = { IF n = 0 THEN base _ NIL ELSE { interval: VM.Interval = VM.Allocate[count: n]; intervals _ CONS[interval, intervals]; base _ VM.AddressForPageNumber[interval.page]}; RETURN}; FreePages: PUBLIC PROC[base: OSMiscOps.Address] = { page: VM.PageNumber; last: LIST OF VM.Interval _ NIL; IF base = NIL THEN RETURN; page _ VM.PageNumberForAddress[base]; 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; }; <> GetNetAndHost: PROC RETURNS[net, host: CARDINAL] = { pId: ARRAY [0..3) OF WORD = LOOPHOLE[ProcessorFace.processorID]; sum: WORD = PrincOpsUtils.BITXOR[pId[0], PrincOpsUtils.BITXOR[pId[1], pId[2]]]; net _ sum/256; host _ sum MOD 256}; lastTime: BasicTime.GMT _ BasicTime.nullGMT; GenerateUniqueId: PUBLIC PROC RETURNS[BcdDefs.VersionStamp] = { net, host: CARDINAL; time: BasicTime.GMT; [net, host] _ GetNetAndHost[]; DO time _ BasicTime.Now[]; IF lastTime = BasicTime.nullGMT OR time # lastTime THEN EXIT; ENDLOOP; lastTime _ time; RETURN[[net: net, host: host, time: LOOPHOLE[time, LONG CARDINAL]]]}; <> StampSize: NAT = 3; Stamp: PUBLIC TYPE = RECORD[word: ARRAY [0..StampSize) OF CARDINAL]; AddStamps: PROC[s1, s2: Stamp] RETURNS[sum: Stamp] = { carry: [0..1] _ 0; i: NAT; FOR i DECREASING IN [0..StampSize) DO t: Basics.LongNumber _ [lc[s1.word[i].LONG + s2.word[i].LONG + carry.LONG]]; sum.word[i] _ t.lowbits; carry _ t.highbits; ENDLOOP; FOR i DECREASING IN [0..StampSize) WHILE carry # 0 DO t: Basics.LongNumber _ [lc[sum.word[i].LONG + carry.LONG]]; sum.word[i] _ t.lowbits; carry _ t.highbits; ENDLOOP}; RotateStamp: PROC[s: Stamp] RETURNS[Stamp] = INLINE {RETURN [AddStamps[s, s]]}; MergeStamps: PUBLIC PROC [sum, item: Stamp] RETURNS [Stamp] = { RETURN[AddStamps[RotateStamp[sum], item]]}; }.