1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
5 -- S Y S T E M . S T A C K _ U S A G E . T A S K I N G --
9 -- Copyright (C) 2009-2023, Free Software Foundation, Inc. --
11 -- GNAT 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. --
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. --
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/>. --
27 -- GNARL was developed by the GNARL team at Florida State University. --
28 -- Extensive contributions were provided by Ada Core Technologies, Inc. --
30 ------------------------------------------------------------------------------
32 -- This is why this package is part of GNARL:
34 with System
.Tasking
.Debug
;
35 with System
.Task_Primitives
.Operations
;
39 package body System
.Stack_Usage
.Tasking
is
42 procedure Report_For_Task
(Id
: System
.Tasking
.Task_Id
);
43 -- A generic procedure calculating stack usage for a given task
45 procedure Compute_All_Tasks
;
46 -- Compute the stack usage for all tasks and saves it in
47 -- System.Stack_Usage.Result_Array
49 procedure Compute_Current_Task
;
50 -- Compute the stack usage for a given task and saves it in the precise
51 -- slot in System.Stack_Usage.Result_Array;
53 procedure Report_Impl
(All_Tasks
: Boolean; Do_Print
: Boolean);
54 -- Report the stack usage of either all tasks (All_Tasks = True) or of the
55 -- current task (All_Task = False). If Print is True, then results are
59 (TS
: System
.Stack_Usage
.Task_Result
;
60 Res
: out Stack_Usage_Result
);
61 -- Convert an object of type System.Stack_Usage in a Stack_Usage_Result
68 (TS
: System
.Stack_Usage
.Task_Result
;
69 Res
: out Stack_Usage_Result
) is
78 procedure Report_For_Task
(Id
: System
.Tasking
.Task_Id
) is
80 System
.Stack_Usage
.Compute_Result
(Id
.Common
.Analyzer
);
81 System
.Stack_Usage
.Report_Result
(Id
.Common
.Analyzer
);
84 -----------------------
85 -- Compute_All_Tasks --
86 -----------------------
88 procedure Compute_All_Tasks
is
89 Id
: System
.Tasking
.Task_Id
;
90 use type System
.Tasking
.Task_Id
;
92 if not System
.Stack_Usage
.Is_Enabled
then
93 Put_Line
("Stack Usage not enabled: bind with -uNNN switch");
96 -- Loop over all tasks
98 for J
in System
.Tasking
.Debug
.Known_Tasks
'First + 1
99 .. System
.Tasking
.Debug
.Known_Tasks
'Last
101 Id
:= System
.Tasking
.Debug
.Known_Tasks
(J
);
104 -- Calculate the task usage for a given task
106 Report_For_Task
(Id
);
110 end Compute_All_Tasks
;
112 --------------------------
113 -- Compute_Current_Task --
114 --------------------------
116 procedure Compute_Current_Task
is
118 if not System
.Stack_Usage
.Is_Enabled
then
119 Put_Line
("Stack Usage not enabled: bind with -uNNN switch");
124 Report_For_Task
(System
.Tasking
.Self
);
127 end Compute_Current_Task
;
133 procedure Report_Impl
(All_Tasks
: Boolean; Do_Print
: Boolean) is
138 System
.Task_Primitives
.Operations
.Lock_RTS
;
145 Compute_Current_Task
;
150 System
.Stack_Usage
.Output_Results
;
153 -- Unlock the runtime
155 System
.Task_Primitives
.Operations
.Unlock_RTS
;
159 ----------------------
160 -- Report_All_Tasks --
161 ----------------------
163 procedure Report_All_Tasks
is
165 Report_Impl
(True, True);
166 end Report_All_Tasks
;
168 -------------------------
169 -- Report_Current_Task --
170 -------------------------
172 procedure Report_Current_Task
is
173 Res
: Stack_Usage_Result
;
175 Res
:= Get_Current_Task_Usage
;
177 end Report_Current_Task
;
179 -------------------------
180 -- Get_All_Tasks_Usage --
181 -------------------------
183 function Get_All_Tasks_Usage
return Stack_Usage_Result_Array
is
184 Res
: Stack_Usage_Result_Array
185 (1 .. System
.Stack_Usage
.Result_Array
'Length);
187 Report_Impl
(True, False);
189 for J
in Res
'Range loop
190 Convert
(System
.Stack_Usage
.Result_Array
(J
), Res
(J
));
194 end Get_All_Tasks_Usage
;
196 ----------------------------
197 -- Get_Current_Task_Usage --
198 ----------------------------
200 function Get_Current_Task_Usage
return Stack_Usage_Result
is
201 Res
: Stack_Usage_Result
;
202 Original
: System
.Stack_Usage
.Task_Result
;
203 Found
: Boolean := False;
206 Report_Impl
(False, False);
208 -- Look for the task info in System.Stack_Usage.Result_Array;
209 -- the search is based on task name
211 for T
in System
.Stack_Usage
.Result_Array
'Range loop
212 if System
.Stack_Usage
.Result_Array
(T
).Task_Name
=
213 System
.Tasking
.Self
.Common
.Analyzer
.Task_Name
215 Original
:= System
.Stack_Usage
.Result_Array
(T
);
221 -- Be sure a task has been found
223 pragma Assert
(Found
);
225 Convert
(Original
, Res
);
227 end Get_Current_Task_Usage
;
233 procedure Print
(Obj
: Stack_Usage_Result
) is
234 Pos
: Positive := Obj
.Task_Name
'Last;
237 -- Simply trim the string containing the task name
239 for S
in Obj
.Task_Name
'Range loop
240 if Obj
.Task_Name
(S
) = ' ' then
247 T_Name
: constant String :=
248 Obj
.Task_Name
(Obj
.Task_Name
'First .. Pos
);
251 ("| " & T_Name
& " | " & Natural'Image (Obj
.Stack_Size
) &
252 Natural'Image (Obj
.Value
));
256 end System
.Stack_Usage
.Tasking
;