home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Black Box 4
/
BlackBox.cdr
/
progpas
/
opstack.arj
/
OPSTACK.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1990-01-15
|
8KB
|
261 lines
{$S-,R-,I-,B-,D-}
{*********************************************************}
{* OPSTACK.PAS 1.00 *}
{* by TurboPower Software *}
{*********************************************************}
unit OpStack;
{-Unit for monitoring stack and heap usage}
interface
const
{If True, results are reported automatically at the end of the program. Set
to False if you want to display results in another manner.}
ReportStackUsage : Boolean = True;
var
{The following variables, like the two procedures that follow, are interfaced
solely for the purpose of displaying results. You should never alter any of
these variables.}
OurSS : Word; {value of SS register when program began}
InitialSP : Word; {value of SP register when program began}
LowestSP : Word; {lowest value for SP register}
HeapHigh : Pointer; {highest address pointed to by HeapPtr}
FreePtrLow : Word; {lowest address pointed to by FreePtr}
procedure CalcStackUsage(var StackUsage : Word; {stack}
var HeapUsage : LongInt; {heap}
var FreeUsage : Word; {free list}
var MemUsage : LongInt); {total}
{-Calculate stack and heap usage}
procedure ShowStackUsage;
{-Display stack and heap usage information}
{The next two routines are interfaced in case you need or want to deinstall the
INT $8 handler temporarily, as you might when using the Exec procedure in the
DOS unit.}
procedure InstallInt8;
{-Save INT $8 vector and install our ISR, if not already installed}
procedure RestoreInt8;
{-Restore the old INT $8 handler if our ISR is installed}
{The following routine allows you to alter the rate at which samples are taken.
For it to have any effect, it must be preceded by a call to RestoreInt8 and
followed by a call to InstallInt8.}
procedure SetSampleRate(Rate : Word);
{-Set number of samples per second. Default is 1165, minimum is 18.}
{==========================================================================}
implementation
type
SegOfs = {structure of a 32-bit pointer}
record
Offset, Segment : Word;
end;
const
Int8Installed : Boolean = False; {True if our INT $8 handler is installed}
DefaultRate = 1024; {corresponds to 1165 samples/second}
var
SaveInt8 : ^Pointer; {pointer to original INT $8 vector}
SaveExitProc : Pointer; {saved value for ExitProc}
Vectors : array[0..$FF] of Pointer absolute $0:$0;
Rate8253,
Counts,
CountsPerTick : Word;
procedure IntsOff;
{-Turn off CPU interrupts}
inline($FA);
procedure IntsOn;
{-Turn on CPU interrupts}
inline($FB);
{$L OPSTACK.OBJ}
procedure ActualSaveInt8;
{-Actually a pointer variable in CS}
external {OPSTACK} ;
procedure Int8;
{-Interrupt service routine used to monitor stack and heap usage}
external {OPSTACK} ;
procedure SetTimerRate(Rate : Word);
{-Program system 8253 timer number 0 to run at specified rate}
begin
IntsOff;
Port[$43] := $36;
Port[$40] := Lo(Rate);
inline($EB/$00); {null jump}
Port[$40] := Hi(Rate);
IntsOn;
end;
procedure InstallInt8;
{-Save INT $8 vector and install our ISR, if not already installed}
begin
{make sure we're not already installed, in case we are called twice.
if we don't do this check, SaveInt8 could get pointed to *our* ISR}
if not Int8Installed then begin
{save the current vector}
SaveInt8^ := Vectors[$8];
{Set counts til next system timer tick}
Counts := 0;
{Keep interrupts off}
IntsOff;
{Take over the timer tick}
Vectors[$8] := @Int8;
{Reprogram the timer to run at the new rate}
SetTimerRate(Rate8253);
{restore interrupts}
IntsOn;
{now we're installed}
Int8Installed := True;
end;
end;
procedure RestoreInt8;
{-Restore the old INT $8 handler if our ISR is installed}
begin
{if we're currently installed, then deinstall}
if Int8Installed then begin
{no more samples}
IntsOff;
{Give back the timer interrupt}
Vectors[$8] := SaveInt8^;
{Reprogram the clock to run at normal rate}
SetTimerRate(0);
{Normal interrupts again}
IntsOn;
{no longer installed}
Int8Installed := False;
end;
end;
procedure SetSampleRate(Rate : Word);
{-Set number of samples per second. Default is 1165, minimum is 18.}
var
Disable : Boolean;
begin
if (Rate >= 18) then begin
{deactivate Int8 temporarily if necessary}
Disable := Int8Installed;
if Disable then
RestoreInt8;
Rate8253 := LongInt($123400) div LongInt(Rate);
CountsPerTick := LongInt($10000) div LongInt(Rate8253);
{reactivate Int8 if necessary}
if Disable then
InstallInt8;
end;
end;
procedure CalcStackUsage(var StackUsage : Word;
var HeapUsage : LongInt;
var FreeUsage : Word; {free list}
var MemUsage : LongInt);
{-Calculate stack and heap usage}
begin
{calculate stack usage}
StackUsage := InitialSP-LowestSP;
{calculate heap usage}
HeapUsage :=
(LongInt(SegOfs(HeapHigh).Segment-SegOfs(HeapOrg).Segment) * 16) +
LongInt(SegOfs(HeapHigh).Offset-SegOfs(HeapOrg).Offset);
{calculate free list usage}
if FreePtrLow = $FFFF then
FreeUsage := 0
else
FreeUsage := $10000-LongInt(FreePtrLow);
{calculate total memory usage}
MemUsage :=
(LongInt(SegOfs(HeapHigh).Segment-PrefixSeg) * 16) +
SegOfs(HeapHigh).Offset;
end;
procedure ShowStackUsage;
{-Display stack and heap usage information}
var
StackUsage : Word;
HeapUsage : LongInt;
FreeUsage : Word;
MemUsage : LongInt;
begin
{calculate stack and heap usage}
CalcStackUsage(StackUsage, HeapUsage, FreeUsage, MemUsage);
{show them}
WriteLn('Stack usage: ', StackUsage, ' bytes.');
WriteLn('Heap usage: ', HeapUsage, ' bytes.');
WriteLn('Free list usage: ', FreeUsage, ' bytes.');
WriteLn('Memory usage: ', MemUsage, ' bytes.');
end;
{$F+} {Don't forget that exit handlers are always called FAR!}
procedure OurExitProc;
{-Deinstalls our INT $8 handler and reports stack/heap usage}
begin
{restore ExitProc}
ExitProc := SaveExitProc;
{restore INT $8}
RestoreInt8;
{show results if desired}
if ReportStackUsage then
ShowStackUsage;
end;
{$F-}
begin
{initialize SaveInt8}
SaveInt8 := @ActualSaveInt8;
{initialize Rate8253 and CountsPerTick}
SetSampleRate(DefaultRate);
{save current value for SS}
OurSS := SSeg;
{save current value of SP and account for the return address on the stack}
InitialSP := SPtr+SizeOf(Pointer);
LowestSP := InitialSP;
{save current position of HeapPtr}
HeapHigh := HeapPtr;
{initialize FreePtrLow}
FreePtrLow := $FFFF;
{install our ISR}
InstallInt8;
{save ExitProc and install our exit handler}
SaveExitProc := ExitProc;
ExitProc := @OurExitProc;
end.