home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / packer / arc / arctool / tpstack.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-09-29  |  7.2 KB  |  249 lines

  1. {                      F i l e    I n f o r m a t i o n
  2.  
  3. * DESCRIPTION
  4. Unit for monitoring stack and heap usage.
  5.  
  6. * ASSOCIATED FILES
  7. TPSTACK.PAS
  8. TPSTACK.ASM
  9. TPSTACK.DOC
  10. TPSTACK.OBJ
  11.  
  12. }
  13. {$S-,R-,I-,B-,D-,F-}
  14.  
  15. {*********************************************************}
  16. {*                   TPSTACK.PAS 1.00                    *}
  17. {*                by TurboPower Software                 *}
  18. {*********************************************************}
  19.  
  20. unit TpStack;
  21.   {-Unit for monitoring stack and heap usage}
  22.  
  23. interface
  24.  
  25. const
  26.   {If True, results are reported automatically at the end of the program. Set
  27.    to False if you want to display results in another manner.}
  28.   ReportStackUsage : Boolean = True;
  29.  
  30. var
  31.   {The following variables, like the two procedures that follow, are interfaced
  32.    solely for the purpose of displaying results. You should never alter any of
  33.    these variables.}
  34.   OurSS : Word;              {value of SS register when program began}
  35.   InitialSP : Word;          {value of SP register when program began}
  36.   LowestSP : Word;           {lowest value for SP register}
  37.   HeapHigh : Pointer;        {highest address pointed to by HeapPtr}
  38.  
  39. procedure CalcStackUsage(var StackUsage : Word; var HeapUsage : LongInt);
  40.   {-Calculate stack and heap usage}
  41.  
  42. procedure ShowStackUsage;
  43.   {-Display stack and heap usage information}
  44.  
  45. {The next two routines are interfaced in case you need or want to deinstall the
  46.  INT $8 handler temporarily, as you might when using the Exec procedure in the
  47.  DOS unit.}
  48.  
  49. procedure InstallInt8;
  50.   {-Save INT $8 vector and install our ISR, if not already installed}
  51.  
  52. procedure RestoreInt8;
  53.   {-Restore the old INT $8 handler if our ISR is installed}
  54.  
  55. {The following routine allows you to alter the rate at which samples are taken.
  56.  For it to have any effect, it must be preceded by a call to RestoreInt8 and
  57.  followed by a call to InstallInt8.}
  58.  
  59. procedure SetSampleRate(Rate : Word);
  60.   {-Set number of samples per second. Default is 1165, minimum is 18.}
  61.  
  62.   {==========================================================================}
  63.  
  64. implementation
  65.  
  66. type
  67.   SegOfs =                   {structure of a 32-bit pointer}
  68.     record
  69.       Offset, Segment : Word;
  70.     end;
  71. const
  72.   Int8Installed : Boolean = False;  {True if our INT $8 handler is installed}
  73.   DefaultRate = 1024;        {corresponds to 1165 samples/second}
  74. var
  75.   SaveInt8 : ^Pointer;       {pointer to original INT $8 vector}
  76.   SaveExitProc : Pointer;    {saved value for ExitProc}
  77.   Vectors : array[0..$FF] of Pointer absolute $0:$0;
  78.   Rate8253,
  79.   Counts,
  80.   CountsPerTick : Word;
  81.  
  82.   procedure IntsOff;
  83.     {-Turn off CPU interrupts}
  84.   inline($FA);
  85.  
  86.   procedure IntsOn;
  87.     {-Turn on CPU interrupts}
  88.   inline($FB);
  89.  
  90.   {$L TPSTACK.OBJ}
  91.  
  92.   procedure ActualSaveInt8;
  93.     {-Actually a pointer variable in CS}
  94.     external {TPSTACK} ;
  95.  
  96.   procedure Int8;
  97.     {-Interrupt service routine used to monitor stack and heap usage}
  98.     external {TPSTACK} ;
  99.  
  100.   procedure SetTimerRate(Rate : Word);
  101.     {-Program system 8253 timer number 0 to run at specified rate}
  102.   begin                      {SetTimerRate}
  103.     IntsOff;
  104.     Port[$43] := $36;
  105.     Port[$40] := Lo(Rate);
  106.     inline($EB/$00);         {null jump}
  107.     Port[$40] := Hi(Rate);
  108.     IntsOn;
  109.   end;                       {SetTimerRate}
  110.  
  111.   procedure InstallInt8;
  112.     {-Save INT $8 vector and install our ISR, if not already installed}
  113.   begin                      {InstallInt8}
  114.     {make sure we're not already installed, in case we are called twice.
  115.      if we don't do this check, SaveInt8 could get pointed to *our* ISR}
  116.     if not Int8Installed then begin
  117.       {save the current vector}
  118.       SaveInt8^ := Vectors[$8];
  119.  
  120.       {Set counts til next system timer tick}
  121.       Counts := 0;
  122.  
  123.       {Keep interrupts off}
  124.       IntsOff;
  125.  
  126.       {Take over the timer tick}
  127.       Vectors[$8] := @Int8;
  128.  
  129.       {Reprogram the timer to run at the new rate}
  130.       SetTimerRate(Rate8253);
  131.  
  132.       {restore interrupts}
  133.       IntsOn;
  134.  
  135.       {now we're installed}
  136.       Int8Installed := True;
  137.     end;
  138.   end;                       {InstallInt8}
  139.  
  140.   procedure RestoreInt8;
  141.     {-Restore the old INT $8 handler if our ISR is installed}
  142.   begin                      {RestoreInt8}
  143.     {if we're currently installed, then deinstall}
  144.     if Int8Installed then begin
  145.       {no more samples}
  146.       IntsOff;
  147.  
  148.       {Give back the timer interrupt}
  149.       Vectors[$8] := SaveInt8^;
  150.  
  151.       {Reprogram the clock to run at normal rate}
  152.       SetTimerRate(0);
  153.  
  154.       {Normal interrupts again}
  155.       IntsOn;
  156.  
  157.       {no longer installed}
  158.       Int8Installed := False;
  159.     end;
  160.   end;                       {RestoreInt8}
  161.  
  162.   procedure SetSampleRate(Rate : Word);
  163.     {-Set number of samples per second. Default is 1165, minimum is 18.}
  164.   var
  165.     Disable : Boolean;
  166.   begin                      {SetSampleRate}
  167.     if (Rate >= 18) then begin
  168.       {deactivate Int8 temporarily if necessary}
  169.       Disable := Int8Installed;
  170.       if Disable then
  171.         RestoreInt8;
  172.  
  173.       Rate8253 := LongInt($123400) div LongInt(Rate);
  174.       CountsPerTick := LongInt($10000) div LongInt(Rate8253);
  175.  
  176.       {reactivate Int8 if necessary}
  177.       if Disable then
  178.         InstallInt8;
  179.     end;
  180.   end;                       {SetSampleRate}
  181.  
  182.   procedure CalcStackUsage(var StackUsage : Word; var HeapUsage : LongInt);
  183.     {-Calculate stack and heap usage}
  184.   begin                      {CalcStackUsage}
  185.     {calculate stack usage}
  186.     StackUsage := InitialSP-LowestSP;
  187.  
  188.     {calculate heap usage}
  189.     HeapUsage :=
  190.       (LongInt(SegOfs(HeapHigh).Segment-SegOfs(HeapOrg).Segment) * 16) +
  191.        LongInt(SegOfs(HeapHigh).Offset-SegOfs(HeapOrg).Offset);
  192.   end;                       {CalcStackUsage}
  193.  
  194.   procedure ShowStackUsage;
  195.     {-Display stack and heap usage information}
  196.   var
  197.     StackUsage : Word;
  198.     HeapUsage : LongInt;
  199.   begin                      {ShowStackUsage}
  200.     {calculate stack and heap usage}
  201.     CalcStackUsage(StackUsage, HeapUsage);
  202.  
  203.     {show them}
  204.     WriteLn('Stack usage: ', StackUsage, ' bytes.');
  205.     WriteLn('Heap usage:  ', HeapUsage, ' bytes.');
  206.   end;                       {ShowStackUsage}
  207.  
  208.   {$F+}  {Don't forget that exit handlers are always called FAR!}
  209.   procedure OurExitProc;
  210.     {-Deinstalls our INT $8 handler and reports stack/heap usage}
  211.   begin                      {OurExitProc}
  212.     {restore ExitProc}
  213.     ExitProc := SaveExitProc;
  214.  
  215.     {restore INT $8}
  216.     RestoreInt8;
  217.  
  218.     {show results if desired}
  219.     if ReportStackUsage then
  220.       ShowStackUsage;
  221.   end;                       {OurExitProc}
  222.   {$F-}
  223.  
  224. begin                        {TpStack}
  225.   {initialize SaveInt8}
  226.   SaveInt8 := @ActualSaveInt8;
  227.  
  228.   {initialize Rate8253 and CountsPerTick}
  229.   SetSampleRate(DefaultRate);
  230.  
  231.   {save current value for SS}
  232.   OurSS := SSeg;
  233.  
  234.   {save current value of SP and account for the return address on the stack}
  235.   InitialSP := SPtr+SizeOf(Pointer);
  236.   LowestSP := InitialSP;
  237.  
  238.   {save current position of HeapPtr}
  239.   HeapHigh := HeapPtr;
  240.  
  241.   {install our ISR}
  242.   InstallInt8;
  243.  
  244.   {save ExitProc and install our exit handler}
  245.   SaveExitProc := ExitProc;
  246.   ExitProc := @OurExitProc;
  247. end.                         {TpStack}
  248. 
  249.