DIRECTORY Basics USING [bitsPerWord, LongMult], BitmapViewer USING [Create, SetBitmap, TouchUp], CedarProcess USING [Fork], Commander USING [CommandProc, Handle, Register], CommandTool USING [ArgumentVector, Failed, Parse], CountedVM USING [Allocate, Handle], File USING [FindVolumeFromName, GetVolumeName, Handle, Info, Open, Read, SystemVolume, Volume, wordsPerPage], FileBackdoor USING [GetRoot], ImagerPixelMap USING [DeviceRectangle, PixelMap, PixelMapRep], Process USING [Pause, SecondsToTicks], Rope USING [Concat, Match, ROPE], ViewerClasses USING [Viewer], ViewerOps USING [SetOpenHeight], VM USING [PageState, State], VMSideDoor USING [vmPages]; ShowVAMImpl: CEDAR PROGRAM IMPORTS Basics, BitmapViewer, CedarProcess, Commander, CommandTool, CountedVM, File, FileBackdoor, Process, Rope, ViewerOps, VM, VMSideDoor ~ BEGIN width: NAT _ 512; updateSeconds: NAT _ 5; DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle; PixelMap: TYPE ~ ImagerPixelMap.PixelMap; Viewer: TYPE ~ ViewerClasses.Viewer; ROPE: TYPE ~ Rope.ROPE; MyData: TYPE ~ REF MyDataRec; MyDataRec: TYPE ~ RECORD[ viewer: Viewer, volume: File.Volume, pageStateBit: PageStateBit _ nil ]; VMFiller: PROC [data: REF] RETURNS [results: REF _ NIL] ~ { myData: MyData ~ NARROW[data]; size: INT ~ VMSideDoor.vmPages; bpl: NAT _ width; lines: NAT _ (size + bpl-1)/bpl; bounds: DeviceRectangle ~ [0, 0, lines, bpl]; pixelMap: PixelMap ~ CVMPixelMap[bounds]; firstTime: BOOL _ TRUE; IF bpl MOD Basics.bitsPerWord # 0 THEN ERROR; ViewerOps.SetOpenHeight[myData.viewer, lines+1]; UNTIL myData.viewer.destroyed DO IF NOT myData.viewer.iconic THEN { vm: CountedVM.Handle ~ NARROW[pixelMap.refRep.ref]; W: TYPE ~ PACKED ARRAY [0..32) OF BOOL; w: W; base: LONG POINTER TO W ~ LOOPHOLE[vm.pointer]; offset: INT _ 0; pageNumber: INT _ 0; pageStateBit: PageStateBit _ myData.pageStateBit; WHILE pageNumber < size DO w _ ALL[FALSE]; FOR i: CARDINAL IN [0..32) WHILE pageNumber < size DO state: VM.PageState ~ VM.State[pageNumber]; w[i] _ SELECT pageStateBit FROM allocated => state.dataState # none, real => state.hasRealMemory, pinned => state.pinCount#0, dirty => state.needsCleaning, ENDCASE => ERROR; pageNumber _ pageNumber+1; ENDLOOP; TRUSTED { IF offset > vm.words-SIZE[W] THEN ERROR; (base+offset)^ _ w; }; offset _ offset + SIZE[W]; ENDLOOP; IF firstTime THEN BitmapViewer.SetBitmap[myData.viewer, pixelMap] ELSE BitmapViewer.TouchUp[myData.viewer, bounds]; firstTime _ FALSE; }; Process.Pause[Process.SecondsToTicks[updateSeconds]]; ENDLOOP; }; VAMFiller: PROC [data: REF] RETURNS [results: REF _ NIL] ~ { myData: MyData ~ NARROW[data]; vamFile: File.Handle = File.Open[myData.volume, FileBackdoor.GetRoot[myData.volume, VAM].fp]; filePages: INT = File.Info[vamFile].size; fileWords: INT = File.wordsPerPage * filePages; bpl: NAT _ width; lines: NAT _ (fileWords*Basics.bitsPerWord + bpl-1)/bpl; bounds: DeviceRectangle ~ [0, 0, lines, bpl]; pixelMap: PixelMap ~ CVMPixelMap[bounds]; firstTime: BOOL _ TRUE; IF bpl MOD Basics.bitsPerWord # 0 THEN ERROR; UNTIL myData.viewer.destroyed DO IF NOT myData.viewer.iconic THEN { vm: CountedVM.Handle ~ NARROW[pixelMap.refRep.ref]; TRUSTED {File.Read[file: vamFile, from: [0], to: vm.pointer, nPages: MIN[filePages, vm.interval.count]]}; IF firstTime THEN BitmapViewer.SetBitmap[myData.viewer, pixelMap] ELSE BitmapViewer.TouchUp[myData.viewer, bounds]; firstTime _ FALSE; }; Process.Pause[Process.SecondsToTicks[5]]; ENDLOOP; }; CVMPixelMap: PROC [bounds: DeviceRectangle] RETURNS [pixelMap: PixelMap] ~ { bitsPerPixel: INT ~ 1; bitsPerLine: NAT ~ bounds.fSize*bitsPerPixel; wordsPerLine: CARDINAL ~ (bitsPerLine+(Basics.bitsPerWord-1)) / Basics.bitsPerWord; words: LONG CARDINAL ~ Basics.LongMult[wordsPerLine, bounds.sSize]; TRUSTED { countedVM: CountedVM.Handle _ CountedVM.Allocate[words]; pixelMap.refRep _ NEW[ImagerPixelMap.PixelMapRep]; pixelMap.refRep.ref _ countedVM; pixelMap.refRep.pointer _ countedVM.pointer; pixelMap.refRep.words _ countedVM.words; pixelMap.refRep.lgBitsPerPixel _ 0; pixelMap.refRep.rast _ wordsPerLine; pixelMap.refRep.lines _ bounds.sSize; }; pixelMap.sMin _ pixelMap.fMin _ 0; [pixelMap.sOrigin, pixelMap.fOrigin, pixelMap.sSize, pixelMap.fSize] _ bounds; }; ShowVAMProc: Commander.CommandProc ~ { argv: CommandTool.ArgumentVector; volume: File.Volume; volumeName: Rope.ROPE; viewer: Viewer _ NIL; argv _ CommandTool.Parse[cmd: cmd ! CommandTool.Failed => { msg _ errorMsg; CONTINUE; } ]; IF argv = NIL THEN GOTO Failed; IF argv.argc = 1 THEN { volume _ File.SystemVolume[]; volumeName _ File.GetVolumeName[volume]; } ELSE { IF argv.argc # 2 THEN GOTO Usage; volume _ File.FindVolumeFromName[argv[1]]; volumeName _ argv[1]; }; IF volume = NIL THEN GOTO NoVolume; viewer _ BitmapViewer.Create[[ column: left, iconic: FALSE, name: Rope.Concat["VAM for ", volumeName ], hscrollable: TRUE ]]; [] _ CedarProcess.Fork[action: VAMFiller, data: NEW[MyDataRec _ [viewer: viewer, volume: volume]]]; EXITS Failed => RETURN[$Failure, msg]; Usage => RETURN[$Failure, " Usage: ShowVAM volumename\n"]; NoVolume => RETURN[$Failure, " No such volume\n"]; }; PageStateBit: TYPE ~ {nil, allocated, real, pinned, dirty}; nameVM: REF ARRAY PageStateBit OF ROPE ~ NEW[ARRAY PageStateBit OF ROPE _ [ "?", "VM Allocated", "VM Real", "VM Pinned", "VM Dirty" ]]; ShowVMProc: Commander.CommandProc = { pageStateBit: PageStateBit _ SELECT TRUE FROM Rope.Match["*alloc*", cmd.commandLine, FALSE] => allocated, Rope.Match["*real*", cmd.commandLine, FALSE] => real, Rope.Match["*pin*", cmd.commandLine, FALSE] => pinned, Rope.Match["*dirt*", cmd.commandLine, FALSE] => dirty, ENDCASE => allocated; viewer: Viewer _ BitmapViewer.Create[[ column: left, iconic: FALSE, name: nameVM[pageStateBit], hscrollable: TRUE ]]; data: REF MyDataRec _ NEW[MyDataRec _ [viewer: viewer, volume: File.SystemVolume[], pageStateBit: pageStateBit]]; [] _ CedarProcess.Fork[action: VMFiller, data: data]; }; Commander.Register[key: "ShowVAM", proc: ShowVAMProc, doc: "Show a viewer with a bitmap of the VAM (volume allocation map) of the given logical volume ('Cedar' if omitted)"]; Commander.Register[key: "ShowVM", proc: ShowVMProc, doc: "Show a viewer with a bitmap of the VM (virtual memory)\n args: (allocated | real | pinned | dirty)"]; END. dShowVAMImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Andrew Birrell November 18, 1983 2:11 pm Bob Hagmann January 21, 1985 9:05:22 am PST Michael Plass, July 11, 1985 4:31:32 pm PDT Creates a pixelmap with a CountedVM.Handle, so a File.Read will work. Will raise a bounds fault if too many bits per line. Bob Hagmann January 21, 1985 8:53:18 am PST Modified to run under Commander changes to: DIRECTORY, ShowVAM, ShowVAMProc, ShowVMProc, ShowVAM, ShowVAMProc, ShowVMProc Imachael Plass, June 28, 1985 9:34:43 am PDT Modified to run under Imager, added other options to ShowVM Êü˜šœ™Icodešœ Ïmœ1™Jšœžœ˜&Jšœžœžœ˜!Jšœžœ ˜Jšœ žœ˜ Jšžœžœ˜Jšœ žœ ˜—J˜šÐln œžœž˜Jšžœžœ žœ žœ žœžœžœžœ žœžœ ˜‹—J˜šœž˜J˜Kšœžœ˜šœžœ˜K˜—Kšœžœ"˜7Kšœ žœ˜)Kšœžœ˜$šžœžœžœ˜K˜—Jšœžœžœ ˜šœ žœžœ˜J˜Jšœ˜Jšœ ˜ Jšœ˜J˜—š Ïnœžœžœžœ žœžœ˜;Kšœžœ˜Kšœžœ˜Kšœžœ ˜Kšœžœ˜ Kšœ-˜-Kšœ)˜)Kšœ žœžœ˜Kšžœžœžœžœ˜-Jšœ0˜0šžœž˜ šžœžœžœ˜"Jšœžœ˜3Jš œžœžœžœ žœžœ˜'Jšœ˜Jš œžœžœžœžœ ˜/Jšœžœ˜Jšœ žœ˜Kšœ1˜1šžœž˜Kšœžœžœ˜š žœžœžœ žœž˜5Kšœžœ žœ˜+šœžœž˜Kšœ$˜$Kšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—Kšœ˜Kšžœ˜—šžœ˜ Kšžœžœžœžœ˜(Kšœ˜Kšœ˜—Kšœžœ˜Kšžœ˜—Kšžœ žœ0˜AKšžœ-˜1Kšœ žœ˜Kšœ˜—Jšœ5˜5Kšžœ˜—Kšœ˜—J˜š   œžœžœžœ žœžœ˜žœ!˜iKšžœ žœ0˜AKšžœ-˜1Kšœ žœ˜Kšœ˜—Jšœ)˜)Kšžœ˜—Kšœ˜—J˜š  œžœžœ˜LKšœE™EKšœžœ˜šœ žœ˜-K™4—Kšœžœ=˜SKšœžœžœ/˜Cšžœ˜ Kšœ8˜8Kšœžœ˜2Kšœ ˜ Kšœ,˜,Kšœ(˜(Kšœ#˜#Kšœ$˜$Kšœ%˜%Kšœ˜—Kšœ"˜"KšœO˜OKšœ˜K˜—šÏb œ˜&Jšœ!˜!Jšœ˜Jšœžœ˜Jšœžœ˜šœ!˜!Icode1šœ+žœ˜6Lšœ˜—Jšžœžœžœžœ˜šžœžœ˜Jšœ˜Jšœ(˜(J˜—šœžœ˜Jšžœžœžœ˜!Jšœ*˜*Jšœ˜J˜—Jšžœ žœžœžœ ˜#šœ˜Jšœ ˜ Jšœžœ˜Jšœ+˜+Jšœ ž˜Jšœ˜—Jšœ0žœ0˜cšž˜Lšœ žœ˜ Lšœ žœ-˜