<> <> <> <> <> 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. <> <> <> <<>> <> <> <<>> <<>>