Commit 37000aba by Quentin Ochem Committed by Arnaud Charlet

s-stausa.ads, [...] (Initialize_Analyzer): Added parameter "Overflow_Guard".

2007-04-20  Quentin Ochem  <ochem@adacore.com>

	* s-stausa.ads, s-stausa.adb (Initialize_Analyzer): Added parameter
	"Overflow_Guard".
	(Stack_Analyzer): Added field "Overflow_Guard"
	(Task_Result): Added field "Overflow_Guard".
	(Index_Str): New constant.
	(Task_Name_Str): New constant.
	(Actual_Size_Str): New constant.
	(Pattern_Array_Element_Size): New constant.
	(Get_Usage_Range): New subprogram.
	(Output_Result): Added parameter Max_Size_Len and Max_Actual_Use_Len.
	Now align the output.
	Added comments.
	(Initialize): Added value for Overflow_Guard.
	(Fill_Stack): Use constant Pattern_Array_Elem_Size when relevant.
	Update the value of the overflow guard according to the actual
	beginning of the pattern array.
	(Initialize_Analyzer): Added parameter Overflow_Guard.
	Take this parameter into accound when computing the max size.
	(Compute_Result): Use constant Pattern_Array_Elem_Size when relevant.
	(Report_Result): Removed extra useless procedure.
	Updated call to Output_Result.
	Moved full computation of the Task_Result here.

From-SVN: r125465
parent 1513f9bf
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-- -- -- --
-- B o d y -- -- B o d y --
-- -- -- --
-- Copyright (C) 2004-2006, Free Software Foundation, Inc. -- -- Copyright (C) 2004-2007, Free Software Foundation, Inc. --
-- -- -- --
-- GNARL is free software; you can redistribute it and/or modify it under -- -- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- -- -- terms of the GNU General Public License as published by the Free Soft- --
...@@ -39,24 +39,42 @@ package body System.Stack_Usage is ...@@ -39,24 +39,42 @@ package body System.Stack_Usage is
use System.Storage_Elements; use System.Storage_Elements;
use System; use System;
use System.IO; use System.IO;
use Interfaces;
procedure Output_Result (Result_Id : Natural; Result : Task_Result);
Index_Str : constant String := "Index";
function Report_Result (Analyzer : Stack_Analyzer) return Natural; Task_Name_Str : constant String := "Task Name";
Stack_Size_Str : constant String := "Stack Size";
function Inner_Than Actual_Size_Str : constant String := "Stack usage [min - max]";
Pattern_Array_Elem_Size : constant Natural :=
(Unsigned_32_Size / Byte_Size);
function Get_Usage_Range (Result : Task_Result) return String;
-- Return string representing the range of possible result of stack usage
procedure Output_Result
(Result_Id : Natural;
Result : Task_Result;
Max_Stack_Size_Len : Natural;
Max_Actual_Use_Len : Natural);
-- Prints the result on the standard output. Result Id is the number of
-- the result in the array, and Result the contents of the actual result.
-- Max_Stack_Size_Len and Max_Actual_Use_Len are used for displaying the
-- proper layout. They hold the maximum length of the string representing
-- the Stack_Size and Actual_Use values.
function Closer_To_Bottom
(A1 : Stack_Address; (A1 : Stack_Address;
A2 : Stack_Address) return Boolean; A2 : Stack_Address) return Boolean;
pragma Inline (Inner_Than); pragma Inline (Closer_To_Bottom);
-- Return True if, according to the direction of the stack growth, A1 is -- Return True if, according to the direction of the stack growth, A1 is
-- inner than A2. Inlined to reduce the size of the stack used by the -- closer to the bottom than A2. Inlined to reduce the size of the stack
-- instrumentation code. -- used by the instrumentation code.
---------------- ----------------------
-- Inner_Than -- -- Closer_To_Bottom --
---------------- ----------------------
function Inner_Than function Closer_To_Bottom
(A1 : Stack_Address; (A1 : Stack_Address;
A2 : Stack_Address) return Boolean A2 : Stack_Address) return Boolean
is is
...@@ -66,27 +84,29 @@ package body System.Stack_Usage is ...@@ -66,27 +84,29 @@ package body System.Stack_Usage is
else else
return A2 > A1; return A2 > A1;
end if; end if;
end Inner_Than; end Closer_To_Bottom;
---------------- ----------------
-- Initialize -- -- Initialize --
---------------- ----------------
-- Add comments to this procedure ???
-- Other subprograms also need more comment in code???
procedure Initialize (Buffer_Size : Natural) is procedure Initialize (Buffer_Size : Natural) is
Bottom_Of_Stack : aliased Integer; Bottom_Of_Stack : aliased Integer;
Stack_Size_Chars : System.Address; Stack_Size_Chars : System.Address;
begin begin
-- Initialize the buffered result array
Result_Array := new Result_Array_Type (1 .. Buffer_Size); Result_Array := new Result_Array_Type (1 .. Buffer_Size);
Result_Array.all := Result_Array.all :=
(others => (others =>
(Task_Name => (Task_Name => (others => ASCII.NUL),
(others => ASCII.NUL), Measure => 0,
Measure => 0, Max_Size => 0,
Max_Size => 0)); Overflow_Guard => 0));
-- Set the Is_Enabled flag to true, so that the task wrapper knows that
-- it has to handle dynamic stack analysis
Is_Enabled := True; Is_Enabled := True;
...@@ -104,11 +124,12 @@ package body System.Stack_Usage is ...@@ -104,11 +124,12 @@ package body System.Stack_Usage is
begin begin
Stack_Size := System.CRTL.atoi (Stack_Size_Chars) * 1024; Stack_Size := System.CRTL.atoi (Stack_Size_Chars) * 1024;
Initialize_Analyzer (Environment_Task_Analyzer, Initialize_Analyzer
"ENVIRONMENT TASK", (Environment_Task_Analyzer,
Stack_Size, "ENVIRONMENT TASK",
System.Storage_Elements.To_Integer Stack_Size,
(Bottom_Of_Stack'Address)); 0,
System.Storage_Elements.To_Integer (Bottom_Of_Stack'Address));
Fill_Stack (Environment_Task_Analyzer); Fill_Stack (Environment_Task_Analyzer);
...@@ -133,43 +154,48 @@ package body System.Stack_Usage is ...@@ -133,43 +154,48 @@ package body System.Stack_Usage is
-- big, the more an "instrumentation threshold at writing" error is -- big, the more an "instrumentation threshold at writing" error is
-- likely to happen. -- likely to happen.
type Word_32_Arr is type Unsigned_32_Arr is
array (1 .. Analyzer.Size / (Word_32_Size / Byte_Size)) of Word_32; array (1 .. Analyzer.Size / Pattern_Array_Elem_Size) of Unsigned_32;
pragma Pack (Word_32_Arr); for Unsigned_32_Arr'Component_Size use 32;
package Arr_Addr is package Arr_Addr is
new System.Address_To_Access_Conversions (Word_32_Arr); new System.Address_To_Access_Conversions (Unsigned_32_Arr);
Arr : aliased Word_32_Arr; Arr : aliased Unsigned_32_Arr;
begin begin
for J in Word_32_Arr'Range loop -- Fill the stack with the pattern
for J in Unsigned_32_Arr'Range loop
Arr (J) := Analyzer.Pattern; Arr (J) := Analyzer.Pattern;
end loop; end loop;
-- Initialize the analyzer value
Analyzer.Array_Address := Arr_Addr.To_Address (Arr'Access); Analyzer.Array_Address := Arr_Addr.To_Address (Arr'Access);
Analyzer.Inner_Pattern_Mark := To_Stack_Address (Arr (1)'Address); Analyzer.Bottom_Pattern_Mark := To_Stack_Address (Arr (1)'Address);
Analyzer.Outer_Pattern_Mark := Analyzer.Top_Pattern_Mark :=
To_Stack_Address (Arr (Word_32_Arr'Last)'Address); To_Stack_Address (Arr (Unsigned_32_Arr'Last)'Address);
if Inner_Than (Analyzer.Outer_Pattern_Mark, if
Analyzer.Inner_Pattern_Mark) then Closer_To_Bottom
Analyzer.Inner_Pattern_Mark := Analyzer.Outer_Pattern_Mark; (Analyzer.Top_Pattern_Mark, Analyzer.Bottom_Pattern_Mark)
Analyzer.Outer_Pattern_Mark := To_Stack_Address (Arr (1)'Address); then
Analyzer.First_Is_Outermost := True; Analyzer.Bottom_Pattern_Mark := Analyzer.Top_Pattern_Mark;
Analyzer.Top_Pattern_Mark := To_Stack_Address (Arr (1)'Address);
Analyzer.First_Is_Topmost := True;
else else
Analyzer.First_Is_Outermost := False; Analyzer.First_Is_Topmost := False;
end if; end if;
-- If Arr has been packed, the following assertion must be true (we add -- If Arr has been packed, the following assertion must be true (we add
-- the size of the element whose address is: -- the size of the element whose address is:
--
-- Min (Analyzer.Inner_Pattern_Mark, Analyzer.Outer_Pattern_Mark)): -- Min (Analyzer.Inner_Pattern_Mark, Analyzer.Outer_Pattern_Mark)):
pragma Assert pragma Assert
(Analyzer.Size = (Analyzer.Size =
Stack_Size Stack_Size
(Analyzer.Outer_Pattern_Mark, Analyzer.Inner_Pattern_Mark) + (Analyzer.Top_Pattern_Mark, Analyzer.Bottom_Pattern_Mark));
Word_32_Size / Byte_Size);
end Fill_Stack; end Fill_Stack;
------------------------- -------------------------
...@@ -177,13 +203,16 @@ package body System.Stack_Usage is ...@@ -177,13 +203,16 @@ package body System.Stack_Usage is
------------------------- -------------------------
procedure Initialize_Analyzer procedure Initialize_Analyzer
(Analyzer : in out Stack_Analyzer; (Analyzer : in out Stack_Analyzer;
Task_Name : String; Task_Name : String;
Size : Natural; Size : Natural;
Bottom : Stack_Address; Overflow_Guard : Natural;
Pattern : Word_32 := 16#DEAD_BEEF#) Bottom : Stack_Address;
Pattern : Unsigned_32 := 16#DEAD_BEEF#)
is is
begin begin
-- Initialize the analyzer fields
Analyzer.Bottom_Of_Stack := Bottom; Analyzer.Bottom_Of_Stack := Bottom;
Analyzer.Size := Size; Analyzer.Size := Size;
Analyzer.Pattern := Pattern; Analyzer.Pattern := Pattern;
...@@ -191,6 +220,9 @@ package body System.Stack_Usage is ...@@ -191,6 +220,9 @@ package body System.Stack_Usage is
Analyzer.Task_Name := (others => ' '); Analyzer.Task_Name := (others => ' ');
-- Compute the task name, and truncate it if it's bigger than
-- Task_Name_Length
if Task_Name'Length <= Task_Name_Length then if Task_Name'Length <= Task_Name_Length then
Analyzer.Task_Name (1 .. Task_Name'Length) := Task_Name; Analyzer.Task_Name (1 .. Task_Name'Length) := Task_Name;
else else
...@@ -199,11 +231,8 @@ package body System.Stack_Usage is ...@@ -199,11 +231,8 @@ package body System.Stack_Usage is
Task_Name'First + Task_Name_Length - 1); Task_Name'First + Task_Name_Length - 1);
end if; end if;
if Next_Id in Result_Array'Range then Analyzer.Overflow_Guard := Overflow_Guard;
Result_Array (Analyzer.Result_Id).Task_Name := Analyzer.Task_Name;
end if;
Result_Array (Analyzer.Result_Id).Max_Size := Size;
Next_Id := Next_Id + 1; Next_Id := Next_Id + 1;
end Initialize_Analyzer; end Initialize_Analyzer;
...@@ -234,25 +263,29 @@ package body System.Stack_Usage is ...@@ -234,25 +263,29 @@ package body System.Stack_Usage is
-- is, the more an "instrumentation threshold at reading" error is -- is, the more an "instrumentation threshold at reading" error is
-- likely to happen. -- likely to happen.
type Word_32_Arr is type Unsigned_32_Arr is
array (1 .. Analyzer.Size / (Word_32_Size / Byte_Size)) of Word_32; array (1 .. Analyzer.Size / Pattern_Array_Elem_Size) of Unsigned_32;
pragma Pack (Word_32_Arr); for Unsigned_32_Arr'Component_Size use 32;
package Arr_Addr is package Arr_Addr is
new System.Address_To_Access_Conversions (Word_32_Arr); new System.Address_To_Access_Conversions (Unsigned_32_Arr);
Arr_Access : Arr_Addr.Object_Pointer; Arr_Access : Arr_Addr.Object_Pointer;
begin begin
Arr_Access := Arr_Addr.To_Pointer (Analyzer.Array_Address); Arr_Access := Arr_Addr.To_Pointer (Analyzer.Array_Address);
Analyzer.Outermost_Touched_Mark := Analyzer.Inner_Pattern_Mark; Analyzer.Topmost_Touched_Mark := Analyzer.Bottom_Pattern_Mark;
-- Look backward from the end of the stack to the beginning. The first
-- index not equals to the patterns marks the beginning of the used
-- stack.
for J in Word_32_Arr'Range loop for J in Unsigned_32_Arr'Range loop
if Arr_Access (J) /= Analyzer.Pattern then if Arr_Access (J) /= Analyzer.Pattern then
Analyzer.Outermost_Touched_Mark := Analyzer.Topmost_Touched_Mark :=
To_Stack_Address (Arr_Access (J)'Address); To_Stack_Address (Arr_Access (J)'Address);
if Analyzer.First_Is_Outermost then if Analyzer.First_Is_Topmost then
exit; exit;
end if; end if;
end if; end if;
...@@ -260,19 +293,51 @@ package body System.Stack_Usage is ...@@ -260,19 +293,51 @@ package body System.Stack_Usage is
end Compute_Result; end Compute_Result;
--------------------- ---------------------
-- Get_Usage_Range --
---------------------
function Get_Usage_Range (Result : Task_Result) return String is
Min_Used_Str : constant String :=
Natural'Image (Result.Measure);
Max_Used_Str : constant String :=
Natural'Image (Result.Measure + Result.Overflow_Guard);
begin
return "[" & Min_Used_Str (2 .. Min_Used_Str'Last) & " -"
& Max_Used_Str & "]";
end Get_Usage_Range;
---------------------
-- Output_Result -- -- Output_Result --
--------------------- ---------------------
procedure Output_Result (Result_Id : Natural; Result : Task_Result) is procedure Output_Result
(Result_Id : Natural;
Result : Task_Result;
Max_Stack_Size_Len : Natural;
Max_Actual_Use_Len : Natural)
is
Result_Id_Str : constant String := Natural'Image (Result_Id);
Stack_Size_Str : constant String := Natural'Image (Result.Max_Size);
Actual_Use_Str : constant String := Get_Usage_Range (Result);
Result_Id_Blanks : constant
String (1 .. Index_Str'Length - Result_Id_Str'Length) :=
(others => ' ');
Stack_Size_Blanks : constant
String (1 .. Max_Stack_Size_Len - Stack_Size_Str'Length) :=
(others => ' ');
Actual_Use_Blanks : constant
String (1 .. Max_Actual_Use_Len - Actual_Use_Str'Length) :=
(others => ' ');
begin begin
Set_Output (Standard_Error); Set_Output (Standard_Error);
Put (Natural'Image (Result_Id)); Put (Result_Id_Blanks & Natural'Image (Result_Id));
Put (" | "); Put (" | ");
Put (Result.Task_Name); Put (Result.Task_Name);
Put (" | "); Put (" | ");
Put (Natural'Image (Result.Max_Size)); Put (Stack_Size_Blanks & Stack_Size_Str);
Put (" | "); Put (" | ");
Put (Natural'Image (Result.Measure)); Put (Actual_Use_Blanks & Actual_Use_Str);
New_Line; New_Line;
end Output_Result; end Output_Result;
...@@ -281,21 +346,87 @@ package body System.Stack_Usage is ...@@ -281,21 +346,87 @@ package body System.Stack_Usage is
--------------------- ---------------------
procedure Output_Results is procedure Output_Results is
Max_Stack_Size : Natural := 0;
Max_Actual_Use_Result_Id : Natural := Result_Array'First;
Max_Stack_Size_Len, Max_Actual_Use_Len : Natural := 0;
Task_Name_Blanks :
constant String (1 .. Task_Name_Length - Task_Name_Str'Length) :=
(others => ' ');
begin begin
Set_Output (Standard_Error);
if Compute_Environment_Task then if Compute_Environment_Task then
Compute_Result (Environment_Task_Analyzer); Compute_Result (Environment_Task_Analyzer);
Report_Result (Environment_Task_Analyzer); Report_Result (Environment_Task_Analyzer);
end if; end if;
Set_Output (Standard_Error); if Result_Array'Length > 0 then
Put ("Index | Task Name | Stack Size | Actual Use"); -- Computes the size of the largest strings that will get displayed,
New_Line; -- in order to do correct column alignment.
for J in Result_Array'Range loop for J in Result_Array'Range loop
exit when J >= Next_Id; exit when J >= Next_Id;
Output_Result (J, Result_Array (J)); if Result_Array (J).Measure
end loop; > Result_Array (Max_Actual_Use_Result_Id).Measure
then
Max_Actual_Use_Result_Id := J;
end if;
if Result_Array (J).Max_Size > Max_Stack_Size then
Max_Stack_Size := Result_Array (J).Max_Size;
end if;
end loop;
Max_Stack_Size_Len := Natural'Image (Max_Stack_Size)'Length;
Max_Actual_Use_Len :=
Get_Usage_Range (Result_Array (Max_Actual_Use_Result_Id))'Length;
-- Display the output header. Blanks will be added in front of the
-- labels if needed.
declare
Stack_Size_Blanks : constant
String (1 .. Max_Stack_Size_Len - Stack_Size_Str'Length) :=
(others => ' ');
Stack_Usage_Blanks : constant
String (1 .. Max_Actual_Use_Len - Actual_Size_Str'Length) :=
(others => ' ');
begin
if Stack_Size_Str'Length > Max_Stack_Size_Len then
Max_Stack_Size_Len := Stack_Size_Str'Length;
end if;
if Actual_Size_Str'Length > Max_Actual_Use_Len then
Max_Actual_Use_Len := Actual_Size_Str'Length;
end if;
Put
(Index_Str & " | " & Task_Name_Str & Task_Name_Blanks & " | "
& Stack_Size_Str & Stack_Size_Blanks & " | "
& Stack_Usage_Blanks & Actual_Size_Str);
end;
New_Line;
-- Now display the individual results
for J in Result_Array'Range loop
exit when J >= Next_Id;
Output_Result
(J, Result_Array (J), Max_Stack_Size_Len, Max_Actual_Use_Len);
end loop;
else
-- If there are no result stored, we'll still display the labels
Put
(Index_Str & " | " & Task_Name_Str & Task_Name_Blanks & " | "
& Stack_Size_Str & " | " & Actual_Size_Str);
New_Line;
end if;
end Output_Results; end Output_Results;
------------------- -------------------
...@@ -303,27 +434,60 @@ package body System.Stack_Usage is ...@@ -303,27 +434,60 @@ package body System.Stack_Usage is
------------------- -------------------
procedure Report_Result (Analyzer : Stack_Analyzer) is procedure Report_Result (Analyzer : Stack_Analyzer) is
Result : constant Task_Result :=
(Task_Name => Analyzer.Task_Name,
Max_Size => Analyzer.Size + Analyzer.Overflow_Guard,
Measure => Stack_Size
(Analyzer.Topmost_Touched_Mark,
Analyzer.Bottom_Of_Stack),
Overflow_Guard => Analyzer.Overflow_Guard -
Natural (Analyzer.Bottom_Of_Stack -
Analyzer.Bottom_Pattern_Mark));
begin begin
if Analyzer.Result_Id in Result_Array'Range then if Analyzer.Result_Id in Result_Array'Range then
Result_Array (Analyzer.Result_Id).Measure := Report_Result (Analyzer);
else
Output_Result
(Analyzer.Result_Id,
(Task_Name => Analyzer.Task_Name,
Max_Size => Analyzer.Size,
Measure => Report_Result (Analyzer)));
end if;
end Report_Result;
function Report_Result (Analyzer : Stack_Analyzer) return Natural is -- If the result can be stored, then store it in Result_Array
begin
if Analyzer.Outermost_Touched_Mark = Analyzer.Inner_Pattern_Mark then Result_Array (Analyzer.Result_Id) := Result;
return Stack_Size (Analyzer.Inner_Pattern_Mark,
Analyzer.Bottom_Of_Stack);
else else
return Stack_Size (Analyzer.Outermost_Touched_Mark,
Analyzer.Bottom_Of_Stack); -- If the result cannot be stored, then we display it right away
declare
Result_Str_Len : constant Natural :=
Get_Usage_Range (Result)'Length;
Size_Str_Len : constant Natural :=
Natural'Image (Analyzer.Size)'Length;
Max_Stack_Size_Len : Natural;
Max_Actual_Use_Len : Natural;
begin
-- Take either the label size or the number image size for the
-- size of the column "Stack Size".
if Size_Str_Len > Stack_Size_Str'Length then
Max_Stack_Size_Len := Size_Str_Len;
else
Max_Stack_Size_Len := Stack_Size_Str'Length;
end if;
-- Take either the label size or the number image size for the
-- size of the column "Stack Usage"
if Result_Str_Len > Actual_Size_Str'Length then
Max_Actual_Use_Len := Result_Str_Len;
else
Max_Actual_Use_Len := Actual_Size_Str'Length;
end if;
Output_Result
(Analyzer.Result_Id,
Result,
Max_Stack_Size_Len,
Max_Actual_Use_Len);
end;
end if; end if;
end Report_Result; end Report_Result;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-- -- -- --
-- S p e c -- -- S p e c --
-- -- -- --
-- Copyright (C) 2004-2005, Free Software Foundation, Inc. -- -- Copyright (C) 2004-2007, Free Software Foundation, Inc. --
-- -- -- --
-- GNARL is free software; you can redistribute it and/or modify it under -- -- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- -- -- terms of the GNU General Public License as published by the Free Soft- --
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
with System; with System;
with System.Storage_Elements; with System.Storage_Elements;
with System.Address_To_Access_Conversions; with System.Address_To_Access_Conversions;
with Interfaces;
package System.Stack_Usage is package System.Stack_Usage is
pragma Preelaborate; pragma Preelaborate;
...@@ -41,25 +42,18 @@ package System.Stack_Usage is ...@@ -41,25 +42,18 @@ package System.Stack_Usage is
package SSE renames System.Storage_Elements; package SSE renames System.Storage_Elements;
Byte_Size : constant := 8; Byte_Size : constant := 8;
Word_32_Size : constant := 4 * Byte_Size; Unsigned_32_Size : constant := 4 * Byte_Size;
type Word_32 is mod 2 ** Word_32_Size; -- The alignment clause seems dubious, what about architectures where
for Word_32'Alignment use 4; -- the maximum alignment is less than 4???
-- Anyway, why not use Interfaces.Unsigned_32???
subtype Stack_Address is SSE.Integer_Address; subtype Stack_Address is SSE.Integer_Address;
-- Address on the stack -- Address on the stack
--
-- Note: in this package, when comparing two addresses on the stack, the
-- comments use the terms "outer", "inner", "outermost" and "innermost"
-- instead of the ambigous "higher", "lower", "highest" and "lowest".
-- "inner" means "closer to the bottom of stack" and is the contrary of
-- "outer". "innermost" means "closest address to the bottom of stack". The
-- stack is growing from the inner to the outer.
-- Top/Bottom would be much better than inner and outer ???
function To_Stack_Address (Value : System.Address) return Stack_Address function To_Stack_Address
renames System.Storage_Elements.To_Integer; (Value : System.Address) return Stack_Address
renames System.Storage_Elements.To_Integer;
type Stack_Analyzer is private; type Stack_Analyzer is private;
-- Type of the stack analyzer tool. It is used to fill a portion of -- Type of the stack analyzer tool. It is used to fill a portion of
...@@ -88,6 +82,7 @@ package System.Stack_Usage is ...@@ -88,6 +82,7 @@ package System.Stack_Usage is
-- Initialize_Analyzer (A, -- Initialize_Analyzer (A,
-- "Task t", -- "Task t",
-- A_Storage_Size - A_Guard, -- A_Storage_Size - A_Guard,
-- A_Guard
-- To_Stack_Address (Bottom_Of_Stack'Address)); -- To_Stack_Address (Bottom_Of_Stack'Address));
-- Fill_Stack (A); -- Fill_Stack (A);
-- Some_User_Code; -- Some_User_Code;
...@@ -139,14 +134,14 @@ package System.Stack_Usage is ...@@ -139,14 +134,14 @@ package System.Stack_Usage is
-- Pattern zone overflow: -- Pattern zone overflow:
-- Description: The stack grows outer than the outermost bound of the -- Description: The stack grows outer than the topmost bound of the
-- pattern zone. In that case, the outermost region modified in the -- pattern zone. In that case, the topmost region modified in the
-- pattern is not the maximum value of the stack pointer during the -- pattern is not the maximum value of the stack pointer during the
-- execution. -- execution.
-- Strategy: At the end of the execution, the difference between the -- Strategy: At the end of the execution, the difference between the
-- outermost memory region modified in the pattern zone and the -- topmost memory region modified in the pattern zone and the
-- outermost bound of the pattern zone can be understood as the -- topmost bound of the pattern zone can be understood as the
-- biggest allocation that the method could have detect, provided -- biggest allocation that the method could have detect, provided
-- that there is no "Untouched allocated zone" error and no "Pattern -- that there is no "Untouched allocated zone" error and no "Pattern
-- usage in user code" error. If no object in the user code is likely -- usage in user code" error. If no object in the user code is likely
...@@ -165,7 +160,7 @@ package System.Stack_Usage is ...@@ -165,7 +160,7 @@ package System.Stack_Usage is
-- changes the measure. Note that this error *very* rarely influence -- changes the measure. Note that this error *very* rarely influence
-- the measure of the total stack usage: to have some influence, the -- the measure of the total stack usage: to have some influence, the
-- pattern has to be used in the object that has been allocated on the -- pattern has to be used in the object that has been allocated on the
-- outermost address of the used stack. -- topmost address of the used stack.
-- Stack overflow: -- Stack overflow:
...@@ -192,7 +187,7 @@ package System.Stack_Usage is ...@@ -192,7 +187,7 @@ package System.Stack_Usage is
-- error is really rare, and it is most probably a bug in the user -- error is really rare, and it is most probably a bug in the user
-- code, e.g. some uninitialized variable. It is (most of the time) -- code, e.g. some uninitialized variable. It is (most of the time)
-- harmless: it influences the measure only if the untouched allocated -- harmless: it influences the measure only if the untouched allocated
-- zone happens to be located at the outermost value of the stack -- zone happens to be located at the topmost value of the stack
-- pointer for the whole execution. -- pointer for the whole execution.
procedure Initialize (Buffer_Size : Natural); procedure Initialize (Buffer_Size : Natural);
...@@ -215,15 +210,16 @@ package System.Stack_Usage is ...@@ -215,15 +210,16 @@ package System.Stack_Usage is
-- | the end of the call) | | -- | the end of the call) | |
-- ^ | | -- ^ | |
-- Analyzer.Bottom_Of_Stack ^ | -- Analyzer.Bottom_Of_Stack ^ |
-- Analyzer.Inner_Pattern_Mark ^ -- Analyzer.Bottom_Pattern_Mark ^
-- Analyzer.Outer_Pattern_Mark -- Analyzer.Top_Pattern_Mark
procedure Initialize_Analyzer procedure Initialize_Analyzer
(Analyzer : in out Stack_Analyzer; (Analyzer : in out Stack_Analyzer;
Task_Name : String; Task_Name : String;
Size : Natural; Size : Natural;
Bottom : Stack_Address; Overflow_Guard : Natural;
Pattern : Word_32 := 16#DEAD_BEEF#); Bottom : Stack_Address;
Pattern : Interfaces.Unsigned_32 := 16#DEAD_BEEF#);
-- Should be called before any use of a Stack_Analyzer, to initialize it. -- Should be called before any use of a Stack_Analyzer, to initialize it.
-- Size is the size of the pattern zone. Bottom should be a close -- Size is the size of the pattern zone. Bottom should be a close
-- approximation of the caller base frame address. -- approximation of the caller base frame address.
...@@ -234,7 +230,7 @@ package System.Stack_Usage is ...@@ -234,7 +230,7 @@ package System.Stack_Usage is
procedure Compute_Result (Analyzer : in out Stack_Analyzer); procedure Compute_Result (Analyzer : in out Stack_Analyzer);
-- Read the patern zone and deduce the stack usage. It should be called -- Read the patern zone and deduce the stack usage. It should be called
-- from the same frame as Fill_Stack. If Analyzer.Probe is not null, an -- from the same frame as Fill_Stack. If Analyzer.Probe is not null, an
-- array of Word_32 with Analyzer.Probe elements is allocated on -- array of Unsigned_32 with Analyzer.Probe elements is allocated on
-- Compute_Result's stack frame. Probe can be used to detect the error: -- Compute_Result's stack frame. Probe can be used to detect the error:
-- "instrumentation threshold at reading". See above. After the call -- "instrumentation threshold at reading". See above. After the call
-- to this procedure, the memory will look like: -- to this procedure, the memory will look like:
...@@ -247,11 +243,11 @@ package System.Stack_Usage is ...@@ -247,11 +243,11 @@ package System.Stack_Usage is
-- | (deallocated at | elements | the | with | -- | (deallocated at | elements | the | with |
-- | the end of the call) | | execution | pattern | -- | the end of the call) | | execution | pattern |
-- | ^ | | | -- | ^ | | |
-- | Inner_Pattern_Mark | | | -- | Bottom_Pattern_Mark | | |
-- | | | -- | | |
-- |<----------------------------------------------------> | -- |<----------------------------------------------------> |
-- Stack used ^ -- Stack used ^
-- Outer_Pattern_Mark -- Top_Pattern_Mark
procedure Report_Result (Analyzer : Stack_Analyzer); procedure Report_Result (Analyzer : Stack_Analyzer);
-- Store the results of the computation in memory, at the address -- Store the results of the computation in memory, at the address
...@@ -268,9 +264,11 @@ package System.Stack_Usage is ...@@ -268,9 +264,11 @@ package System.Stack_Usage is
private private
Task_Name_Length : constant := 32; Task_Name_Length : constant := 32;
-- The maximum length of task name displayed.
-- ??? Consider merging this variable with Max_Task_Image_Length.
package Word_32_Addr is package Unsigned_32_Addr is
new System.Address_To_Access_Conversions (Word_32); new System.Address_To_Access_Conversions (Interfaces.Unsigned_32);
type Stack_Analyzer is record type Stack_Analyzer is record
Task_Name : String (1 .. Task_Name_Length); Task_Name : String (1 .. Task_Name_Length);
...@@ -279,19 +277,19 @@ private ...@@ -279,19 +277,19 @@ private
Size : Natural; Size : Natural;
-- Size of the pattern zone -- Size of the pattern zone
Pattern : Word_32; Pattern : Interfaces.Unsigned_32;
-- Pattern used to recognize untouched memory -- Pattern used to recognize untouched memory
Inner_Pattern_Mark : Stack_Address; Bottom_Pattern_Mark : Stack_Address;
-- Innermost bound of the pattern area on the stack -- Bound of the pattern area on the stack clostest to the bottom
Outer_Pattern_Mark : Stack_Address; Top_Pattern_Mark : Stack_Address;
-- Outermost bound of the pattern area on the stack -- Topmost bound of the pattern area on the stack
Outermost_Touched_Mark : Stack_Address; Topmost_Touched_Mark : Stack_Address;
-- Outermost address of the pattern area whose value it is pointing -- Topmost address of the pattern area whose value it is pointing
-- at has been modified during execution. If the systematic error are -- at has been modified during execution. If the systematic error are
-- compensated, it is the outermost value of the stack pointer during -- compensated, it is the topmost value of the stack pointer during
-- the execution. -- the execution.
Bottom_Of_Stack : Stack_Address; Bottom_Of_Stack : Stack_Address;
...@@ -299,16 +297,20 @@ private ...@@ -299,16 +297,20 @@ private
-- Initialize_Analyzer. -- Initialize_Analyzer.
Array_Address : System.Address; Array_Address : System.Address;
-- Address of the array of Word_32 that represents the pattern zone -- Address of the array of Unsigned_32 that represents the pattern zone
First_Is_Outermost : Boolean; First_Is_Topmost : Boolean;
-- Set to true if the first element of the array of Word_32 that -- Set to true if the first element of the array of Unsigned_32 that
-- represents the pattern zone is at the outermost address of the -- represents the pattern zone is at the topmost address of the
-- pattern zone; false if it is the innermost address. -- pattern zone; false if it is the bottommost address.
Result_Id : Positive; Result_Id : Positive;
-- Id of the result. If less than value given to gnatbind -u corresponds -- Id of the result. If less than value given to gnatbind -u corresponds
-- to the location in the result array of result for the current task. -- to the location in the result array of result for the current task.
Overflow_Guard : Natural;
-- The amount of bytes that won't be analyzed in order to prevent
-- writing out of the stack
end record; end record;
Environment_Task_Analyzer : Stack_Analyzer; Environment_Task_Analyzer : Stack_Analyzer;
...@@ -316,9 +318,10 @@ private ...@@ -316,9 +318,10 @@ private
Compute_Environment_Task : Boolean; Compute_Environment_Task : Boolean;
type Task_Result is record type Task_Result is record
Task_Name : String (1 .. Task_Name_Length); Task_Name : String (1 .. Task_Name_Length);
Measure : Natural; Measure : Natural;
Max_Size : Natural; Max_Size : Natural;
Overflow_Guard : Natural;
end record; end record;
type Result_Array_Type is array (Positive range <>) of Task_Result; type Result_Array_Type is array (Positive range <>) of Task_Result;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment