1 ------------------------------------------------------------------------------
3 -- GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS --
5 -- S Y S T E M . T A S K I N G . D E B U G --
11 -- Copyright (C) 1997-2001 Free Software Foundation, Inc. --
13 -- GNARL is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNARL; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
24 -- As a special exception, if other files instantiate generics from this --
25 -- unit, or you link this unit with other files to produce an executable, --
26 -- this unit does not by itself cause the resulting executable to be --
27 -- covered by the GNU General Public License. This exception does not --
28 -- however invalidate any other reasons why the executable file might be --
29 -- covered by the GNU Public License. --
31 -- GNARL was developed by the GNARL team at Florida State University. --
32 -- Extensive contributions were provided by Ada Core Technologies Inc. --
34 ------------------------------------------------------------------------------
36 -- This package encapsulates all direct interfaces to task debugging services
37 -- that are needed by gdb with gnat mode (1.13 and higher)
39 -- Note : This file *must* be compiled with debugging information
41 -- Do not add any dependency to GNARL packages since this package is used
42 -- in both normal and resticted (ravenscar) environments.
44 with System
.Task_Info
,
45 System
.Task_Primitives
.Operations
,
48 package body System
.Tasking
.Debug
is
52 package STPO
renames System
.Task_Primitives
.Operations
;
54 type Integer_Address
is mod 2 ** Standard
'Address_Size;
55 type Integer_Address_Ptr
is access all Integer_Address
;
58 Unchecked_Conversion
(System
.Address
, Integer_Address_Ptr
);
61 Unchecked_Conversion
(Task_ID
, Integer_Address
);
63 Hex_Address_Width
: constant := (Standard
'Address_Size / 4);
65 Zero_Pos
: constant := Character'Pos ('0');
67 Hex_Digits
: constant array (0 .. Integer_Address
'(15)) of Character :=
70 subtype Buf_Range is Integer range 1 .. 80;
71 type Buf_Array is array (Buf_Range) of aliased Character;
74 Next : Buf_Range := Buf_Range'First;
75 Chars : Buf_Array := (Buf_Range => ' ');
78 type Buffer_Ptr is access all Buffer;
80 type Trace_Flag_Set is array (Character) of Boolean;
82 Trace_On : Trace_Flag_Set := ('A
' .. 'Z
' => False, others => True);
84 -----------------------
85 -- Local Subprograms --
86 -----------------------
92 -- Put TCB pointer T, (coded in hexadecimal) into Buffer
93 -- right-justified in Width characters.
99 -- Put N (coded in decimal) into Buf right-justified in Width
100 -- characters starting at Buf (Next).
105 Buffer : Buffer_Ptr);
106 -- Put string S into Buf left-justified in Width characters
107 -- starting with space in Buf (Next), truncated as necessary.
111 Buffer : Buffer_Ptr);
112 -- Put character C into Buf, left-justified, starting at Buf (Next)
114 procedure Space (Buffer : Buffer_Ptr);
115 -- Increment Next, resulting in a space
119 Buffer : Buffer_Ptr);
120 -- Increment Next by N, resulting in N spaces
122 procedure Clear (Buffer : Buffer_Ptr);
123 -- Clear Buf and reset Next to 1
125 procedure Write_Buf (Buffer : Buffer_Ptr);
126 -- Write contents of Buf (1 .. Next) to standard output
132 procedure Clear (Buffer : Buffer_Ptr) is
133 Next : Buf_Range renames Buffer.Next;
134 Buf : Buf_Array renames Buffer.Chars;
137 Buf := (Buf_Range => ' ');
145 function Image (T : ST.Task_ID) return String is
146 Buf : aliased Buffer;
147 Result : String (1 .. Hex_Address_Width + 21);
149 use type System.Task_Info.Task_Image_Type;
152 Clear (Buf'Unchecked_Access);
153 Put (T, Hex_Address_Width, Buf'Unchecked_Access);
154 Put (':', Buf'Unchecked_Access);
155 Put (Integer_Address (T.Serial_Number), 4, Buf'Unchecked_Access);
156 Space (Buf'Unchecked_Access);
158 if T.Common.Task_Image = null then
159 Put ("", 15, Buf'Unchecked_Access);
161 Put (T.Common.Task_Image.all, 15, Buf'Unchecked_Access);
164 for J in Result'Range loop
165 Result (J) := Buf.Chars (J);
175 procedure List_Tasks is
179 Print_Task_Info_Header;
184 C := C.Common.All_Tasks_Link;
188 -----------------------
189 -- Print_Accept_Info --
190 -----------------------
192 procedure Print_Accept_Info (T : ST.Task_ID) is
193 Buf : aliased Buffer;
196 if T.Open_Accepts = null then
200 Clear (Buf'Unchecked_Access);
201 Space (10, Buf'Unchecked_Access);
202 Put ("accepting:", 11, Buf'Unchecked_Access);
204 for J in T.Open_Accepts.all'Range loop
205 Put (Integer_Address (T.Open_Accepts (J).S), 3, Buf'Unchecked_Access);
208 Write_Buf (Buf'Unchecked_Access);
209 end Print_Accept_Info;
211 ------------------------
212 -- Print_Current_Task --
213 ------------------------
215 procedure Print_Current_Task is
217 Print_Task_Info (STPO.Self);
218 end Print_Current_Task;
220 ---------------------
221 -- Print_Task_Info --
222 ---------------------
224 procedure Print_Task_Info (T : ST.Task_ID) is
225 Entry_Call : Entry_Call_Link;
226 Buf : aliased Buffer;
228 use type System.Task_Info.Task_Image_Type;
231 Clear (Buf'Unchecked_Access);
232 Put (T, Hex_Address_Width, Buf'Unchecked_Access);
233 Put (':', Buf'Unchecked_Access);
234 Put (' ', Buf'Unchecked_Access);
235 Put (':', Buf'Unchecked_Access);
238 Put (" null task", 10, Buf'Unchecked_Access);
239 Write_Buf (Buf'Unchecked_Access);
243 Put (Integer_Address (T.Serial_Number), 4, Buf'Unchecked_Access);
244 Space (Buf'Unchecked_Access);
246 if T.Common.Task_Image = null then
247 Put ("", 15, Buf'Unchecked_Access);
249 Put (T.Common.Task_Image.all, 15, Buf'Unchecked_Access);
252 Space (Buf'Unchecked_Access);
253 Put (Task_States'Image (T.Common.State), 10, Buf'Unchecked_Access);
254 Space (Buf'Unchecked_Access);
257 Put ('C
', Buf'Unchecked_Access);
259 Space (Buf'Unchecked_Access);
262 if T.Open_Accepts /= null then
263 Put ('A
', Buf'Unchecked_Access);
265 Space (Buf'Unchecked_Access);
268 if T.Common.Call /= null then
269 Put ('C
', Buf'Unchecked_Access);
271 Space (Buf'Unchecked_Access);
274 if T.Terminate_Alternative then
275 Put ('T
', Buf'Unchecked_Access);
277 Space (Buf'Unchecked_Access);
281 Put ('A
', Buf'Unchecked_Access);
283 Space (Buf'Unchecked_Access);
286 if T.Deferral_Level = 0 then
287 Space (3, Buf'Unchecked_Access);
289 Put ('D
', Buf'Unchecked_Access);
290 if T.Deferral_Level < 0 then
291 Put ("<0", 2, Buf'Unchecked_Access);
292 elsif T.Deferral_Level > 1 then
293 Put (Integer_Address (T.Deferral_Level), 2, Buf'Unchecked_Access);
295 Space (2, Buf'Unchecked_Access);
299 Space (Buf'Unchecked_Access);
300 Put (Integer_Address (T.Master_of_Task), 1, Buf'Unchecked_Access);
301 Space (Buf'Unchecked_Access);
302 Put (Integer_Address (T.Master_Within), 1, Buf'Unchecked_Access);
303 Put (',', Buf'Unchecked_Access);
304 Space (Buf'Unchecked_Access);
305 Put (Integer_Address (T.Awake_Count), 1, Buf'Unchecked_Access);
306 Space (Buf'Unchecked_Access);
307 Put (Integer_Address (T.Alive_Count), 1, Buf'Unchecked_Access);
308 Put (',', Buf'Unchecked_Access);
309 Space (Buf'Unchecked_Access);
310 Put (Integer_Address (T.ATC_Nesting_Level), 1, Buf'Unchecked_Access);
311 Space (Buf'Unchecked_Access);
312 Put (Integer_Address (T.Pending_ATC_Level), 1, Buf'Unchecked_Access);
313 Put (',', Buf'Unchecked_Access);
314 Space (Buf'Unchecked_Access);
315 Put (Integer_Address (T.Common.Wait_Count), 1, Buf'Unchecked_Access);
316 Put (',', Buf'Unchecked_Access);
317 Space (Buf'Unchecked_Access);
318 Put (Integer_Address (T.User_State), 1, Buf'Unchecked_Access);
319 Write_Buf (Buf'Unchecked_Access);
321 if T.Common.Call /= null then
322 Entry_Call := T.Common.Call;
323 Clear (Buf'Unchecked_Access);
324 Space (10, Buf'Unchecked_Access);
325 Put ("serving:", 8, Buf'Unchecked_Access);
327 while Entry_Call /= null loop
329 (Entry_Call.Self.Serial_Number), 5, Buf'Unchecked_Access);
330 Entry_Call := Entry_Call.Acceptor_Prev_Call;
333 Write_Buf (Buf'Unchecked_Access);
336 Print_Accept_Info (T);
339 ----------------------------
340 -- Print_Task_Info_Header --
341 ----------------------------
343 procedure Print_Task_Info_Header is
344 Buf : aliased Buffer;
347 Clear (Buf'Unchecked_Access);
348 Put ("TASK_ID", Hex_Address_Width, Buf'Unchecked_Access);
349 Put (':', Buf'Unchecked_Access);
350 Put ('F
', Buf'Unchecked_Access);
351 Put (':', Buf'Unchecked_Access);
352 Put ("SERIAL_NUMBER", 4, Buf'Unchecked_Access);
353 Space (Buf'Unchecked_Access);
354 Put (" NAME", 15, Buf'Unchecked_Access);
355 Put (" STATE", 10, Buf'Unchecked_Access);
356 Space (11, Buf'Unchecked_Access);
357 Put ("MAST", 5, Buf'Unchecked_Access);
358 Put ("AWAK", 5, Buf'Unchecked_Access);
359 Put ("ATC", 5, Buf'Unchecked_Access);
360 Put ("WT", 3, Buf'Unchecked_Access);
361 Put ("DBG", 3, Buf'Unchecked_Access);
362 Write_Buf (Buf'Unchecked_Access);
363 end Print_Task_Info_Header;
375 X : Integer_Address := +T;
376 Next : Buf_Range renames Buffer.Next;
377 Buf : Buf_Array renames Buffer.Chars;
378 First : constant Integer := Next;
379 Wdth : Integer := Width;
382 if Wdth > Buf'Last - Next then
383 Wdth := Buf'Last - Next;
386 J := Next + (Wdth - 1);
393 Buf (J) := Hex_Digits (X rem 16);
397 -- Check for overflow
399 if J < First and then X > 0 then
411 (N : Integer_Address;
416 X : Integer_Address := N;
417 Next : Buf_Range renames Buffer.Next;
418 Buf : Buf_Array renames Buffer.Chars;
419 First : constant Integer := Next;
420 Wdth : Integer := Width;
423 if Wdth > Buf'Last - Next then
424 Wdth := Buf'Last - Next;
427 J := Next + (Wdth - 1);
434 Buf (J) := Hex_Digits (X rem 10);
438 -- Check for overflow
440 if J < First and then X > 0 then
455 Next : Buf_Range renames Buffer.Next;
456 Buf : Buf_Array renames Buffer.Chars;
457 Bound : constant Integer := Integer'Min (Next + Width, Buf'Last);
461 for K in S'Range loop
481 Next : Buf_Range renames Buffer.Next;
482 Buf : Buf_Array renames Buffer.Chars;
485 if Next >= Buf'Last then
487 else Buf (Next) := C;
492 ----------------------
493 -- Resume_All_Tasks --
494 ----------------------
496 procedure Resume_All_Tasks (Thread_Self : OS_Interface.Thread_Id) is
501 STPO.Lock_All_Tasks_List;
505 R := STPO.Resume_Task (C, Thread_Self);
506 C := C.Common.All_Tasks_Link;
509 STPO.Unlock_All_Tasks_List;
510 end Resume_All_Tasks;
516 function Self return Task_ID is
527 Value : Boolean := True)
530 Trace_On (Flag) := Value;
537 procedure Set_User_State (Value : Integer) is
539 STPO.Self.User_State := Value;
546 procedure Space (Buffer : Buffer_Ptr) is
547 Next : Buf_Range renames Buffer.Next;
548 Buf : Buf_Array renames Buffer.Chars;
551 if Next >= Buf'Last then
562 Next : Buf_Range renames Buffer.Next;
563 Buf : Buf_Array renames Buffer.Chars;
566 if Next + N > Buf'Last then
573 -----------------------
574 -- Suspend_All_Tasks --
575 -----------------------
577 procedure Suspend_All_Tasks (Thread_Self : OS_Interface.Thread_Id) is
582 STPO.Lock_All_Tasks_List;
586 R := STPO.Suspend_Task (C, Thread_Self);
587 C := C.Common.All_Tasks_Link;
590 STPO.Unlock_All_Tasks_List;
591 end Suspend_All_Tasks;
593 ------------------------
594 -- Task_Creation_Hook --
595 ------------------------
597 procedure Task_Creation_Hook (Thread : OS_Interface.Thread_Id) is
598 pragma Inspection_Point (Thread);
599 -- gdb needs to access the thread parameter in order to implement
600 -- the multitask mode under VxWorks.
604 end Task_Creation_Hook;
606 ---------------------------
607 -- Task_Termination_Hook --
608 ---------------------------
610 procedure Task_Termination_Hook is
613 end Task_Termination_Hook;
620 (Self_ID : ST.Task_ID;
622 Other_ID : ST.Task_ID;
625 Buf : aliased Buffer;
626 use type System.Task_Info.Task_Image_Type;
629 if Trace_On (Flag) then
630 Clear (Buf'Unchecked_Access);
631 Put (Self_ID, Hex_Address_Width, Buf'Unchecked_Access);
632 Put (':', Buf'Unchecked_Access);
633 Put (Flag, Buf'Unchecked_Access);
634 Put (':', Buf'Unchecked_Access);
636 (Integer_Address (Self_ID.Serial_Number),
637 4, Buf'Unchecked_Access);
638 Space (Buf'Unchecked_Access);
640 if Self_ID.Common.Task_Image = null then
641 Put ("", 15, Buf'Unchecked_Access);
643 Put (Self_ID.Common.Task_Image.all, 15, Buf'Unchecked_Access);
646 Space (Buf'Unchecked_Access);
648 if Other_ID /= null then
650 (Integer_Address (Other_ID.Serial_Number),
651 4, Buf'Unchecked_Access);
652 Space (Buf'Unchecked_Access);
655 Put (Msg, Buf.Chars'Last - Buf.Next + 1, Buf'Unchecked_Access);
656 Write_Buf (Buf'Unchecked_Access);
661 (Self_ID : ST.Task_ID;
666 Trace (Self_ID, Msg, null, Flag);
673 Self_ID : constant ST.Task_ID := STPO.Self;
676 Trace (Self_ID, Msg, null, Flag);
681 Other_ID : ST.Task_ID;
684 Self_ID : constant ST.Task_ID := STPO.Self;
687 Trace (Self_ID, Msg, null, Flag);
694 procedure Write_Buf (Buffer : Buffer_Ptr) is
695 Next : Buf_Range renames Buffer.Next;
696 Buf : Buf_Array renames Buffer.Chars;
698 procedure put_char (C : Integer);
699 pragma Import (C, put_char, "put_char");
702 for J in 1 .. Next - 1 loop
703 put_char (Character'Pos (Buf (J)));
706 put_char (Character'Pos (ASCII.LF));
709 end System.Tasking.Debug;