Mercurial > hg > CbC > CbC_gcc
comparison gcc/ada/libgnat/s-stausa.ads @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
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-2017, 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 3, or (at your option) any later ver- -- | |
14 -- sion. GNAT 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. -- | |
17 -- -- | |
18 -- As a special exception under Section 7 of GPL version 3, you are granted -- | |
19 -- additional permissions described in the GCC Runtime Library Exception, -- | |
20 -- version 3.1, as published by the Free Software Foundation. -- | |
21 -- -- | |
22 -- You should have received a copy of the GNU General Public License and -- | |
23 -- a copy of the GCC Runtime Library Exception along with this program; -- | |
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- | |
25 -- <http://www.gnu.org/licenses/>. -- | |
26 -- -- | |
27 -- GNARL was developed by the GNARL team at Florida State University. -- | |
28 -- Extensive contributions were provided by Ada Core Technologies, Inc. -- | |
29 -- -- | |
30 ------------------------------------------------------------------------------ | |
31 | |
32 with System; | |
33 with System.Storage_Elements; | |
34 with System.Address_To_Access_Conversions; | |
35 with Interfaces; | |
36 | |
37 package System.Stack_Usage is | |
38 pragma Preelaborate; | |
39 | |
40 package SSE renames System.Storage_Elements; | |
41 | |
42 subtype Stack_Address is SSE.Integer_Address; | |
43 -- Address on the stack | |
44 | |
45 function To_Stack_Address | |
46 (Value : System.Address) return Stack_Address | |
47 renames System.Storage_Elements.To_Integer; | |
48 | |
49 Task_Name_Length : constant := 32; | |
50 -- The maximum length of task name displayed. | |
51 -- ??? Consider merging this variable with Max_Task_Image_Length. | |
52 | |
53 type Task_Result is record | |
54 Task_Name : String (1 .. Task_Name_Length); | |
55 | |
56 Value : Natural; | |
57 -- Amount of stack used. The value is calculated on the basis of the | |
58 -- mechanism used by GNAT to allocate it, and it is NOT a precise value. | |
59 | |
60 Stack_Size : Natural; | |
61 -- Size of the stack | |
62 end record; | |
63 | |
64 type Result_Array_Type is array (Positive range <>) of Task_Result; | |
65 | |
66 type Stack_Analyzer is private; | |
67 -- Type of the stack analyzer tool. It is used to fill a portion of the | |
68 -- stack with Pattern, and to compute the stack used after some execution. | |
69 | |
70 -- Usage: | |
71 | |
72 -- A typical use of the package is something like: | |
73 | |
74 -- A : Stack_Analyzer; | |
75 | |
76 -- task T is | |
77 -- pragma Storage_Size (A_Storage_Size); | |
78 -- end T; | |
79 | |
80 -- [...] | |
81 | |
82 -- Bottom_Of_Stack : aliased Integer; | |
83 -- -- Bottom_Of_Stack'Address will be used as an approximation of | |
84 -- -- the bottom of stack. A good practise is to avoid allocating | |
85 -- -- other local variables on this stack, as it would degrade | |
86 -- -- the quality of this approximation. | |
87 | |
88 -- begin | |
89 -- Initialize_Analyzer (A, | |
90 -- "Task t", | |
91 -- A_Storage_Size, | |
92 -- 0, | |
93 -- A_Storage_Size - A_Guard, | |
94 -- To_Stack_Address (Bottom_Of_Stack'Address)); | |
95 -- Fill_Stack (A); | |
96 -- Some_User_Code; | |
97 -- Compute_Result (A); | |
98 -- Report_Result (A); | |
99 -- end T; | |
100 | |
101 -- Errors: | |
102 -- | |
103 -- We are instrumenting the code to measure the stack used by the user | |
104 -- code. This method has a number of systematic errors, but several methods | |
105 -- can be used to evaluate or reduce those errors. Here are those errors | |
106 -- and the strategy that we use to deal with them: | |
107 | |
108 -- Bottom offset: | |
109 | |
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 | |
112 -- pointer in this procedure is, therefore, different from the value | |
113 -- before the call to the instrumentation procedure. | |
114 | |
115 -- Strategy: The user of this package should measure the bottom of stack | |
116 -- before the call to Fill_Stack and pass it in parameter. The impact | |
117 -- is very minor unless the stack used is very small, but in this case | |
118 -- you aren't very interested by the figure. | |
119 | |
120 -- Instrumentation threshold at writing: | |
121 | |
122 -- Description: The procedure used to fill the stack with a given | |
123 -- pattern will itself have a stack frame. Therefore, it will | |
124 -- fill the stack after this stack frame. This part of the stack will | |
125 -- appear as used in the final measure. | |
126 | |
127 -- Strategy: As the user passes the value of the bottom of stack to | |
128 -- the instrumentation to deal with the bottom offset error, and as | |
129 -- the instrumentation procedure knows where the pattern filling start | |
130 -- on the stack, the difference between the two values is the minimum | |
131 -- stack usage that the method can measure. If, when the results are | |
132 -- computed, the pattern zone has been left untouched, we conclude | |
133 -- that the stack usage is inferior to this minimum stack usage. | |
134 | |
135 -- Instrumentation threshold at reading: | |
136 | |
137 -- Description: The procedure used to read the stack at the end of the | |
138 -- execution clobbers the stack by allocating its stack frame. If this | |
139 -- stack frame is bigger than the total stack used by the user code at | |
140 -- this point, it will increase the measured stack size. | |
141 | |
142 -- Strategy: We could augment this stack frame and see if it changes the | |
143 -- measure. However, this error should be negligible. | |
144 | |
145 -- Pattern zone overflow: | |
146 | |
147 -- Description: The stack grows outer than the topmost bound of the | |
148 -- pattern zone. In that case, the topmost region modified in the | |
149 -- pattern is not the maximum value of the stack pointer during the | |
150 -- execution. | |
151 | |
152 -- Strategy: At the end of the execution, the difference between the | |
153 -- topmost memory region modified in the pattern zone and the | |
154 -- topmost bound of the pattern zone can be understood as the | |
155 -- biggest allocation that the method could have detect, provided | |
156 -- that there is no "Untouched allocated zone" error and no "Pattern | |
157 -- usage in user code" error. If no object in the user code is likely | |
158 -- to have this size, this is not likely to happen. | |
159 | |
160 -- Pattern usage in user code: | |
161 | |
162 -- Description: The pattern can be found in the object of the user code. | |
163 -- Therefore, the address space where this object has been allocated | |
164 -- will appear as untouched. | |
165 | |
166 -- Strategy: Choose a pattern that is uncommon. 16#0000_0000# is the | |
167 -- worst choice; 16#DEAD_BEEF# can be a good one. A good choice is an | |
168 -- address which is not a multiple of 2, and which is not in the | |
169 -- target address space. You can also change the pattern to see if it | |
170 -- changes the measure. Note that this error *very* rarely influence | |
171 -- the measure of the total stack usage: to have some influence, the | |
172 -- pattern has to be used in the object that has been allocated on the | |
173 -- topmost address of the used stack. | |
174 | |
175 -- Stack overflow: | |
176 | |
177 -- Description: The pattern zone does not fit on the stack. This may | |
178 -- lead to an erroneous execution. | |
179 | |
180 -- Strategy: Specify a storage size that is bigger than the size of the | |
181 -- pattern. 2 times bigger should be enough. | |
182 | |
183 -- Augmentation of the user stack frames: | |
184 | |
185 -- Description: The use of instrumentation object or procedure may | |
186 -- augment the stack frame of the caller. | |
187 | |
188 -- Strategy: Do *not* inline the instrumentation procedures. Do *not* | |
189 -- allocate the Stack_Analyzer object on the stack. | |
190 | |
191 -- Untouched allocated zone: | |
192 | |
193 -- Description: The user code may allocate objects that it will never | |
194 -- touch. In that case, the pattern will not be changed. | |
195 | |
196 -- Strategy: There are no way to detect this error. Fortunately, this | |
197 -- error is really rare, and it is most probably a bug in the user | |
198 -- code, e.g. some uninitialized variable. It is (most of the time) | |
199 -- harmless: it influences the measure only if the untouched allocated | |
200 -- zone happens to be located at the topmost value of the stack | |
201 -- pointer for the whole execution. | |
202 | |
203 procedure Initialize (Buffer_Size : Natural); | |
204 pragma Export (C, Initialize, "__gnat_stack_usage_initialize"); | |
205 -- Initializes the size of the buffer that stores the results. Only the | |
206 -- first Buffer_Size results are stored. Any results that do not fit in | |
207 -- this buffer will be displayed on the fly. | |
208 | |
209 procedure Fill_Stack (Analyzer : in out Stack_Analyzer); | |
210 -- Fill an area of the stack with the pattern Analyzer.Pattern. The size | |
211 -- of this area is Analyzer.Size. After the call to this procedure, | |
212 -- the memory will look like that: | |
213 -- | |
214 -- Stack growing | |
215 -- ----------------------------------------------------------------------> | |
216 -- |<--------------------->|<----------------------------------->| | |
217 -- | Stack frames to | Memory filled with Analyzer.Pattern | | |
218 -- | Fill_Stack | | | |
219 -- ^ | ^ | |
220 -- Analyzer.Stack_Base | Analyzer.Pattern_Limit | |
221 -- ^ | |
222 -- Analyzer.Pattern_Limit +/- Analyzer.Pattern_Size | |
223 -- | |
224 | |
225 procedure Initialize_Analyzer | |
226 (Analyzer : in out Stack_Analyzer; | |
227 Task_Name : String; | |
228 Stack_Size : Natural; | |
229 Stack_Base : Stack_Address; | |
230 Pattern_Size : Natural; | |
231 Pattern : Interfaces.Unsigned_32 := 16#DEAD_BEEF#); | |
232 -- Should be called before any use of a Stack_Analyzer, to initialize it. | |
233 -- Max_Pattern_Size is the size of the pattern zone, might be smaller than | |
234 -- the full stack size Stack_Size in order to take into account e.g. the | |
235 -- secondary stack and a guard against overflow. The actual size taken | |
236 -- will be readjusted with data already used at the time the stack is | |
237 -- actually filled. | |
238 | |
239 Is_Enabled : Boolean := False; | |
240 -- When this flag is true, then stack analysis is enabled | |
241 | |
242 procedure Compute_Result (Analyzer : in out Stack_Analyzer); | |
243 -- Read the pattern zone and deduce the stack usage. It should be called | |
244 -- from the same frame as Fill_Stack. If Analyzer.Probe is not null, an | |
245 -- array of Unsigned_32 with Analyzer.Probe elements is allocated on | |
246 -- Compute_Result's stack frame. Probe can be used to detect the error: | |
247 -- "instrumentation threshold at reading". See above. After the call | |
248 -- to this procedure, the memory will look like: | |
249 -- | |
250 -- Stack growing | |
251 -- -----------------------------------------------------------------------> | |
252 -- |<---------------------->|<-------------->|<--------->|<--------->| | |
253 -- | Stack frames | Array of | used | Memory | | |
254 -- | to Compute_Result | Analyzer.Probe | during | filled | | |
255 -- | | elements | the | with | | |
256 -- | | | execution | pattern | | |
257 -- | | | | |
258 -- |<----------------------------------------------------> | | |
259 -- Stack used ^ | |
260 -- Pattern_Limit | |
261 | |
262 procedure Report_Result (Analyzer : Stack_Analyzer); | |
263 -- Store the results of the computation in memory, at the address | |
264 -- corresponding to the symbol __gnat_stack_usage_results. This is not | |
265 -- done inside Compute_Result in order to use as less stack as possible | |
266 -- within a task. | |
267 | |
268 procedure Output_Results; | |
269 -- Print the results computed so far on the standard output. Should be | |
270 -- called when all tasks are dead. | |
271 | |
272 pragma Export (C, Output_Results, "__gnat_stack_usage_output_results"); | |
273 | |
274 private | |
275 | |
276 package Unsigned_32_Addr is | |
277 new System.Address_To_Access_Conversions (Interfaces.Unsigned_32); | |
278 | |
279 subtype Pattern_Type is Interfaces.Unsigned_32; | |
280 Bytes_Per_Pattern : constant := Pattern_Type'Object_Size / Storage_Unit; | |
281 | |
282 type Stack_Analyzer is record | |
283 Task_Name : String (1 .. Task_Name_Length); | |
284 -- Name of the task | |
285 | |
286 Stack_Base : Stack_Address; | |
287 -- Address of the base of the stack, as given by the caller of | |
288 -- Initialize_Analyzer. | |
289 | |
290 Stack_Size : Natural; | |
291 -- Entire size of the analyzed stack | |
292 | |
293 Pattern_Size : Natural; | |
294 -- Size of the pattern zone | |
295 | |
296 Pattern : Pattern_Type; | |
297 -- Pattern used to recognize untouched memory | |
298 | |
299 Pattern_Limit : Stack_Address; | |
300 -- Bound of the pattern area farthest to the base | |
301 | |
302 Topmost_Touched_Mark : Stack_Address; | |
303 -- Topmost address of the pattern area whose value it is pointing | |
304 -- at has been modified during execution. If the systematic error are | |
305 -- compensated, it is the topmost value of the stack pointer during | |
306 -- the execution. | |
307 | |
308 Pattern_Overlay_Address : System.Address; | |
309 -- Address of the stack abstraction object we overlay over a | |
310 -- task's real stack, typically a pattern-initialized array. | |
311 | |
312 Result_Id : Positive; | |
313 -- Id of the result. If less than value given to gnatbind -u corresponds | |
314 -- to the location in the result array of result for the current task. | |
315 end record; | |
316 | |
317 Environment_Task_Analyzer : Stack_Analyzer; | |
318 | |
319 Compute_Environment_Task : Boolean; | |
320 | |
321 type Result_Array_Ptr is access all Result_Array_Type; | |
322 | |
323 Result_Array : Result_Array_Ptr; | |
324 pragma Export (C, Result_Array, "__gnat_stack_usage_results"); | |
325 -- Exported in order to have an easy accessible symbol in when debugging | |
326 | |
327 Next_Id : Positive := 1; | |
328 -- Id of the next stack analyzer | |
329 | |
330 function Stack_Size | |
331 (SP_Low : Stack_Address; | |
332 SP_High : Stack_Address) return Natural; | |
333 pragma Inline (Stack_Size); | |
334 -- Return the size of a portion of stack delimited by SP_High and SP_Low | |
335 -- (), i.e. the difference between SP_High and SP_Low. The storage element | |
336 -- pointed by SP_Low is not included in the size. Inlined to reduce the | |
337 -- size of the stack used by the instrumentation code. | |
338 | |
339 end System.Stack_Usage; |