OSDN Git Service

Nathanael Nerode <neroden@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / ada / s-tasdeb.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                 GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS              --
4 --                                                                          --
5 --                  S Y S T E M . T A S K I N G . D E B U G                 --
6 --                                                                          --
7 --                                  B o d y                                 --
8 --                                                                          --
9 --                                                                          --
10 --          Copyright (C) 1997-2002 Free Software Foundation, Inc.          --
11 --                                                                          --
12 -- GNARL is free software; you can  redistribute it  and/or modify it under --
13 -- terms of the  GNU General Public License as published  by the Free Soft- --
14 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
15 -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
18 -- for  more details.  You should have  received  a copy of the GNU General --
19 -- Public License  distributed with GNARL; see file COPYING.  If not, write --
20 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
21 -- MA 02111-1307, USA.                                                      --
22 --                                                                          --
23 -- As a special exception,  if other files  instantiate  generics from this --
24 -- unit, or you link  this unit with other files  to produce an executable, --
25 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
26 -- covered  by the  GNU  General  Public  License.  This exception does not --
27 -- however invalidate  any other reasons why  the executable file  might be --
28 -- covered by the  GNU Public License.                                      --
29 --                                                                          --
30 -- GNARL was developed by the GNARL team at Florida State University.       --
31 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
32 --                                                                          --
33 ------------------------------------------------------------------------------
34
35 --  This package encapsulates all direct interfaces to task debugging services
36 --  that are needed by gdb with gnat mode (1.13 and higher)
37
38 --  Note : This file *must* be compiled with debugging information
39
40 --  Do not add any dependency to GNARL packages since this package is used
41 --  in both normal and restricted (ravenscar) environments.
42
43 with System.Task_Info,
44      System.Task_Primitives.Operations,
45      Unchecked_Conversion;
46
47 package body System.Tasking.Debug is
48
49    use Interfaces.C;
50
51    package STPO renames System.Task_Primitives.Operations;
52
53    type Integer_Address is mod 2 ** Standard'Address_Size;
54
55    function "+" is new
56      Unchecked_Conversion (Task_ID, Integer_Address);
57
58    Hex_Address_Width : constant := (Standard'Address_Size / 4);
59
60    Hex_Digits : constant array (0 .. Integer_Address'(15)) of Character :=
61                   "0123456789abcdef";
62
63    subtype Buf_Range is Integer range 1 .. 80;
64    type Buf_Array is array (Buf_Range) of aliased Character;
65
66    type Buffer is record
67       Next  : Buf_Range := Buf_Range'First;
68       Chars : Buf_Array := (Buf_Range => ' ');
69    end record;
70
71    type Buffer_Ptr is access all Buffer;
72
73    type Trace_Flag_Set is array (Character) of Boolean;
74
75    Trace_On : Trace_Flag_Set := ('A' .. 'Z' => False, others => True);
76
77    -----------------------
78    -- Local Subprograms --
79    -----------------------
80
81    procedure Put
82      (T      : ST.Task_ID;
83       Width  : Integer;
84       Buffer : Buffer_Ptr);
85    --  Put TCB pointer T, (coded in hexadecimal) into Buffer
86    --  right-justified in Width characters.
87
88    procedure Put
89      (N      : Integer_Address;
90       Width  : Integer;
91       Buffer : Buffer_Ptr);
92    --  Put N (coded in decimal) into Buf right-justified in Width
93    --  characters starting at Buf (Next).
94
95    procedure Put
96      (S      : String;
97       Width  : Integer;
98       Buffer : Buffer_Ptr);
99    --  Put string S into Buf left-justified in Width characters
100    --  starting with space in Buf (Next), truncated as necessary.
101
102    procedure Put
103      (C      : Character;
104       Buffer : Buffer_Ptr);
105    --  Put character C into Buf, left-justified, starting at Buf (Next)
106
107    procedure Space (Buffer : Buffer_Ptr);
108    --  Increment Next, resulting in a space
109
110    procedure Space
111      (N      : Integer;
112       Buffer : Buffer_Ptr);
113    --  Increment Next by N, resulting in N spaces
114
115    procedure Clear (Buffer : Buffer_Ptr);
116    --  Clear Buf and reset Next to 1
117
118    procedure Write_Buf (Buffer : Buffer_Ptr);
119    --  Write contents of Buf (1 .. Next) to standard output
120
121    -----------
122    -- Clear --
123    -----------
124
125    procedure Clear (Buffer : Buffer_Ptr) is
126       Next : Buf_Range renames Buffer.Next;
127       Buf  : Buf_Array renames Buffer.Chars;
128
129    begin
130       Buf := (Buf_Range => ' ');
131       Next := 1;
132    end Clear;
133
134    -----------
135    -- Image --
136    -----------
137
138    function Image (T : ST.Task_ID) return String is
139       Buf    : aliased Buffer;
140       Result : String (1 .. Hex_Address_Width + 21);
141
142       use type System.Task_Info.Task_Image_Type;
143
144    begin
145       Clear (Buf'Unchecked_Access);
146       Put (T, Hex_Address_Width, Buf'Unchecked_Access);
147       Put (':', Buf'Unchecked_Access);
148       Put (Integer_Address (T.Serial_Number), 4, Buf'Unchecked_Access);
149       Space (Buf'Unchecked_Access);
150
151       if T.Common.Task_Image = null then
152          Put ("", 15, Buf'Unchecked_Access);
153       else
154          Put (T.Common.Task_Image.all, 15, Buf'Unchecked_Access);
155       end if;
156
157       for J in Result'Range loop
158          Result (J) := Buf.Chars (J);
159       end loop;
160
161       return Result;
162    end Image;
163
164    ----------------
165    -- List_Tasks --
166    ----------------
167
168    procedure List_Tasks is
169       C : ST.Task_ID;
170
171    begin
172       Print_Task_Info_Header;
173       C := All_Tasks_List;
174
175       while C /= null loop
176          Print_Task_Info (C);
177          C := C.Common.All_Tasks_Link;
178       end loop;
179    end List_Tasks;
180
181    -----------------------
182    -- Print_Accept_Info --
183    -----------------------
184
185    procedure Print_Accept_Info (T : ST.Task_ID) is
186       Buf : aliased Buffer;
187
188    begin
189       if T.Open_Accepts = null then
190          return;
191       end if;
192
193       Clear (Buf'Unchecked_Access);
194       Space (10, Buf'Unchecked_Access);
195       Put ("accepting:", 11, Buf'Unchecked_Access);
196
197       for J in T.Open_Accepts.all'Range loop
198          Put (Integer_Address (T.Open_Accepts (J).S), 3, Buf'Unchecked_Access);
199       end loop;
200
201       Write_Buf (Buf'Unchecked_Access);
202    end Print_Accept_Info;
203
204    ------------------------
205    -- Print_Current_Task --
206    ------------------------
207
208    procedure Print_Current_Task is
209    begin
210       Print_Task_Info (STPO.Self);
211    end Print_Current_Task;
212
213    ---------------------
214    -- Print_Task_Info --
215    ---------------------
216
217    procedure Print_Task_Info (T : ST.Task_ID) is
218       Entry_Call : Entry_Call_Link;
219       Buf        : aliased Buffer;
220
221       use type System.Task_Info.Task_Image_Type;
222
223    begin
224       Clear (Buf'Unchecked_Access);
225       Put (T, Hex_Address_Width, Buf'Unchecked_Access);
226       Put (':', Buf'Unchecked_Access);
227       Put (' ', Buf'Unchecked_Access);
228       Put (':', Buf'Unchecked_Access);
229
230       if T = null then
231          Put (" null task", 10, Buf'Unchecked_Access);
232          Write_Buf (Buf'Unchecked_Access);
233          return;
234       end if;
235
236       Put (Integer_Address (T.Serial_Number), 4, Buf'Unchecked_Access);
237       Space (Buf'Unchecked_Access);
238
239       if T.Common.Task_Image = null then
240          Put ("", 15, Buf'Unchecked_Access);
241       else
242          Put (T.Common.Task_Image.all, 15, Buf'Unchecked_Access);
243       end if;
244
245       Space (Buf'Unchecked_Access);
246       Put (Task_States'Image (T.Common.State), 10, Buf'Unchecked_Access);
247       Space (Buf'Unchecked_Access);
248
249       if T.Callable then
250          Put ('C', Buf'Unchecked_Access);
251       else
252          Space (Buf'Unchecked_Access);
253       end if;
254
255       if T.Open_Accepts /= null then
256          Put ('A', Buf'Unchecked_Access);
257       else
258          Space (Buf'Unchecked_Access);
259       end if;
260
261       if T.Common.Call /= null then
262          Put ('C', Buf'Unchecked_Access);
263       else
264          Space (Buf'Unchecked_Access);
265       end if;
266
267       if T.Terminate_Alternative then
268          Put ('T', Buf'Unchecked_Access);
269       else
270          Space (Buf'Unchecked_Access);
271       end if;
272
273       if T.Aborting then
274          Put ('A', Buf'Unchecked_Access);
275       else
276          Space (Buf'Unchecked_Access);
277       end if;
278
279       if T.Deferral_Level = 0 then
280          Space (3, Buf'Unchecked_Access);
281       else
282          Put ('D', Buf'Unchecked_Access);
283          if T.Deferral_Level < 0 then
284             Put ("<0", 2, Buf'Unchecked_Access);
285          elsif T.Deferral_Level > 1 then
286             Put (Integer_Address (T.Deferral_Level), 2, Buf'Unchecked_Access);
287          else
288             Space (2, Buf'Unchecked_Access);
289          end if;
290       end if;
291
292       Space (Buf'Unchecked_Access);
293       Put (Integer_Address (T.Master_of_Task), 1, Buf'Unchecked_Access);
294       Space (Buf'Unchecked_Access);
295       Put (Integer_Address (T.Master_Within), 1, Buf'Unchecked_Access);
296       Put (',', Buf'Unchecked_Access);
297       Space (Buf'Unchecked_Access);
298       Put (Integer_Address (T.Awake_Count), 1, Buf'Unchecked_Access);
299       Space (Buf'Unchecked_Access);
300       Put (Integer_Address (T.Alive_Count), 1, Buf'Unchecked_Access);
301       Put (',', Buf'Unchecked_Access);
302       Space (Buf'Unchecked_Access);
303       Put (Integer_Address (T.ATC_Nesting_Level), 1, Buf'Unchecked_Access);
304       Space (Buf'Unchecked_Access);
305       Put (Integer_Address (T.Pending_ATC_Level), 1, Buf'Unchecked_Access);
306       Put (',', Buf'Unchecked_Access);
307       Space (Buf'Unchecked_Access);
308       Put (Integer_Address (T.Common.Wait_Count), 1, Buf'Unchecked_Access);
309       Put (',', Buf'Unchecked_Access);
310       Space (Buf'Unchecked_Access);
311       Put (Integer_Address (T.User_State), 1, Buf'Unchecked_Access);
312       Write_Buf (Buf'Unchecked_Access);
313
314       if T.Common.Call /= null then
315          Entry_Call := T.Common.Call;
316          Clear (Buf'Unchecked_Access);
317          Space (10, Buf'Unchecked_Access);
318          Put ("serving:", 8, Buf'Unchecked_Access);
319
320          while Entry_Call /= null loop
321             Put (Integer_Address
322               (Entry_Call.Self.Serial_Number), 5, Buf'Unchecked_Access);
323             Entry_Call := Entry_Call.Acceptor_Prev_Call;
324          end loop;
325
326          Write_Buf (Buf'Unchecked_Access);
327       end if;
328
329       Print_Accept_Info (T);
330    end Print_Task_Info;
331
332    ----------------------------
333    -- Print_Task_Info_Header --
334    ----------------------------
335
336    procedure Print_Task_Info_Header is
337       Buf : aliased Buffer;
338
339    begin
340       Clear (Buf'Unchecked_Access);
341       Put ("TASK_ID", Hex_Address_Width, Buf'Unchecked_Access);
342       Put (':', Buf'Unchecked_Access);
343       Put ('F', Buf'Unchecked_Access);
344       Put (':', Buf'Unchecked_Access);
345       Put ("SERIAL_NUMBER", 4, Buf'Unchecked_Access);
346       Space (Buf'Unchecked_Access);
347       Put (" NAME", 15, Buf'Unchecked_Access);
348       Put (" STATE", 10, Buf'Unchecked_Access);
349       Space (11, Buf'Unchecked_Access);
350       Put ("MAST", 5, Buf'Unchecked_Access);
351       Put ("AWAK", 5, Buf'Unchecked_Access);
352       Put ("ATC", 5, Buf'Unchecked_Access);
353       Put ("WT", 3, Buf'Unchecked_Access);
354       Put ("DBG", 3, Buf'Unchecked_Access);
355       Write_Buf (Buf'Unchecked_Access);
356    end Print_Task_Info_Header;
357
358    ---------
359    -- Put --
360    ---------
361
362    procedure Put
363      (T      : ST.Task_ID;
364       Width  : Integer;
365       Buffer : Buffer_Ptr)
366    is
367       J     : Integer;
368       X     : Integer_Address := +T;
369       Next  : Buf_Range renames Buffer.Next;
370       Buf   : Buf_Array renames Buffer.Chars;
371       First : constant Integer := Next;
372       Wdth  : Integer := Width;
373
374    begin
375       if Wdth > Buf'Last - Next then
376          Wdth := Buf'Last - Next;
377       end if;
378
379       J := Next + (Wdth - 1);
380
381       if X = 0 then
382          Buf (J) := '0';
383
384       else
385          while X > 0 loop
386             Buf (J) := Hex_Digits (X rem 16);
387             J := J - 1;
388             X := X / 16;
389
390             --  Check for overflow
391
392             if J < First and then X > 0 then
393                Buf (J + 1) := '*';
394                exit;
395             end if;
396
397          end loop;
398       end if;
399
400       Next := Next + Wdth;
401    end Put;
402
403    procedure Put
404      (N      : Integer_Address;
405       Width  : Integer;
406       Buffer : Buffer_Ptr)
407    is
408       J     : Integer;
409       X     : Integer_Address := N;
410       Next  : Buf_Range renames Buffer.Next;
411       Buf   : Buf_Array renames Buffer.Chars;
412       First : constant Integer := Next;
413       Wdth  : Integer := Width;
414
415    begin
416       if Wdth > Buf'Last - Next then
417          Wdth := Buf'Last - Next;
418       end if;
419
420       J := Next + (Wdth - 1);
421
422       if N = 0 then
423          Buf (J) := '0';
424
425       else
426          while X > 0 loop
427             Buf (J) := Hex_Digits (X rem 10);
428             J := J - 1;
429             X := X / 10;
430
431             --  Check for overflow
432
433             if J < First and then X > 0 then
434                Buf (J + 1) := '*';
435                exit;
436             end if;
437          end loop;
438       end if;
439
440       Next := Next + Wdth;
441    end Put;
442
443    procedure Put
444      (S      : String;
445       Width  : Integer;
446       Buffer : Buffer_Ptr)
447    is
448       Next  : Buf_Range renames Buffer.Next;
449       Buf   : Buf_Array renames Buffer.Chars;
450       Bound : constant Integer := Integer'Min (Next + Width, Buf'Last);
451       J     : Integer := Next;
452
453    begin
454       for K in S'Range loop
455
456          --  Check overflow
457
458          if J >= Bound then
459             Buf (J - 1) := '*';
460             exit;
461          end if;
462
463          Buf (J) := S (K);
464          J := J + 1;
465       end loop;
466
467       Next := Bound;
468    end Put;
469
470    procedure Put
471      (C      : Character;
472       Buffer : Buffer_Ptr)
473    is
474       Next : Buf_Range renames Buffer.Next;
475       Buf  : Buf_Array renames Buffer.Chars;
476
477    begin
478       if Next >= Buf'Last then
479          Buf (Next) := '*';
480       else Buf (Next) := C;
481          Next := Next + 1;
482       end if;
483    end Put;
484
485    ----------------------
486    -- Resume_All_Tasks --
487    ----------------------
488
489    procedure Resume_All_Tasks (Thread_Self : OS_Interface.Thread_Id) is
490       C : ST.Task_ID;
491       R : Boolean;
492
493    begin
494       STPO.Lock_RTS;
495       C := All_Tasks_List;
496
497       while C /= null loop
498          R := STPO.Resume_Task (C, Thread_Self);
499          C := C.Common.All_Tasks_Link;
500       end loop;
501
502       STPO.Unlock_RTS;
503    end Resume_All_Tasks;
504
505    ----------
506    -- Self --
507    ----------
508
509    function Self return Task_ID is
510    begin
511       return STPO.Self;
512    end Self;
513
514    ---------------
515    -- Set_Trace --
516    ---------------
517
518    procedure Set_Trace
519      (Flag  : Character;
520       Value : Boolean := True)
521    is
522    begin
523       Trace_On (Flag) := Value;
524    end Set_Trace;
525
526    --------------------
527    -- Set_User_State --
528    --------------------
529
530    procedure Set_User_State (Value : Integer) is
531    begin
532       STPO.Self.User_State := Value;
533    end Set_User_State;
534
535    -----------
536    -- Space --
537    -----------
538
539    procedure Space (Buffer : Buffer_Ptr) is
540       Next : Buf_Range renames Buffer.Next;
541       Buf  : Buf_Array renames Buffer.Chars;
542
543    begin
544       if Next >= Buf'Last then
545          Buf (Next) := '*';
546       else
547          Next := Next + 1;
548       end if;
549    end Space;
550
551    procedure Space
552      (N      : Integer;
553       Buffer : Buffer_Ptr)
554    is
555       Next : Buf_Range renames Buffer.Next;
556       Buf  : Buf_Array renames Buffer.Chars;
557
558    begin
559       if Next + N > Buf'Last then
560          Buf (Next) := '*';
561       else
562          Next := Next + N;
563       end if;
564    end Space;
565
566    -----------------------
567    -- Suspend_All_Tasks --
568    -----------------------
569
570    procedure Suspend_All_Tasks (Thread_Self : OS_Interface.Thread_Id) is
571       C : ST.Task_ID;
572       R : Boolean;
573
574    begin
575       STPO.Lock_RTS;
576       C := All_Tasks_List;
577
578       while C /= null loop
579          R := STPO.Suspend_Task (C, Thread_Self);
580          C := C.Common.All_Tasks_Link;
581       end loop;
582
583       STPO.Unlock_RTS;
584    end Suspend_All_Tasks;
585
586    ------------------------
587    -- Task_Creation_Hook --
588    ------------------------
589
590    procedure Task_Creation_Hook (Thread : OS_Interface.Thread_Id) is
591       pragma Inspection_Point (Thread);
592       --  gdb needs to access the thread parameter in order to implement
593       --  the multitask mode under VxWorks.
594
595    begin
596       null;
597    end Task_Creation_Hook;
598
599    ---------------------------
600    -- Task_Termination_Hook --
601    ---------------------------
602
603    procedure Task_Termination_Hook is
604    begin
605       null;
606    end Task_Termination_Hook;
607
608    -----------
609    -- Trace --
610    -----------
611
612    procedure Trace
613      (Self_ID  : ST.Task_ID;
614       Msg      : String;
615       Other_ID : ST.Task_ID;
616       Flag     : Character)
617    is
618       Buf : aliased Buffer;
619       use type System.Task_Info.Task_Image_Type;
620
621    begin
622       if Trace_On (Flag) then
623          Clear (Buf'Unchecked_Access);
624          Put (Self_ID, Hex_Address_Width, Buf'Unchecked_Access);
625          Put (':', Buf'Unchecked_Access);
626          Put (Flag, Buf'Unchecked_Access);
627          Put (':', Buf'Unchecked_Access);
628          Put
629            (Integer_Address (Self_ID.Serial_Number),
630             4, Buf'Unchecked_Access);
631          Space (Buf'Unchecked_Access);
632
633          if Self_ID.Common.Task_Image = null then
634             Put ("", 15, Buf'Unchecked_Access);
635          else
636             Put (Self_ID.Common.Task_Image.all, 15, Buf'Unchecked_Access);
637          end if;
638
639          Space (Buf'Unchecked_Access);
640
641          if Other_ID /= null then
642             Put
643               (Integer_Address (Other_ID.Serial_Number),
644                4, Buf'Unchecked_Access);
645             Space (Buf'Unchecked_Access);
646          end if;
647
648          Put (Msg, Buf.Chars'Last - Buf.Next + 1, Buf'Unchecked_Access);
649          Write_Buf (Buf'Unchecked_Access);
650       end if;
651    end Trace;
652
653    procedure Trace
654      (Self_ID : ST.Task_ID;
655       Msg     : String;
656       Flag    : Character)
657    is
658    begin
659       Trace (Self_ID, Msg, null, Flag);
660    end Trace;
661
662    procedure Trace
663      (Msg : String;
664       Flag : Character)
665    is
666       Self_ID : constant ST.Task_ID := STPO.Self;
667
668    begin
669       Trace (Self_ID, Msg, null, Flag);
670    end Trace;
671
672    procedure Trace
673      (Msg      : String;
674       Other_ID : ST.Task_ID;
675       Flag     : Character)
676    is
677       pragma Warnings (Off, Other_ID);
678
679       Self_ID : constant ST.Task_ID := STPO.Self;
680
681    begin
682       Trace (Self_ID, Msg, null, Flag);
683    end Trace;
684
685    ---------------
686    -- Write_Buf --
687    ---------------
688
689    procedure Write_Buf (Buffer : Buffer_Ptr) is
690       Next : Buf_Range renames Buffer.Next;
691       Buf  : Buf_Array renames Buffer.Chars;
692
693       procedure put_char (C : Integer);
694       pragma Import (C, put_char, "put_char");
695
696    begin
697       for J in 1 .. Next - 1 loop
698          put_char (Character'Pos (Buf (J)));
699       end loop;
700
701       put_char (Character'Pos (ASCII.LF));
702    end Write_Buf;
703
704 end System.Tasking.Debug;