OSDN Git Service

New file.
[pf3gnuchains/gcc-fork.git] / gcc / ada / s-stausa.ads
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS               --
4 --                                                                          --
5 --                   S Y S T E M - S T A C K _ U S A G E                    --
6 --                                                                          --
7 --                                 S p e c                                  --
8 --                                                                          --
9 --         Copyright (C) 2004-2005, Free Software Foundation, Inc.          --
10 --                                                                          --
11 -- GNARL is free software; you can  redistribute it  and/or modify it under --
12 -- terms of the  GNU General Public License as published  by the Free Soft- --
13 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
14 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNARL; see file COPYING.  If not, write --
19 -- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
20 -- Boston, MA 02110-1301, USA.                                              --
21 --                                                                          --
22 -- As a special exception,  if other files  instantiate  generics from this --
23 -- unit, or you link  this unit with other files  to produce an executable, --
24 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
25 -- covered  by the  GNU  General  Public  License.  This exception does not --
26 -- however invalidate  any other reasons why  the executable file  might be --
27 -- covered by the  GNU Public License.                                      --
28 --                                                                          --
29 -- GNARL was developed by the GNARL team at Florida State University.       --
30 -- Extensive contributions were provided by Ada Core Technologies, Inc.     --
31 --                                                                          --
32 ------------------------------------------------------------------------------
33
34 with System;
35 with System.Storage_Elements;
36 with System.Address_To_Access_Conversions;
37
38 package System.Stack_Usage is
39
40    package SSE renames System.Storage_Elements;
41
42    Byte_Size : constant := 8;
43    Word_32_Size : constant := 4 * Byte_Size;
44
45    type Word_32 is mod 2 ** Word_32_Size;
46    for Word_32'Alignment use 4;
47
48    subtype Stack_Address is SSE.Integer_Address;
49    --  Address on the stack.
50    --
51    --  NOTE:
52    --  *****
53    --
54    --  in this package, when comparing two addresses on the
55    --  stack, the comments use the terms "outer", "inner", "outermost"
56    --  and "innermost" instead of the ambigous "higher", "lower",
57    --  "highest" and "lowest". "inner" means "closer to the bottom of
58    --  stack" and is the contrary of "outer". "innermost" means "closest
59    --  address to the bottom of stack". The stack is growing from the
60    --  innermost addresses to the outermost addresses.
61
62    function To_Stack_Address (Value : Address) return Stack_Address
63      renames System.Storage_Elements.To_Integer;
64
65    type Stack_Analyzer is private;
66    --  Type of the stack analyzer tool. It is used to fill a portion of
67    --  the stack with Pattern, and to compute the stack used after some
68    --  execution.
69    --
70    --  USAGE:
71    --  ******
72    --
73    --  --  A typical use of the package is something like:
74    --
75    --  A : Stack_Analyzer;
76    --
77    --  task T is
78    --     pragma Storage_Size (A_Storage_Size);
79    --  end T;
80    --
81    --  [...]
82    --
83    --     Bottom_Of_Stack : aliased Integer;
84    --     --  Bottom_Of_Stack'Address will be used as an approximation of
85    --     --  the bottom of stack. A good practise is to avoid allocating
86    --     --  other local variables on this stack, as it would degrade
87    --     --  the quality of this approximation.
88    --
89    --  begin
90    --     Initialize_Analyzer (A,
91    --                          "Task t",
92    --                          A_Storage_Size - A_Guard,
93    --                          To_Stack_Address (Bottom_Of_Stack'Address));
94    --     Fill_Stack (A);
95    --     Some_User_Code;
96    --     Compute_Result (A);
97    --     Report_Result (A);
98    --  end T;
99    --
100    --
101    --  Errors:
102    --  *******
103    --
104    --  We are instrumenting the code to measure the stack used by the user
105    --  code. This method has a number of systematic errors, but several
106    --  methods can be used to evaluate or reduce those errors. Here are
107    --  those errors and the strategy that we use to deal with them:
108    --
109    --  * Bottom offset:
110    --   - Description: The procedure used to fill the stack with a given
111    --   pattern will itself have a stack frame. The value of the stack pointer
112    --   in this procedure is, therefore, different from the value before the
113    --   call to the instrumentation procedure.
114    --   - Strategy: The user of this package shall measure the bottom of stack
115    --   before the call to Fill_Stack and pass it in parameter.
116    --
117    --  * Instrumentation threshold at writing:
118    --   - Description: The procedure used to fill the stack with a given
119    --   pattern will itself have a stack frame.  Therefore, it will
120    --   fill the stack after this stack frame. This part of the stack will
121    --   appear as used in the final measure.
122    --   - Strategy: As the user pass the value of the bottom of stack to
123    --   the instrumentation to deal with the bottom offset error, and as
124    --   as the instrumentation procedure knows where the pattern filling
125    --   start on the stack, the difference between the two values is the
126    --   minimum stack usage that the method can measure. If, when the results
127    --   are computed, the pattern zone has been left untouched, we conclude
128    --   that the stack usage is inferior to this minimum stack usage.
129    --
130    --  * Instrumentation threshold at reading:
131    --   - Description: The procedure used to read the stack at the end of the
132    --   execution clobbers the stack by allocating its stack frame. If this
133    --   stack frame is bigger than the total stack used by the user code at
134    --   this point, it will increase the measured stack size.
135    --   - Strategy: We could augment this stack frame and see if it changes the
136    --   measure. However, this error should be negligeable.
137    --
138    --   * Pattern zone overflow:
139    --    - Description: The stack grows outer than the outermost bound of the
140    --    pattern zone. In that case, the outermost region modified in the
141    --    pattern is not the maximum value of the stack pointer during the
142    --    execution.
143    --    - Strategy: At the end of the execution, the difference between the
144    --    outermost memory region modified in the pattern zone and the
145    --    outermost bound of the pattern zone can be understood as the
146    --    biggest allocation that the method could have detect, provided
147    --    that there is no "Untouched allocated zone" error and no "Pattern
148    --    usage in user code" error. If no object in the user code is likely
149    --    to have this size, this is not likely to happen.
150    --
151    --   * Pattern usage in user code:
152    --    - Description: The pattern can be found in the object of the user
153    --    code. Therefore, the address space where this object has been
154    --    allocated will appear as untouched.
155    --    - Strategy: Choose a pattern that is uncommon. 16#0000_0000# is the
156    --    worst choice; 16#DEAD_BEEF# can be a good one. A good choice is an
157    --    address which is not a multiple of 2, and which is not in the
158    --    target address space. You can also change the pattern to see if
159    --    it changes the measure. Note that this error *very* rarely influence
160    --    the measure of the total stack usage: to have some influence, the
161    --    pattern has to be used in the object that has been allocated on the
162    --    outermost address of the used stack.
163    --
164    --   * Stack overflow:
165    --    - Description: The pattern zone does not fit on the stack.
166    --    This may lead to an erroneous execution.
167    --    - Strategy: Specify a storage size that is bigger than the
168    --    size of the pattern. 2 times bigger should be enough.
169    --
170    --   * Augmentation of the user stack frames:
171    --    - Description: The use of instrumentation object or procedure may
172    --    augment the stack frame of the caller.
173    --    - Strategy: Do *not* inline the instrumentation procedures. Do *not*
174    --    allocate the Stack_Analyzer object on the stack.
175    --
176    --   * Untouched allocated zone:
177    --    - Description: The user code may allocate objects that it will never
178    --    touch. In that case, the pattern will not be changed.
179    --    - Strategy: There are no way to detect this error. Fortunately, this
180    --    error is really rare, and it is most probably a bug in the user code,
181    --    e.g. some uninitialized variable. It is (most of the time) harmless:
182    --    it influences the measure only if the untouched allocated zone
183    --    happens to be located at the outermost value of the stack pointer
184    --    for the whole execution.
185
186    procedure Fill_Stack (Analyzer : in out Stack_Analyzer);
187    --  Fill an area of the stack with the pattern Analyzer.Pattern. The size
188    --  of this area is Analyzer.Size. After the call to this procedure,
189    --  the memory will look like that:
190    --
191    --                                                             Stack growing
192    --  ----------------------------------------------------------------------->
193    --  |<---------------------->|<----------------------------------->|
194    --  |  Stack frame           | Memory filled with Analyzer.Pattern |
195    --  |  of Fill_Stack         |                                     |
196    --  |  (deallocated at       |                                     |
197    --  |  the end of the call)  |                                     |
198    --  ^                        |                                     |
199    --  Analyzer.Bottom_Of_Stack ^                                     |
200    --                    Analyzer.Inner_Pattern_Mark                  ^
201    --                                            Analyzer.Outer_Pattern_Mark
202
203    procedure Compute_Result (Analyzer : in out Stack_Analyzer);
204    --  Read the patern zone and deduce the stack usage. It should
205    --  be called from the same frame as Fill_Stack. If Analyzer.Probe is not
206    --  null, an array of Word_32 with Analyzer.Probe elements is allocated on
207    --  Compute_Result's stack frame. Probe can be used to detect an
208    --  "instrumentation threshold at reading" error; See above.
209    --  After the call to this procedure, the memory will look like:
210    --
211    --                                                             Stack growing
212    --  ----------------------------------------------------------------------->
213    --  |<---------------------->|<-------------->|<--------->|<--------->|
214    --  |  Stack frame           | Array of       | used      |  Memory   |
215    --  |  of Compute_Result     | Analyzer.Probe | during    |   filled  |
216    --  |  (deallocated at       | elements       |  the      |    with   |
217    --  |  the end of the call)  |                | execution |  pattern  |
218    --  |                        ^                |           |           |
219    --  |                   Inner_Pattern_Mark    |           |           |
220    --  |                                                     |           |
221    --  |<---------------------------------------------------->           |
222    --                  Stack used                                        ^
223    --                                                     Outer_Pattern_Mark
224
225    procedure Report_Result (Analyzer : Stack_Analyzer);
226    --  Store the results of the computation in memory, at the address
227    --  corresponding to the symbol __gnat_stack_usage_results.
228
229    type Parameterless_Procedure is access procedure;
230
231    procedure Initialize_Analyzer
232      (Analyzer  : in out Stack_Analyzer;
233       Task_Name : String;
234       Size      : Natural;
235       Bottom    : Stack_Address;
236       Pattern   : Word_32 := 16#DEAD_BEEF#);
237    --  Should be called before any use of a Stack_Analyzer, to initialize it.
238    --  Size is the size of the pattern zone.
239    --  Bottom should be a close approximation of the caller base
240    --  frame address.
241
242    procedure Output_Results;
243    --  Print the results computed so far on the standard output. Should be
244    --  called when all tasks are dead.
245
246 private
247
248    package Word_32_Addr is
249       new System.Address_To_Access_Conversions (Word_32);
250
251    type Result_Array_Id is range 0 .. 1_023;
252
253    type Stack_Analyzer
254    is record
255       Size                   : Natural;
256       --  Size of the pattern zone.
257
258       Pattern                : Word_32 := 16#DEAD_BEEF#;
259       --  Pattern used to recognize untouched memory.
260
261       Inner_Pattern_Mark     : Stack_Address;
262       --  Innermost bound of the pattern area on the stack.
263
264       Outer_Pattern_Mark     : Stack_Address;
265       --  Outermost bound of the pattern area on the stack.
266
267       Outermost_Touched_Mark : Stack_Address;
268       --  Outermost address of the pattern area whose value it is pointing
269       --  at has been modified during execution. If the systematic error are
270       --  compensated, it is the outermost value of the stack pointer during
271       --  the execution.
272
273       Bottom_Of_Stack        : Stack_Address;
274       --  Address of the bottom of the stack, as given by the caller of
275       --  Initialize_Analyzer.
276
277       Array_Address          : Address;
278       --  Address of the array of Word_32 that represents the pattern zone.
279
280       First_Is_Outermost     : Boolean;
281       --  Set to true if the first element of the array of Word_32 that
282       --  represents the pattern zone is at the outermost address of the
283       --  pattern zone; false if it is the innermost address.
284
285       Result_Id              : Result_Array_Id;
286       --  Location in the result array of the result for the current task.
287    end record;
288
289 end System.Stack_Usage;