MODULE WMPerfMonPluginInterrupts;
IMPORT
WMPerfMonPlugins,
Machine, Modules;
CONST
ModuleName = "WMPerfMonPluginInterrupts";
TYPE
InterruptStatistics = OBJECT(WMPerfMonPlugins.Plugin)
PROCEDURE Init(p : WMPerfMonPlugins.Parameter);
VAR ds : WMPerfMonPlugins.DatasetDescriptor;
BEGIN
p.name := "Interrupts"; p.description := "Interrupt statistics";
p.modulename := ModuleName;
p.autoMin := FALSE; p.autoMax := TRUE; p.minDigits := 7;
NEW(ds, 44);
ds[0].name := "INT0-Divide Error";
ds[1].name := "INT1-Reserved";
ds[2].name := "INT2-NMI";
ds[3].name := "INT3-Breakpoint";
ds[4].name := "INT4-Overflow";
ds[5].name := "INT5-BOUND range exceeded";
ds[6].name := "INT6-Invalid Opcode";
ds[7].name := "INT7-No Math Coprocessor";
ds[8].name := "INT8-Double Fault";
ds[9].name := "INT9-CoprocessorSegment Overrun";
ds[10].name := "INT10-Invalid TSS";
ds[11].name := "INT11-Segment not present";
ds[12].name := "INT12-Stack segment fault";
ds[13].name := "INT13-General Protection";
ds[14].name := "INT14-Page Fault";
ds[15].name := "INT15-Reserved";
ds[16].name := "INT16-Math Fault";
ds[17].name := "INT17-Alignment Check";
ds[18].name := "INT18-Machine Check";
ds[19].name := "INT19-SIMD FP Exception";
ds[20].name := "INT32-IRQ0 (Timer)";
ds[21].name := "INT33-IRQ1 (Keyboard)";
ds[22].name := "INT35-IRQ3";
ds[23].name := "INT36-IRQ4";
ds[24].name := "INT37-IRQ5";
ds[25].name := "INT38-IRQ6";
ds[26].name := "INT39-IRQ7";
ds[27].name := "INT40-IRQ8 (RTC)";
ds[28].name := "INT41-IRQ9";
ds[29].name := "INT42-IRQ10";
ds[30].name := "INT43-IRQ11";
ds[31].name := "INT44-IRQ12";
ds[32].name := "INT45-IRQ13";
ds[33].name := "INT46-IRQ14";
ds[34].name := "INT47-IRQ15";
ds[35].name := "INT49-SMP Kernel Call";
ds[36].name := "INT58-SoftInt";
ds[37].name := "INT59-SMP Local IPC";
ds[38].name := "INT60-SMP Timer Interrupt";
ds[39].name := "INT61-SMP IPC ";
ds[40].name := "INT62-SMP Error Interrupt";
ds[41].name := "INT63-SMP Spurious Interrupt";
ds[42].name := "Total"; INCL(ds[42].flags, WMPerfMonPlugins.Sum);
ds[43].name := "Others";
p.datasetDescriptor := ds;
END Init;
PROCEDURE UpdateDataset;
VAR i, offset, temp : LONGINT;
BEGIN
FOR i := 0 TO 19 DO
dataset[i] := interrupts[i].count;
END;
offset := Machine.IRQ0;
dataset[20] := interrupts[offset + 0].count;
dataset[21] := interrupts[offset + 1].count;
FOR i := 3 TO 15 DO
dataset[22 - 3 + i] := interrupts[offset + i].count;
END;
dataset[35] := interrupts[49].count;
dataset[36] := interrupts[58].count;
dataset[37] := interrupts[59].count;
dataset[38] := interrupts[60].count;
dataset[39] := interrupts[61].count;
dataset[40] := interrupts[62].count;
dataset[41] := interrupts[63].count;
temp := others;
dataset[42] := temp;
FOR i := 0 TO 41 DO
dataset[42] := dataset[42] + dataset[i];
END;
dataset[43] := temp;
END UpdateDataset;
END InterruptStatistics;
InterruptInfo = RECORD
count : LONGINT;
handlerInstalled : BOOLEAN;
isOther : BOOLEAN;
END;
VAR
interrupts : ARRAY 256 OF InterruptInfo;
others : LONGINT;
PROCEDURE HandleInterrupts(VAR state : Machine.State);
BEGIN
IF (0 <= state.INT) & (state.INT < 256) THEN
IF interrupts[state.INT].handlerInstalled THEN
Machine.AtomicInc(interrupts[state.INT].count);
ELSE
Machine.AtomicInc(others);
END;
END;
END HandleInterrupts;
PROCEDURE RegisterHandlers;
VAR i : LONGINT;
BEGIN
FOR i := 0 TO LEN(interrupts)-1 DO interrupts[i].isOther := TRUE; END;
FOR i := 0 TO 19 DO interrupts[i].isOther := FALSE; END;
FOR i := 32 TO 47 DO interrupts[i].isOther := FALSE; END;
interrupts[49].isOther := FALSE;
FOR i := 58 TO 63 DO interrupts[i].isOther := FALSE; END;
FOR i := 244 TO 253 DO interrupts[i].isOther := FALSE; END;
FOR i := 0 TO 63 DO
IF (i # 34) & (i # 39) THEN
Machine.InstallHandler(HandleInterrupts, i);
interrupts[i].handlerInstalled := TRUE;
END;
END;
END RegisterHandlers;
PROCEDURE UnregisterHandlers;
VAR i : LONGINT;
BEGIN
FOR i := 0 TO LEN(interrupts)-1 DO
IF interrupts[i].handlerInstalled THEN
Machine.RemoveHandler(HandleInterrupts, i);
interrupts[i].count := 0;
interrupts[i].handlerInstalled := FALSE;
END;
END;
END UnregisterHandlers;
PROCEDURE InitPlugin;
VAR par : WMPerfMonPlugins.Parameter; plugin : InterruptStatistics;
BEGIN
NEW(par); NEW(plugin, par);
END InitPlugin;
PROCEDURE Install*;
END Install;
PROCEDURE Cleanup;
BEGIN
UnregisterHandlers;
WMPerfMonPlugins.updater.RemoveByModuleName(ModuleName);
END Cleanup;
BEGIN
Modules.InstallTermHandler(Cleanup);
RegisterHandlers;
InitPlugin;
END WMPerfMonPluginInterrupts.
WMPerfMonPluginInterrupts.Install ~ SystemTools.Free WMPerfMonPluginInterrupts ~