ShowVAMImpl.mesa
Copyright © 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
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: REFNIL] ~ {
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: BOOLTRUE;
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: REFNIL] ~ {
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: BOOLTRUE;
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] ~ {
Creates a pixelmap with a CountedVM.Handle, so a File.Read will work.
bitsPerPixel: INT ~ 1;
bitsPerLine: NAT ~ bounds.fSize*bitsPerPixel;
Will raise a bounds fault if too many bits per line.
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.
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