OSDN Git Service

Minor reformatting.
[pf3gnuchains/gcc-fork.git] / gcc / ada / s-tassta.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                 GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                 --
4 --                                                                          --
5 --                 S Y S T E M . T A S K I N G . S T A G E S                --
6 --                                                                          --
7 --                                  B o d y                                 --
8 --                                                                          --
9 --         Copyright (C) 1992-2009, 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 pragma Polling (Off);
33 --  Turn off polling, we do not want ATC polling to take place during tasking
34 --  operations. It causes infinite loops and other problems.
35
36 with Ada.Exceptions;
37 with Ada.Unchecked_Deallocation;
38
39 with System.Tasking.Debug;
40 with System.Address_Image;
41 with System.Task_Primitives;
42 with System.Task_Primitives.Operations;
43 with System.Tasking.Utilities;
44 with System.Tasking.Queuing;
45 with System.Tasking.Rendezvous;
46 with System.OS_Primitives;
47 with System.Secondary_Stack;
48 with System.Storage_Elements;
49 with System.Restrictions;
50 with System.Standard_Library;
51 with System.Traces.Tasking;
52 with System.Stack_Usage;
53
54 with System.Soft_Links;
55 --  These are procedure pointers to non-tasking routines that use task
56 --  specific data. In the absence of tasking, these routines refer to global
57 --  data. In the presence of tasking, they must be replaced with pointers to
58 --  task-specific versions. Also used for Create_TSD, Destroy_TSD,
59 --  Get_Current_Excep, Finalize_Global_List, Task_Termination, Handler.
60
61 with System.Tasking.Initialization;
62 pragma Elaborate_All (System.Tasking.Initialization);
63 --  This insures that tasking is initialized if any tasks are created
64
65 package body System.Tasking.Stages is
66
67    package STPO renames System.Task_Primitives.Operations;
68    package SSL  renames System.Soft_Links;
69    package SSE  renames System.Storage_Elements;
70    package SST  renames System.Secondary_Stack;
71
72    use Ada.Exceptions;
73
74    use Parameters;
75    use Task_Primitives;
76    use Task_Primitives.Operations;
77    use Task_Info;
78
79    use System.Traces;
80    use System.Traces.Tasking;
81
82    -----------------------
83    -- Local Subprograms --
84    -----------------------
85
86    procedure Free is new
87      Ada.Unchecked_Deallocation (Ada_Task_Control_Block, Task_Id);
88
89    procedure Free_Entry_Names (T : Task_Id);
90    --  Deallocate all string names associated with task entries
91
92    procedure Trace_Unhandled_Exception_In_Task (Self_Id : Task_Id);
93    --  This procedure outputs the task specific message for exception
94    --  tracing purposes.
95
96    procedure Task_Wrapper (Self_ID : Task_Id);
97    pragma Convention (C, Task_Wrapper);
98    --  This is the procedure that is called by the GNULL from the new context
99    --  when a task is created. It waits for activation and then calls the task
100    --  body procedure. When the task body procedure completes, it terminates
101    --  the task.
102    --
103    --  The Task_Wrapper's address will be provided to the underlying threads
104    --  library as the task entry point. Convention C is what makes most sense
105    --  for that purpose (Export C would make the function globally visible,
106    --  and affect the link name on which GDB depends). This will in addition
107    --  trigger an automatic stack alignment suitable for GCC's assumptions if
108    --  need be.
109
110    --  "Vulnerable_..." in the procedure names below means they must be called
111    --  with abort deferred.
112
113    procedure Vulnerable_Complete_Task (Self_ID : Task_Id);
114    --  Complete the calling task. This procedure must be called with
115    --  abort deferred. It should only be called by Complete_Task and
116    --  Finalize_Global_Tasks (for the environment task).
117
118    procedure Vulnerable_Complete_Master (Self_ID : Task_Id);
119    --  Complete the current master of the calling task. This procedure
120    --  must be called with abort deferred. It should only be called by
121    --  Vulnerable_Complete_Task and Complete_Master.
122
123    procedure Vulnerable_Complete_Activation (Self_ID : Task_Id);
124    --  Signal to Self_ID's activator that Self_ID has completed activation.
125    --  This procedure must be called with abort deferred.
126
127    procedure Abort_Dependents (Self_ID : Task_Id);
128    --  Abort all the direct dependents of Self at its current master nesting
129    --  level, plus all of their dependents, transitively. RTS_Lock should be
130    --  locked by the caller.
131
132    procedure Vulnerable_Free_Task (T : Task_Id);
133    --  Recover all runtime system storage associated with the task T. This
134    --  should only be called after T has terminated and will no longer be
135    --  referenced.
136    --
137    --  For tasks created by an allocator that fails, due to an exception, it is
138    --  called from Expunge_Unactivated_Tasks.
139    --
140    --  Different code is used at master completion, in Terminate_Dependents,
141    --  due to a need for tighter synchronization with the master.
142
143    ----------------------
144    -- Abort_Dependents --
145    ----------------------
146
147    procedure Abort_Dependents (Self_ID : Task_Id) is
148       C : Task_Id;
149       P : Task_Id;
150
151    begin
152       C := All_Tasks_List;
153       while C /= null loop
154          P := C.Common.Parent;
155          while P /= null loop
156             if P = Self_ID then
157
158                --  ??? C is supposed to take care of its own dependents, so
159                --  there should be no need to worry about them. Need to double
160                --  check this.
161
162                if C.Master_of_Task = Self_ID.Master_Within then
163                   Utilities.Abort_One_Task (Self_ID, C);
164                   C.Dependents_Aborted := True;
165                end if;
166
167                exit;
168             end if;
169
170             P := P.Common.Parent;
171          end loop;
172
173          C := C.Common.All_Tasks_Link;
174       end loop;
175
176       Self_ID.Dependents_Aborted := True;
177    end Abort_Dependents;
178
179    -----------------
180    -- Abort_Tasks --
181    -----------------
182
183    procedure Abort_Tasks (Tasks : Task_List) is
184    begin
185       Utilities.Abort_Tasks (Tasks);
186    end Abort_Tasks;
187
188    --------------------
189    -- Activate_Tasks --
190    --------------------
191
192    --  Note that locks of activator and activated task are both locked here.
193    --  This is necessary because C.Common.State and Self.Common.Wait_Count have
194    --  to be synchronized. This is safe from deadlock because the activator is
195    --  always created before the activated task. That satisfies our
196    --  in-order-of-creation ATCB locking policy.
197
198    --  At one point, we may also lock the parent, if the parent is different
199    --  from the activator. That is also consistent with the lock ordering
200    --  policy, since the activator cannot be created before the parent.
201
202    --  Since we are holding both the activator's lock, and Task_Wrapper locks
203    --  that before it does anything more than initialize the low-level ATCB
204    --  components, it should be safe to wait to update the counts until we see
205    --  that the thread creation is successful.
206
207    --  If the thread creation fails, we do need to close the entries of the
208    --  task. The first phase, of dequeuing calls, only requires locking the
209    --  acceptor's ATCB, but the waking up of the callers requires locking the
210    --  caller's ATCB. We cannot safely do this while we are holding other
211    --  locks. Therefore, the queue-clearing operation is done in a separate
212    --  pass over the activation chain.
213
214    procedure Activate_Tasks (Chain_Access : Activation_Chain_Access) is
215       Self_ID        : constant Task_Id := STPO.Self;
216       P              : Task_Id;
217       C              : Task_Id;
218       Next_C, Last_C : Task_Id;
219       Activate_Prio  : System.Any_Priority;
220       Success        : Boolean;
221       All_Elaborated : Boolean := True;
222
223    begin
224       --  If pragma Detect_Blocking is active, then we must check whether this
225       --  potentially blocking operation is called from a protected action.
226
227       if System.Tasking.Detect_Blocking
228         and then Self_ID.Common.Protected_Action_Nesting > 0
229       then
230          raise Program_Error with "potentially blocking operation";
231       end if;
232
233       pragma Debug
234         (Debug.Trace (Self_ID, "Activate_Tasks", 'C'));
235
236       Initialization.Defer_Abort_Nestable (Self_ID);
237
238       pragma Assert (Self_ID.Common.Wait_Count = 0);
239
240       --  Lock RTS_Lock, to prevent activated tasks from racing ahead before
241       --  we finish activating the chain.
242
243       Lock_RTS;
244
245       --  Check that all task bodies have been elaborated
246
247       C := Chain_Access.T_ID;
248       Last_C := null;
249       while C /= null loop
250          if C.Common.Elaborated /= null
251            and then not C.Common.Elaborated.all
252          then
253             All_Elaborated := False;
254          end if;
255
256          --  Reverse the activation chain so that tasks are activated in the
257          --  same order they're declared.
258
259          Next_C := C.Common.Activation_Link;
260          C.Common.Activation_Link := Last_C;
261          Last_C := C;
262          C := Next_C;
263       end loop;
264
265       Chain_Access.T_ID := Last_C;
266
267       if not All_Elaborated then
268          Unlock_RTS;
269          Initialization.Undefer_Abort_Nestable (Self_ID);
270          raise Program_Error with "Some tasks have not been elaborated";
271       end if;
272
273       --  Activate all the tasks in the chain. Creation of the thread of
274       --  control was deferred until activation. So create it now.
275
276       C := Chain_Access.T_ID;
277       while C /= null loop
278          if C.Common.State /= Terminated then
279             pragma Assert (C.Common.State = Unactivated);
280
281             P := C.Common.Parent;
282             Write_Lock (P);
283             Write_Lock (C);
284
285             Activate_Prio :=
286               (if C.Common.Base_Priority < Get_Priority (Self_ID)
287                then Get_Priority (Self_ID)
288                else C.Common.Base_Priority);
289
290             System.Task_Primitives.Operations.Create_Task
291               (C, Task_Wrapper'Address,
292                Parameters.Size_Type
293                  (C.Common.Compiler_Data.Pri_Stack_Info.Size),
294                Activate_Prio, Success);
295
296             --  There would be a race between the created task and the creator
297             --  to do the following initialization, if we did not have a
298             --  Lock/Unlock_RTS pair in the task wrapper to prevent it from
299             --  racing ahead.
300
301             if Success then
302                C.Common.State := Activating;
303                C.Awake_Count := 1;
304                C.Alive_Count := 1;
305                P.Awake_Count := P.Awake_Count + 1;
306                P.Alive_Count := P.Alive_Count + 1;
307
308                if P.Common.State = Master_Completion_Sleep and then
309                  C.Master_of_Task = P.Master_Within
310                then
311                   pragma Assert (Self_ID /= P);
312                   P.Common.Wait_Count := P.Common.Wait_Count + 1;
313                end if;
314
315                for J in System.Tasking.Debug.Known_Tasks'Range loop
316                   if System.Tasking.Debug.Known_Tasks (J) = null then
317                      System.Tasking.Debug.Known_Tasks (J) := C;
318                      C.Known_Tasks_Index := J;
319                      exit;
320                   end if;
321                end loop;
322
323                if Global_Task_Debug_Event_Set then
324                   Debug.Signal_Debug_Event
325                    (Debug.Debug_Event_Activating, C);
326                end if;
327
328                C.Common.State := Runnable;
329
330                Unlock (C);
331                Unlock (P);
332
333             else
334                --  No need to set Awake_Count, State, etc. here since the loop
335                --  below will do that for any Unactivated tasks.
336
337                Unlock (C);
338                Unlock (P);
339                Self_ID.Common.Activation_Failed := True;
340             end if;
341          end if;
342
343          C := C.Common.Activation_Link;
344       end loop;
345
346       if not Single_Lock then
347          Unlock_RTS;
348       end if;
349
350       --  Close the entries of any tasks that failed thread creation, and count
351       --  those that have not finished activation.
352
353       Write_Lock (Self_ID);
354       Self_ID.Common.State := Activator_Sleep;
355
356       C := Chain_Access.T_ID;
357       while C /= null loop
358          Write_Lock (C);
359
360          if C.Common.State = Unactivated then
361             C.Common.Activator := null;
362             C.Common.State := Terminated;
363             C.Callable := False;
364             Utilities.Cancel_Queued_Entry_Calls (C);
365
366          elsif C.Common.Activator /= null then
367             Self_ID.Common.Wait_Count := Self_ID.Common.Wait_Count + 1;
368          end if;
369
370          Unlock (C);
371          P := C.Common.Activation_Link;
372          C.Common.Activation_Link := null;
373          C := P;
374       end loop;
375
376       --  Wait for the activated tasks to complete activation. It is
377       --  unsafe to abort any of these tasks until the count goes to zero.
378
379       loop
380          exit when Self_ID.Common.Wait_Count = 0;
381          Sleep (Self_ID, Activator_Sleep);
382       end loop;
383
384       Self_ID.Common.State := Runnable;
385       Unlock (Self_ID);
386
387       if Single_Lock then
388          Unlock_RTS;
389       end if;
390
391       --  Remove the tasks from the chain
392
393       Chain_Access.T_ID := null;
394       Initialization.Undefer_Abort_Nestable (Self_ID);
395
396       if Self_ID.Common.Activation_Failed then
397          Self_ID.Common.Activation_Failed := False;
398          raise Tasking_Error with "Failure during activation";
399       end if;
400    end Activate_Tasks;
401
402    -------------------------
403    -- Complete_Activation --
404    -------------------------
405
406    procedure Complete_Activation is
407       Self_ID : constant Task_Id := STPO.Self;
408
409    begin
410       Initialization.Defer_Abort_Nestable (Self_ID);
411
412       if Single_Lock then
413          Lock_RTS;
414       end if;
415
416       Vulnerable_Complete_Activation (Self_ID);
417
418       if Single_Lock then
419          Unlock_RTS;
420       end if;
421
422       Initialization.Undefer_Abort_Nestable (Self_ID);
423
424       --  ??? Why do we need to allow for nested deferral here?
425
426       if Runtime_Traces then
427          Send_Trace_Info (T_Activate);
428       end if;
429    end Complete_Activation;
430
431    ---------------------
432    -- Complete_Master --
433    ---------------------
434
435    procedure Complete_Master is
436       Self_ID : constant Task_Id := STPO.Self;
437    begin
438       pragma Assert
439         (Self_ID.Deferral_Level > 0
440           or else not System.Restrictions.Abort_Allowed);
441       Vulnerable_Complete_Master (Self_ID);
442    end Complete_Master;
443
444    -------------------
445    -- Complete_Task --
446    -------------------
447
448    --  See comments on Vulnerable_Complete_Task for details
449
450    procedure Complete_Task is
451       Self_ID  : constant Task_Id := STPO.Self;
452
453    begin
454       pragma Assert
455         (Self_ID.Deferral_Level > 0
456           or else not System.Restrictions.Abort_Allowed);
457
458       Vulnerable_Complete_Task (Self_ID);
459
460       --  All of our dependents have terminated. Never undefer abort again!
461
462    end Complete_Task;
463
464    -----------------
465    -- Create_Task --
466    -----------------
467
468    --  Compiler interface only. Do not call from within the RTS. This must be
469    --  called to create a new task.
470
471    procedure Create_Task
472      (Priority          : Integer;
473       Size              : System.Parameters.Size_Type;
474       Task_Info         : System.Task_Info.Task_Info_Type;
475       Relative_Deadline : Ada.Real_Time.Time_Span;
476       Num_Entries       : Task_Entry_Index;
477       Master            : Master_Level;
478       State             : Task_Procedure_Access;
479       Discriminants     : System.Address;
480       Elaborated        : Access_Boolean;
481       Chain             : in out Activation_Chain;
482       Task_Image        : String;
483       Created_Task      : out Task_Id;
484       Build_Entry_Names : Boolean)
485    is
486       T, P          : Task_Id;
487       Self_ID       : constant Task_Id := STPO.Self;
488       Success       : Boolean;
489       Base_Priority : System.Any_Priority;
490       Len           : Natural;
491
492       pragma Unreferenced (Relative_Deadline);
493       --  EDF scheduling is not supported by any of the target platforms so
494       --  this parameter is not passed any further.
495
496    begin
497       --  If Master is greater than the current master, it means that Master
498       --  has already awaited its dependent tasks. This raises Program_Error,
499       --  by 4.8(10.3/2). See AI-280. Ignore this check for foreign threads.
500
501       if Self_ID.Master_of_Task /= Foreign_Task_Level
502         and then Master > Self_ID.Master_Within
503       then
504          raise Program_Error with
505            "create task after awaiting termination";
506       end if;
507
508       --  If pragma Detect_Blocking is active must be checked whether this
509       --  potentially blocking operation is called from a protected action.
510
511       if System.Tasking.Detect_Blocking
512         and then Self_ID.Common.Protected_Action_Nesting > 0
513       then
514          raise Program_Error with "potentially blocking operation";
515       end if;
516
517       pragma Debug (Debug.Trace (Self_ID, "Create_Task", 'C'));
518
519       Base_Priority :=
520         (if Priority = Unspecified_Priority
521          then Self_ID.Common.Base_Priority
522          else System.Any_Priority (Priority));
523
524       --  Find parent P of new Task, via master level number
525
526       P := Self_ID;
527
528       if P /= null then
529          while P.Master_of_Task >= Master loop
530             P := P.Common.Parent;
531             exit when P = null;
532          end loop;
533       end if;
534
535       Initialization.Defer_Abort_Nestable (Self_ID);
536
537       begin
538          T := New_ATCB (Num_Entries);
539       exception
540          when others =>
541             Initialization.Undefer_Abort_Nestable (Self_ID);
542             raise Storage_Error with "Cannot allocate task";
543       end;
544
545       --  RTS_Lock is used by Abort_Dependents and Abort_Tasks. Up to this
546       --  point, it is possible that we may be part of a family of tasks that
547       --  is being aborted.
548
549       Lock_RTS;
550       Write_Lock (Self_ID);
551
552       --  Now, we must check that we have not been aborted. If so, we should
553       --  give up on creating this task, and simply return.
554
555       if not Self_ID.Callable then
556          pragma Assert (Self_ID.Pending_ATC_Level = 0);
557          pragma Assert (Self_ID.Pending_Action);
558          pragma Assert
559            (Chain.T_ID = null or else Chain.T_ID.Common.State = Unactivated);
560
561          Unlock (Self_ID);
562          Unlock_RTS;
563          Initialization.Undefer_Abort_Nestable (Self_ID);
564
565          --  ??? Should never get here
566
567          pragma Assert (False);
568          raise Standard'Abort_Signal;
569       end if;
570
571       Initialize_ATCB (Self_ID, State, Discriminants, P, Elaborated,
572         Base_Priority, Task_Info, Size, T, Success);
573
574       if not Success then
575          Free (T);
576          Unlock (Self_ID);
577          Unlock_RTS;
578          Initialization.Undefer_Abort_Nestable (Self_ID);
579          raise Storage_Error with "Failed to initialize task";
580       end if;
581
582       if Master = Foreign_Task_Level + 2 then
583
584          --  This should not happen, except when a foreign task creates non
585          --  library-level Ada tasks. In this case, we pretend the master is
586          --  a regular library level task, otherwise the run-time will get
587          --  confused when waiting for these tasks to terminate.
588
589          T.Master_of_Task := Library_Task_Level;
590
591       else
592          T.Master_of_Task := Master;
593       end if;
594
595       T.Master_Within := T.Master_of_Task + 1;
596
597       for L in T.Entry_Calls'Range loop
598          T.Entry_Calls (L).Self := T;
599          T.Entry_Calls (L).Level := L;
600       end loop;
601
602       if Task_Image'Length = 0 then
603          T.Common.Task_Image_Len := 0;
604       else
605          Len := 1;
606          T.Common.Task_Image (1) := Task_Image (Task_Image'First);
607
608          --  Remove unwanted blank space generated by 'Image
609
610          for J in Task_Image'First + 1 .. Task_Image'Last loop
611             if Task_Image (J) /= ' '
612               or else Task_Image (J - 1) /= '('
613             then
614                Len := Len + 1;
615                T.Common.Task_Image (Len) := Task_Image (J);
616                exit when Len = T.Common.Task_Image'Last;
617             end if;
618          end loop;
619
620          T.Common.Task_Image_Len := Len;
621       end if;
622
623       Unlock (Self_ID);
624       Unlock_RTS;
625
626       --  Note: we should not call 'new' while holding locks since new
627       --  may use locks (e.g. RTS_Lock under Windows) itself and cause a
628       --  deadlock.
629
630       if Build_Entry_Names then
631          T.Entry_Names :=
632            new Entry_Names_Array (1 .. Entry_Index (Num_Entries));
633       end if;
634
635       --  Create TSD as early as possible in the creation of a task, since it
636       --  may be used by the operation of Ada code within the task.
637
638       SSL.Create_TSD (T.Common.Compiler_Data);
639       T.Common.Activation_Link := Chain.T_ID;
640       Chain.T_ID := T;
641       Initialization.Initialize_Attributes_Link.all (T);
642       Created_Task := T;
643       Initialization.Undefer_Abort_Nestable (Self_ID);
644
645       if Runtime_Traces then
646          Send_Trace_Info (T_Create, T);
647       end if;
648    end Create_Task;
649
650    --------------------
651    -- Current_Master --
652    --------------------
653
654    function Current_Master return Master_Level is
655    begin
656       return STPO.Self.Master_Within;
657    end Current_Master;
658
659    ------------------
660    -- Enter_Master --
661    ------------------
662
663    procedure Enter_Master is
664       Self_ID : constant Task_Id := STPO.Self;
665    begin
666       Self_ID.Master_Within := Self_ID.Master_Within + 1;
667    end Enter_Master;
668
669    -------------------------------
670    -- Expunge_Unactivated_Tasks --
671    -------------------------------
672
673    --  See procedure Close_Entries for the general case
674
675    procedure Expunge_Unactivated_Tasks (Chain : in out Activation_Chain) is
676       Self_ID : constant Task_Id := STPO.Self;
677       C       : Task_Id;
678       Call    : Entry_Call_Link;
679       Temp    : Task_Id;
680
681    begin
682       pragma Debug
683         (Debug.Trace (Self_ID, "Expunge_Unactivated_Tasks", 'C'));
684
685       Initialization.Defer_Abort_Nestable (Self_ID);
686
687       --  ???
688       --  Experimentation has shown that abort is sometimes (but not always)
689       --  already deferred when this is called.
690
691       --  That may indicate an error. Find out what is going on
692
693       C := Chain.T_ID;
694       while C /= null loop
695          pragma Assert (C.Common.State = Unactivated);
696
697          Temp := C.Common.Activation_Link;
698
699          if C.Common.State = Unactivated then
700             Lock_RTS;
701             Write_Lock (C);
702
703             for J in 1 .. C.Entry_Num loop
704                Queuing.Dequeue_Head (C.Entry_Queues (J), Call);
705                pragma Assert (Call = null);
706             end loop;
707
708             Unlock (C);
709
710             Initialization.Remove_From_All_Tasks_List (C);
711             Unlock_RTS;
712
713             Vulnerable_Free_Task (C);
714             C := Temp;
715          end if;
716       end loop;
717
718       Chain.T_ID := null;
719       Initialization.Undefer_Abort_Nestable (Self_ID);
720    end Expunge_Unactivated_Tasks;
721
722    ---------------------------
723    -- Finalize_Global_Tasks --
724    ---------------------------
725
726    --  ???
727    --  We have a potential problem here if finalization of global objects does
728    --  anything with signals or the timer server, since by that time those
729    --  servers have terminated.
730
731    --  It is hard to see how that would occur
732
733    --  However, a better solution might be to do all this finalization
734    --  using the global finalization chain.
735
736    procedure Finalize_Global_Tasks is
737       Self_ID : constant Task_Id := STPO.Self;
738
739       Ignore  : Boolean;
740       pragma Unreferenced (Ignore);
741
742    begin
743       if Self_ID.Deferral_Level = 0 then
744          --  ???
745          --  In principle, we should be able to predict whether abort is
746          --  already deferred here (and it should not be deferred yet but in
747          --  practice it seems Finalize_Global_Tasks is being called sometimes,
748          --  from RTS code for exceptions, with abort already deferred.
749
750          Initialization.Defer_Abort_Nestable (Self_ID);
751
752          --  Never undefer again!!!
753       end if;
754
755       --  This code is only executed by the environment task
756
757       pragma Assert (Self_ID = Environment_Task);
758
759       --  Set Environment_Task'Callable to false to notify library-level tasks
760       --  that it is waiting for them.
761
762       Self_ID.Callable := False;
763
764       --  Exit level 2 master, for normal tasks in library-level packages
765
766       Complete_Master;
767
768       --  Force termination of "independent" library-level server tasks
769
770       Lock_RTS;
771
772       Abort_Dependents (Self_ID);
773
774       if not Single_Lock then
775          Unlock_RTS;
776       end if;
777
778       --  We need to explicitly wait for the task to be terminated here
779       --  because on true concurrent system, we may end this procedure before
780       --  the tasks are really terminated.
781
782       Write_Lock (Self_ID);
783
784       loop
785          exit when Utilities.Independent_Task_Count = 0;
786
787          --  We used to yield here, but this did not take into account low
788          --  priority tasks that would cause dead lock in some cases (true
789          --  FIFO scheduling).
790
791          Timed_Sleep
792            (Self_ID, 0.01, System.OS_Primitives.Relative,
793             Self_ID.Common.State, Ignore, Ignore);
794       end loop;
795
796       --  ??? On multi-processor environments, it seems that the above loop
797       --  isn't sufficient, so we need to add an additional delay.
798
799       Timed_Sleep
800         (Self_ID, 0.01, System.OS_Primitives.Relative,
801          Self_ID.Common.State, Ignore, Ignore);
802
803       Unlock (Self_ID);
804
805       if Single_Lock then
806          Unlock_RTS;
807       end if;
808
809       --  Complete the environment task
810
811       Vulnerable_Complete_Task (Self_ID);
812
813       --  Handle normal task termination by the environment task, but only
814       --  for the normal task termination. In the case of Abnormal and
815       --  Unhandled_Exception they must have been handled before, and the
816       --  task termination soft link must have been changed so the task
817       --  termination routine is not executed twice.
818
819       SSL.Task_Termination_Handler.all (Ada.Exceptions.Null_Occurrence);
820
821       --  Finalize the global list for controlled objects if needed
822
823       SSL.Finalize_Global_List.all;
824
825       --  Reset the soft links to non-tasking
826
827       SSL.Abort_Defer        := SSL.Abort_Defer_NT'Access;
828       SSL.Abort_Undefer      := SSL.Abort_Undefer_NT'Access;
829       SSL.Lock_Task          := SSL.Task_Lock_NT'Access;
830       SSL.Unlock_Task        := SSL.Task_Unlock_NT'Access;
831       SSL.Get_Jmpbuf_Address := SSL.Get_Jmpbuf_Address_NT'Access;
832       SSL.Set_Jmpbuf_Address := SSL.Set_Jmpbuf_Address_NT'Access;
833       SSL.Get_Sec_Stack_Addr := SSL.Get_Sec_Stack_Addr_NT'Access;
834       SSL.Set_Sec_Stack_Addr := SSL.Set_Sec_Stack_Addr_NT'Access;
835       SSL.Check_Abort_Status := SSL.Check_Abort_Status_NT'Access;
836       SSL.Get_Stack_Info     := SSL.Get_Stack_Info_NT'Access;
837
838       --  Don't bother trying to finalize Initialization.Global_Task_Lock
839       --  and System.Task_Primitives.RTS_Lock.
840
841    end Finalize_Global_Tasks;
842
843    ----------------------
844    -- Free_Entry_Names --
845    ----------------------
846
847    procedure Free_Entry_Names (T : Task_Id) is
848       Names : Entry_Names_Array_Access := T.Entry_Names;
849
850       procedure Free_Entry_Names_Array_Access is new
851         Ada.Unchecked_Deallocation
852           (Entry_Names_Array, Entry_Names_Array_Access);
853
854    begin
855       if Names = null then
856          return;
857       end if;
858
859       Free_Entry_Names_Array (Names.all);
860       Free_Entry_Names_Array_Access (Names);
861    end Free_Entry_Names;
862
863    ---------------
864    -- Free_Task --
865    ---------------
866
867    procedure Free_Task (T : Task_Id) is
868       Self_Id : constant Task_Id := Self;
869
870    begin
871       if T.Common.State = Terminated then
872
873          --  It is not safe to call Abort_Defer or Write_Lock at this stage
874
875          Initialization.Task_Lock (Self_Id);
876
877          Lock_RTS;
878          Initialization.Finalize_Attributes_Link.all (T);
879          Initialization.Remove_From_All_Tasks_List (T);
880          Unlock_RTS;
881
882          Initialization.Task_Unlock (Self_Id);
883
884          Free_Entry_Names (T);
885          System.Task_Primitives.Operations.Finalize_TCB (T);
886
887       --  If the task is not terminated, then we simply ignore the call. This
888       --  happens when a user program attempts an unchecked deallocation on
889       --  a non-terminated task.
890
891       else
892          null;
893       end if;
894    end Free_Task;
895
896    ---------------------------
897    -- Move_Activation_Chain --
898    ---------------------------
899
900    procedure Move_Activation_Chain
901      (From, To   : Activation_Chain_Access;
902       New_Master : Master_ID)
903    is
904       Self_ID : constant Task_Id := STPO.Self;
905       C       : Task_Id;
906
907    begin
908       pragma Debug
909         (Debug.Trace (Self_ID, "Move_Activation_Chain", 'C'));
910
911       --  Nothing to do if From is empty, and we can check that without
912       --  deferring aborts.
913
914       C := From.all.T_ID;
915
916       if C = null then
917          return;
918       end if;
919
920       Initialization.Defer_Abort (Self_ID);
921
922       --  Loop through the From chain, changing their Master_of_Task
923       --  fields, and to find the end of the chain.
924
925       loop
926          C.Master_of_Task := New_Master;
927          exit when C.Common.Activation_Link = null;
928          C := C.Common.Activation_Link;
929       end loop;
930
931       --  Hook From in at the start of To
932
933       C.Common.Activation_Link := To.all.T_ID;
934       To.all.T_ID := From.all.T_ID;
935
936       --  Set From to empty
937
938       From.all.T_ID := null;
939
940       Initialization.Undefer_Abort (Self_ID);
941    end Move_Activation_Chain;
942
943    --  Compiler interface only. Do not call from within the RTS
944
945    --------------------
946    -- Set_Entry_Name --
947    --------------------
948
949    procedure Set_Entry_Name
950      (T   : Task_Id;
951       Pos : Task_Entry_Index;
952       Val : String_Access)
953    is
954    begin
955       pragma Assert (T.Entry_Names /= null);
956
957       T.Entry_Names (Entry_Index (Pos)) := Val;
958    end Set_Entry_Name;
959
960    ------------------
961    -- Task_Wrapper --
962    ------------------
963
964    --  The task wrapper is a procedure that is called first for each task body
965    --  and which in turn calls the compiler-generated task body procedure.
966    --  The wrapper's main job is to do initialization for the task. It also
967    --  has some locally declared objects that serve as per-task local data.
968    --  Task finalization is done by Complete_Task, which is called from an
969    --  at-end handler that the compiler generates.
970
971    procedure Task_Wrapper (Self_ID : Task_Id) is
972       use type SSE.Storage_Offset;
973       use System.Standard_Library;
974       use System.Stack_Usage;
975
976       Bottom_Of_Stack : aliased Integer;
977
978       Task_Alternate_Stack :
979         aliased SSE.Storage_Array (1 .. Alternate_Stack_Size);
980       --  The alternate signal stack for this task, if any
981
982       Use_Alternate_Stack : constant Boolean := Alternate_Stack_Size /= 0;
983       --  Whether to use above alternate signal stack for stack overflows
984
985       Secondary_Stack_Size :
986         constant SSE.Storage_Offset :=
987           Self_ID.Common.Compiler_Data.Pri_Stack_Info.Size *
988           SSE.Storage_Offset (Parameters.Sec_Stack_Ratio) / 100;
989
990       Secondary_Stack : aliased SSE.Storage_Array (1 .. Secondary_Stack_Size);
991
992       pragma Warnings (Off);
993       --  Why are warnings being turned off here???
994
995       Secondary_Stack_Address : System.Address := Secondary_Stack'Address;
996       --  Address of secondary stack. In the fixed secondary stack case, this
997       --  value is not modified, causing a warning, hence the bracketing with
998       --  Warnings (Off/On). But why is so much *more* bracketed???
999
1000       Small_Overflow_Guard : constant := 12 * 1024;
1001       --  Note: this used to be 4K, but was changed to 12K, since smaller
1002       --  values resulted in segmentation faults from dynamic stack analysis.
1003
1004       Big_Overflow_Guard   : constant := 16 * 1024;
1005       Small_Stack_Limit    : constant := 64 * 1024;
1006       --  ??? These three values are experimental, and seems to work on most
1007       --  platforms. They still need to be analyzed further. They also need
1008       --  documentation, what are they???
1009
1010       Size : Natural :=
1011                Natural (Self_ID.Common.Compiler_Data.Pri_Stack_Info.Size);
1012
1013       Overflow_Guard : Natural;
1014       --  Size of the overflow guard, used by dynamic stack usage analysis
1015
1016       pragma Warnings (On);
1017
1018       SEH_Table : aliased SSE.Storage_Array (1 .. 8);
1019       --  Structured Exception Registration table (2 words)
1020
1021       procedure Install_SEH_Handler (Addr : System.Address);
1022       pragma Import (C, Install_SEH_Handler, "__gnat_install_SEH_handler");
1023       --  Install the SEH (Structured Exception Handling) handler
1024
1025       Cause : Cause_Of_Termination := Normal;
1026       --  Indicates the reason why this task terminates. Normal corresponds to
1027       --  a task terminating due to completing the last statement of its body,
1028       --  or as a result of waiting on a terminate alternative. If the task
1029       --  terminates because it is being aborted then Cause will be set to
1030       --  Abnormal. If the task terminates because of an exception raised by
1031       --  the execution of its task body, then Cause is set to
1032       --  Unhandled_Exception.
1033
1034       EO : Exception_Occurrence;
1035       --  If the task terminates because of an exception raised by the
1036       --  execution of its task body, then EO will contain the associated
1037       --  exception occurrence. Otherwise, it will contain Null_Occurrence.
1038
1039       TH : Termination_Handler := null;
1040       --  Pointer to the protected procedure to be executed upon task
1041       --  termination.
1042
1043       procedure Search_Fall_Back_Handler (ID : Task_Id);
1044       --  Procedure that searches recursively a fall-back handler through the
1045       --  master relationship. If the handler is found, its pointer is stored
1046       --  in TH.
1047
1048       ------------------------------
1049       -- Search_Fall_Back_Handler --
1050       ------------------------------
1051
1052       procedure Search_Fall_Back_Handler (ID : Task_Id) is
1053       begin
1054          --  If there is a fall back handler, store its pointer for later
1055          --  execution.
1056
1057          if ID.Common.Fall_Back_Handler /= null then
1058             TH := ID.Common.Fall_Back_Handler;
1059
1060          --  Otherwise look for a fall back handler in the parent
1061
1062          elsif ID.Common.Parent /= null then
1063             Search_Fall_Back_Handler (ID.Common.Parent);
1064
1065          --  Otherwise, do nothing
1066
1067          else
1068             return;
1069          end if;
1070       end Search_Fall_Back_Handler;
1071
1072    begin
1073       pragma Assert (Self_ID.Deferral_Level = 1);
1074
1075       --  Assume a size of the stack taken at this stage
1076
1077       Overflow_Guard :=
1078         (if Size < Small_Stack_Limit
1079          then Small_Overflow_Guard
1080          else Big_Overflow_Guard);
1081
1082       if not Parameters.Sec_Stack_Dynamic then
1083          Self_ID.Common.Compiler_Data.Sec_Stack_Addr :=
1084            Secondary_Stack'Address;
1085          SST.SS_Init (Secondary_Stack_Address, Integer (Secondary_Stack'Last));
1086          Size := Size - Natural (Secondary_Stack_Size);
1087       end if;
1088
1089       if Use_Alternate_Stack then
1090          Self_ID.Common.Task_Alternate_Stack := Task_Alternate_Stack'Address;
1091       end if;
1092
1093       Size := Size - Overflow_Guard;
1094
1095       if System.Stack_Usage.Is_Enabled then
1096          STPO.Lock_RTS;
1097          Initialize_Analyzer
1098            (Self_ID.Common.Analyzer,
1099             Self_ID.Common.Task_Image
1100               (1 .. Self_ID.Common.Task_Image_Len),
1101             Natural
1102               (Self_ID.Common.Compiler_Data.Pri_Stack_Info.Size),
1103             Size,
1104             SSE.To_Integer (Bottom_Of_Stack'Address));
1105          STPO.Unlock_RTS;
1106          Fill_Stack (Self_ID.Common.Analyzer);
1107       end if;
1108
1109       --  Set the guard page at the bottom of the stack. The call to unprotect
1110       --  the page is done in Terminate_Task
1111
1112       Stack_Guard (Self_ID, True);
1113
1114       --  Initialize low-level TCB components, that cannot be initialized by
1115       --  the creator. Enter_Task sets Self_ID.LL.Thread
1116
1117       Enter_Task (Self_ID);
1118
1119       --  We setup the SEH (Structured Exception Handling) handler if supported
1120       --  on the target.
1121
1122       Install_SEH_Handler (SEH_Table'Address);
1123
1124       --  Initialize exception occurrence
1125
1126       Save_Occurrence (EO, Ada.Exceptions.Null_Occurrence);
1127
1128       --  We lock RTS_Lock to wait for activator to finish activating the rest
1129       --  of the chain, so that everyone in the chain comes out in priority
1130       --  order.
1131
1132       --  This also protects the value of
1133       --    Self_ID.Common.Activator.Common.Wait_Count.
1134
1135       Lock_RTS;
1136       Unlock_RTS;
1137
1138       if not System.Restrictions.Abort_Allowed then
1139
1140          --  If Abort is not allowed, reset the deferral level since it will
1141          --  not get changed by the generated code. Keeping a default value
1142          --  of one would prevent some operations (e.g. select or delay) to
1143          --  proceed successfully.
1144
1145          Self_ID.Deferral_Level := 0;
1146       end if;
1147
1148       if Global_Task_Debug_Event_Set then
1149          Debug.Signal_Debug_Event
1150           (Debug.Debug_Event_Run, Self_ID);
1151       end if;
1152
1153       begin
1154          --  We are separating the following portion of the code in order to
1155          --  place the exception handlers in a different block. In this way,
1156          --  we do not call Set_Jmpbuf_Address (which needs Self) before we
1157          --  set Self in Enter_Task
1158
1159          --  Call the task body procedure
1160
1161          --  The task body is called with abort still deferred. That
1162          --  eliminates a dangerous window, for which we had to patch-up in
1163          --  Terminate_Task.
1164
1165          --  During the expansion of the task body, we insert an RTS-call
1166          --  to Abort_Undefer, at the first point where abort should be
1167          --  allowed.
1168
1169          Self_ID.Common.Task_Entry_Point (Self_ID.Common.Task_Arg);
1170          Initialization.Defer_Abort_Nestable (Self_ID);
1171
1172       exception
1173          --  We can't call Terminate_Task in the exception handlers below,
1174          --  since there may be (e.g. in the case of GCC exception handling)
1175          --  clean ups associated with the exception handler that need to
1176          --  access task specific data.
1177
1178          --  Defer abort so that this task can't be aborted while exiting
1179
1180          when Standard'Abort_Signal =>
1181             Initialization.Defer_Abort_Nestable (Self_ID);
1182
1183             --  Update the cause that motivated the task termination so that
1184             --  the appropriate information is passed to the task termination
1185             --  procedure. Task termination as a result of waiting on a
1186             --  terminate alternative is a normal termination, although it is
1187             --  implemented using the abort mechanisms.
1188
1189             if Self_ID.Terminate_Alternative then
1190                Cause := Normal;
1191
1192                if Global_Task_Debug_Event_Set then
1193                   Debug.Signal_Debug_Event
1194                    (Debug.Debug_Event_Terminated, Self_ID);
1195                end if;
1196             else
1197                Cause := Abnormal;
1198
1199                if Global_Task_Debug_Event_Set then
1200                   Debug.Signal_Debug_Event
1201                    (Debug.Debug_Event_Abort_Terminated, Self_ID);
1202                end if;
1203             end if;
1204          when others =>
1205             --  ??? Using an E : others here causes CD2C11A to fail on Tru64
1206
1207             Initialization.Defer_Abort_Nestable (Self_ID);
1208
1209             --  Perform the task specific exception tracing duty.  We handle
1210             --  these outputs here and not in the common notification routine
1211             --  because we need access to tasking related data and we don't
1212             --  want to drag dependencies against tasking related units in the
1213             --  the common notification units. Additionally, no trace is ever
1214             --  triggered from the common routine for the Unhandled_Raise case
1215             --  in tasks, since an exception never appears unhandled in this
1216             --  context because of this handler.
1217
1218             if Exception_Trace = Unhandled_Raise then
1219                Trace_Unhandled_Exception_In_Task (Self_ID);
1220             end if;
1221
1222             --  Update the cause that motivated the task termination so that
1223             --  the appropriate information is passed to the task termination
1224             --  procedure, as well as the associated Exception_Occurrence.
1225
1226             Cause := Unhandled_Exception;
1227
1228             Save_Occurrence (EO, SSL.Get_Current_Excep.all.all);
1229
1230             if Global_Task_Debug_Event_Set then
1231                Debug.Signal_Debug_Event
1232                  (Debug.Debug_Event_Exception_Terminated, Self_ID);
1233             end if;
1234       end;
1235
1236       --  Look for a task termination handler. This code is for all tasks but
1237       --  the environment task. The task termination code for the environment
1238       --  task is executed by SSL.Task_Termination_Handler.
1239
1240       if Single_Lock then
1241          Lock_RTS;
1242       end if;
1243
1244       Write_Lock (Self_ID);
1245
1246       if Self_ID.Common.Specific_Handler /= null then
1247          TH := Self_ID.Common.Specific_Handler;
1248       else
1249          --  Look for a fall-back handler following the master relationship
1250          --  for the task.
1251
1252          Search_Fall_Back_Handler (Self_ID);
1253       end if;
1254
1255       Unlock (Self_ID);
1256
1257       if Single_Lock then
1258          Unlock_RTS;
1259       end if;
1260
1261       --  Execute the task termination handler if we found it
1262
1263       if TH /= null then
1264          TH.all (Cause, Self_ID, EO);
1265       end if;
1266
1267       if System.Stack_Usage.Is_Enabled then
1268          Compute_Result (Self_ID.Common.Analyzer);
1269          Report_Result (Self_ID.Common.Analyzer);
1270       end if;
1271
1272       Terminate_Task (Self_ID);
1273    end Task_Wrapper;
1274
1275    --------------------
1276    -- Terminate_Task --
1277    --------------------
1278
1279    --  Before we allow the thread to exit, we must clean up. This is a
1280    --  delicate job. We must wake up the task's master, who may immediately try
1281    --  to deallocate the ATCB out from under the current task WHILE IT IS STILL
1282    --  EXECUTING.
1283
1284    --  To avoid this, the parent task must be blocked up to the latest
1285    --  statement executed. The trouble is that we have another step that we
1286    --  also want to postpone to the very end, i.e., calling SSL.Destroy_TSD.
1287    --  We have to postpone that until the end because compiler-generated code
1288    --  is likely to try to access that data at just about any point.
1289
1290    --  We can't call Destroy_TSD while we are holding any other locks, because
1291    --  it locks Global_Task_Lock, and our deadlock prevention rules require
1292    --  that to be the outermost lock. Our first "solution" was to just lock
1293    --  Global_Task_Lock in addition to the other locks, and force the parent to
1294    --  also lock this lock between its wakeup and its freeing of the ATCB. See
1295    --  Complete_Task for the parent-side of the code that has the matching
1296    --  calls to Task_Lock and Task_Unlock. That was not really a solution,
1297    --  since the operation Task_Unlock continued to access the ATCB after
1298    --  unlocking, after which the parent was observed to race ahead, deallocate
1299    --  the ATCB, and then reallocate it to another task. The call to
1300    --  Undefer_Abort in Task_Unlock by the "terminated" task was overwriting
1301    --  the data of the new task that reused the ATCB! To solve this problem, we
1302    --  introduced the new operation Final_Task_Unlock.
1303
1304    procedure Terminate_Task (Self_ID : Task_Id) is
1305       Environment_Task : constant Task_Id := STPO.Environment_Task;
1306       Master_of_Task   : Integer;
1307
1308    begin
1309       Debug.Task_Termination_Hook;
1310
1311       if Runtime_Traces then
1312          Send_Trace_Info (T_Terminate);
1313       end if;
1314
1315       --  Since GCC cannot allocate stack chunks efficiently without reordering
1316       --  some of the allocations, we have to handle this unexpected situation
1317       --  here. We should normally never have to call Vulnerable_Complete_Task
1318       --  here.
1319
1320       if Self_ID.Common.Activator /= null then
1321          Vulnerable_Complete_Task (Self_ID);
1322       end if;
1323
1324       Initialization.Task_Lock (Self_ID);
1325
1326       if Single_Lock then
1327          Lock_RTS;
1328       end if;
1329
1330       Master_of_Task := Self_ID.Master_of_Task;
1331
1332       --  Check if the current task is an independent task If so, decrement
1333       --  the Independent_Task_Count value.
1334
1335       if Master_of_Task = Independent_Task_Level then
1336          if Single_Lock then
1337             Utilities.Independent_Task_Count :=
1338               Utilities.Independent_Task_Count - 1;
1339          else
1340             Write_Lock (Environment_Task);
1341             Utilities.Independent_Task_Count :=
1342               Utilities.Independent_Task_Count - 1;
1343             Unlock (Environment_Task);
1344          end if;
1345       end if;
1346
1347       --  Unprotect the guard page if needed
1348
1349       Stack_Guard (Self_ID, False);
1350
1351       Utilities.Make_Passive (Self_ID, Task_Completed => True);
1352
1353       if Single_Lock then
1354          Unlock_RTS;
1355       end if;
1356
1357       pragma Assert (Check_Exit (Self_ID));
1358
1359       SSL.Destroy_TSD (Self_ID.Common.Compiler_Data);
1360       Initialization.Final_Task_Unlock (Self_ID);
1361
1362       --  WARNING: past this point, this thread must assume that the ATCB has
1363       --  been deallocated. It should not be accessed again.
1364
1365       if Master_of_Task > 0 then
1366          STPO.Exit_Task;
1367       end if;
1368    end Terminate_Task;
1369
1370    ----------------
1371    -- Terminated --
1372    ----------------
1373
1374    function Terminated (T : Task_Id) return Boolean is
1375       Self_ID : constant Task_Id := STPO.Self;
1376       Result  : Boolean;
1377
1378    begin
1379       Initialization.Defer_Abort_Nestable (Self_ID);
1380
1381       if Single_Lock then
1382          Lock_RTS;
1383       end if;
1384
1385       Write_Lock (T);
1386       Result := T.Common.State = Terminated;
1387       Unlock (T);
1388
1389       if Single_Lock then
1390          Unlock_RTS;
1391       end if;
1392
1393       Initialization.Undefer_Abort_Nestable (Self_ID);
1394       return Result;
1395    end Terminated;
1396
1397    ----------------------------------------
1398    -- Trace_Unhandled_Exception_In_Task --
1399    ----------------------------------------
1400
1401    procedure Trace_Unhandled_Exception_In_Task (Self_Id : Task_Id) is
1402       procedure To_Stderr (S : String);
1403       pragma Import (Ada, To_Stderr, "__gnat_to_stderr");
1404
1405       use System.Soft_Links;
1406       use System.Standard_Library;
1407
1408       function To_Address is new
1409         Ada.Unchecked_Conversion
1410          (Task_Id, System.Task_Primitives.Task_Address);
1411
1412       function Tailored_Exception_Information
1413         (E : Exception_Occurrence) return String;
1414       pragma Import
1415         (Ada, Tailored_Exception_Information,
1416          "__gnat_tailored_exception_information");
1417
1418       Excep : constant Exception_Occurrence_Access :=
1419                 SSL.Get_Current_Excep.all;
1420
1421    begin
1422       --  This procedure is called by the task outermost handler in
1423       --  Task_Wrapper below, so only once the task stack has been fully
1424       --  unwound. The common notification routine has been called at the
1425       --  raise point already.
1426
1427       --  Lock to prevent unsynchronized output
1428
1429       Initialization.Task_Lock (Self_Id);
1430       To_Stderr ("task ");
1431
1432       if Self_Id.Common.Task_Image_Len /= 0 then
1433          To_Stderr
1434            (Self_Id.Common.Task_Image (1 .. Self_Id.Common.Task_Image_Len));
1435          To_Stderr ("_");
1436       end if;
1437
1438       To_Stderr (System.Address_Image (To_Address (Self_Id)));
1439       To_Stderr (" terminated by unhandled exception");
1440       To_Stderr ((1 => ASCII.LF));
1441       To_Stderr (Tailored_Exception_Information (Excep.all));
1442       Initialization.Task_Unlock (Self_Id);
1443    end Trace_Unhandled_Exception_In_Task;
1444
1445    ------------------------------------
1446    -- Vulnerable_Complete_Activation --
1447    ------------------------------------
1448
1449    --  As in several other places, the locks of the activator and activated
1450    --  task are both locked here. This follows our deadlock prevention lock
1451    --  ordering policy, since the activated task must be created after the
1452    --  activator.
1453
1454    procedure Vulnerable_Complete_Activation (Self_ID : Task_Id) is
1455       Activator : constant Task_Id := Self_ID.Common.Activator;
1456
1457    begin
1458       pragma Debug (Debug.Trace (Self_ID, "V_Complete_Activation", 'C'));
1459
1460       Write_Lock (Activator);
1461       Write_Lock (Self_ID);
1462
1463       pragma Assert (Self_ID.Common.Activator /= null);
1464
1465       --  Remove dangling reference to Activator, since a task may
1466       --  outlive its activator.
1467
1468       Self_ID.Common.Activator := null;
1469
1470       --  Wake up the activator, if it is waiting for a chain of tasks to
1471       --  activate, and we are the last in the chain to complete activation.
1472
1473       if Activator.Common.State = Activator_Sleep then
1474          Activator.Common.Wait_Count := Activator.Common.Wait_Count - 1;
1475
1476          if Activator.Common.Wait_Count = 0 then
1477             Wakeup (Activator, Activator_Sleep);
1478          end if;
1479       end if;
1480
1481       --  The activator raises a Tasking_Error if any task it is activating
1482       --  is completed before the activation is done. However, if the reason
1483       --  for the task completion is an abort, we do not raise an exception.
1484       --  See RM 9.2(5).
1485
1486       if not Self_ID.Callable and then Self_ID.Pending_ATC_Level /= 0 then
1487          Activator.Common.Activation_Failed := True;
1488       end if;
1489
1490       Unlock (Self_ID);
1491       Unlock (Activator);
1492
1493       --  After the activation, active priority should be the same as base
1494       --  priority. We must unlock the Activator first, though, since it
1495       --  should not wait if we have lower priority.
1496
1497       if Get_Priority (Self_ID) /= Self_ID.Common.Base_Priority then
1498          Write_Lock (Self_ID);
1499          Set_Priority (Self_ID, Self_ID.Common.Base_Priority);
1500          Unlock (Self_ID);
1501       end if;
1502    end Vulnerable_Complete_Activation;
1503
1504    --------------------------------
1505    -- Vulnerable_Complete_Master --
1506    --------------------------------
1507
1508    procedure Vulnerable_Complete_Master (Self_ID : Task_Id) is
1509       C  : Task_Id;
1510       P  : Task_Id;
1511       CM : constant Master_Level := Self_ID.Master_Within;
1512       T  : aliased Task_Id;
1513
1514       To_Be_Freed : Task_Id;
1515       --  This is a list of ATCBs to be freed, after we have released all RTS
1516       --  locks. This is necessary because of the locking order rules, since
1517       --  the storage manager uses Global_Task_Lock.
1518
1519       pragma Warnings (Off);
1520       function Check_Unactivated_Tasks return Boolean;
1521       pragma Warnings (On);
1522       --  Temporary error-checking code below. This is part of the checks
1523       --  added in the new run time. Call it only inside a pragma Assert.
1524
1525       -----------------------------
1526       -- Check_Unactivated_Tasks --
1527       -----------------------------
1528
1529       function Check_Unactivated_Tasks return Boolean is
1530       begin
1531          if not Single_Lock then
1532             Lock_RTS;
1533          end if;
1534
1535          Write_Lock (Self_ID);
1536
1537          C := All_Tasks_List;
1538          while C /= null loop
1539             if C.Common.Activator = Self_ID and then C.Master_of_Task = CM then
1540                return False;
1541             end if;
1542
1543             if C.Common.Parent = Self_ID and then C.Master_of_Task = CM then
1544                Write_Lock (C);
1545
1546                if C.Common.State = Unactivated then
1547                   return False;
1548                end if;
1549
1550                Unlock (C);
1551             end if;
1552
1553             C := C.Common.All_Tasks_Link;
1554          end loop;
1555
1556          Unlock (Self_ID);
1557
1558          if not Single_Lock then
1559             Unlock_RTS;
1560          end if;
1561
1562          return True;
1563       end Check_Unactivated_Tasks;
1564
1565    --  Start of processing for Vulnerable_Complete_Master
1566
1567    begin
1568       pragma Debug
1569         (Debug.Trace (Self_ID, "V_Complete_Master", 'C'));
1570
1571       pragma Assert (Self_ID.Common.Wait_Count = 0);
1572       pragma Assert
1573         (Self_ID.Deferral_Level > 0
1574           or else not System.Restrictions.Abort_Allowed);
1575
1576       --  Count how many active dependent tasks this master currently has, and
1577       --  record this in Wait_Count.
1578
1579       --  This count should start at zero, since it is initialized to zero for
1580       --  new tasks, and the task should not exit the sleep-loops that use this
1581       --  count until the count reaches zero.
1582
1583       --  While we're counting, if we run across any unactivated tasks that
1584       --  belong to this master, we summarily terminate them as required by
1585       --  RM-9.2(6).
1586
1587       Lock_RTS;
1588       Write_Lock (Self_ID);
1589
1590       C := All_Tasks_List;
1591       while C /= null loop
1592
1593          --  Terminate unactivated (never-to-be activated) tasks
1594
1595          if C.Common.Activator = Self_ID and then C.Master_of_Task = CM then
1596
1597             pragma Assert (C.Common.State = Unactivated);
1598             --  Usually, C.Common.Activator = Self_ID implies C.Master_of_Task
1599             --  = CM. The only case where C is pending activation by this
1600             --  task, but the master of C is not CM is in Ada 2005, when C is
1601             --  part of a return object of a build-in-place function.
1602
1603             Write_Lock (C);
1604             C.Common.Activator := null;
1605             C.Common.State := Terminated;
1606             C.Callable := False;
1607             Utilities.Cancel_Queued_Entry_Calls (C);
1608             Unlock (C);
1609          end if;
1610
1611          --  Count it if dependent on this master
1612
1613          if C.Common.Parent = Self_ID and then C.Master_of_Task = CM then
1614             Write_Lock (C);
1615
1616             if C.Awake_Count /= 0 then
1617                Self_ID.Common.Wait_Count := Self_ID.Common.Wait_Count + 1;
1618             end if;
1619
1620             Unlock (C);
1621          end if;
1622
1623          C := C.Common.All_Tasks_Link;
1624       end loop;
1625
1626       Self_ID.Common.State := Master_Completion_Sleep;
1627       Unlock (Self_ID);
1628
1629       if not Single_Lock then
1630          Unlock_RTS;
1631       end if;
1632
1633       --  Wait until dependent tasks are all terminated or ready to terminate.
1634       --  While waiting, the task may be awakened if the task's priority needs
1635       --  changing, or this master is aborted. In the latter case, we abort the
1636       --  dependents, and resume waiting until Wait_Count goes to zero.
1637
1638       Write_Lock (Self_ID);
1639
1640       loop
1641          exit when Self_ID.Common.Wait_Count = 0;
1642
1643          --  Here is a difference as compared to Complete_Master
1644
1645          if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
1646            and then not Self_ID.Dependents_Aborted
1647          then
1648             if Single_Lock then
1649                Abort_Dependents (Self_ID);
1650             else
1651                Unlock (Self_ID);
1652                Lock_RTS;
1653                Abort_Dependents (Self_ID);
1654                Unlock_RTS;
1655                Write_Lock (Self_ID);
1656             end if;
1657          else
1658             Sleep (Self_ID, Master_Completion_Sleep);
1659          end if;
1660       end loop;
1661
1662       Self_ID.Common.State := Runnable;
1663       Unlock (Self_ID);
1664
1665       --  Dependents are all terminated or on terminate alternatives. Now,
1666       --  force those on terminate alternatives to terminate, by aborting them.
1667
1668       pragma Assert (Check_Unactivated_Tasks);
1669
1670       if Self_ID.Alive_Count > 1 then
1671          --  ???
1672          --  Consider finding a way to skip the following extra steps if there
1673          --  are no dependents with terminate alternatives. This could be done
1674          --  by adding another count to the ATCB, similar to Awake_Count, but
1675          --  keeping track of tasks that are on terminate alternatives.
1676
1677          pragma Assert (Self_ID.Common.Wait_Count = 0);
1678
1679          --  Force any remaining dependents to terminate by aborting them
1680
1681          if not Single_Lock then
1682             Lock_RTS;
1683          end if;
1684
1685          Abort_Dependents (Self_ID);
1686
1687          --  Above, when we "abort" the dependents we are simply using this
1688          --  operation for convenience. We are not required to support the full
1689          --  abort-statement semantics; in particular, we are not required to
1690          --  immediately cancel any queued or in-service entry calls. That is
1691          --  good, because if we tried to cancel a call we would need to lock
1692          --  the caller, in order to wake the caller up. Our anti-deadlock
1693          --  rules prevent us from doing that without releasing the locks on C
1694          --  and Self_ID. Releasing and retaking those locks would be wasteful
1695          --  at best, and should not be considered further without more
1696          --  detailed analysis of potential concurrent accesses to the ATCBs
1697          --  of C and Self_ID.
1698
1699          --  Count how many "alive" dependent tasks this master currently has,
1700          --  and record this in Wait_Count. This count should start at zero,
1701          --  since it is initialized to zero for new tasks, and the task should
1702          --  not exit the sleep-loops that use this count until the count
1703          --  reaches zero.
1704
1705          pragma Assert (Self_ID.Common.Wait_Count = 0);
1706
1707          Write_Lock (Self_ID);
1708
1709          C := All_Tasks_List;
1710          while C /= null loop
1711             if C.Common.Parent = Self_ID and then C.Master_of_Task = CM then
1712                Write_Lock (C);
1713
1714                pragma Assert (C.Awake_Count = 0);
1715
1716                if C.Alive_Count > 0 then
1717                   pragma Assert (C.Terminate_Alternative);
1718                   Self_ID.Common.Wait_Count := Self_ID.Common.Wait_Count + 1;
1719                end if;
1720
1721                Unlock (C);
1722             end if;
1723
1724             C := C.Common.All_Tasks_Link;
1725          end loop;
1726
1727          Self_ID.Common.State := Master_Phase_2_Sleep;
1728          Unlock (Self_ID);
1729
1730          if not Single_Lock then
1731             Unlock_RTS;
1732          end if;
1733
1734          --  Wait for all counted tasks to finish terminating themselves
1735
1736          Write_Lock (Self_ID);
1737
1738          loop
1739             exit when Self_ID.Common.Wait_Count = 0;
1740             Sleep (Self_ID, Master_Phase_2_Sleep);
1741          end loop;
1742
1743          Self_ID.Common.State := Runnable;
1744          Unlock (Self_ID);
1745       end if;
1746
1747       --  We don't wake up for abort here. We are already terminating just as
1748       --  fast as we can, so there is no point.
1749
1750       --  Remove terminated tasks from the list of Self_ID's dependents, but
1751       --  don't free their ATCBs yet, because of lock order restrictions, which
1752       --  don't allow us to call "free" or "malloc" while holding any other
1753       --  locks. Instead, we put those ATCBs to be freed onto a temporary list,
1754       --  called To_Be_Freed.
1755
1756       if not Single_Lock then
1757          Lock_RTS;
1758       end if;
1759
1760       C := All_Tasks_List;
1761       P := null;
1762       while C /= null loop
1763          if C.Common.Parent = Self_ID and then C.Master_of_Task >= CM then
1764             if P /= null then
1765                P.Common.All_Tasks_Link := C.Common.All_Tasks_Link;
1766             else
1767                All_Tasks_List := C.Common.All_Tasks_Link;
1768             end if;
1769
1770             T := C.Common.All_Tasks_Link;
1771             C.Common.All_Tasks_Link := To_Be_Freed;
1772             To_Be_Freed := C;
1773             C := T;
1774
1775          else
1776             P := C;
1777             C := C.Common.All_Tasks_Link;
1778          end if;
1779       end loop;
1780
1781       Unlock_RTS;
1782
1783       --  Free all the ATCBs on the list To_Be_Freed
1784
1785       --  The ATCBs in the list are no longer in All_Tasks_List, and after
1786       --  any interrupt entries are detached from them they should no longer
1787       --  be referenced.
1788
1789       --  Global_Task_Lock (Task_Lock/Unlock) is locked in the loop below to
1790       --  avoid a race between a terminating task and its parent. The parent
1791       --  might try to deallocate the ACTB out from underneath the exiting
1792       --  task. Note that Free will also lock Global_Task_Lock, but that is
1793       --  OK, since this is the *one* lock for which we have a mechanism to
1794       --  support nested locking. See Task_Wrapper and its finalizer for more
1795       --  explanation.
1796
1797       --  ???
1798       --  The check "T.Common.Parent /= null ..." below is to prevent dangling
1799       --  references to terminated library-level tasks, which could otherwise
1800       --  occur during finalization of library-level objects. A better solution
1801       --  might be to hook task objects into the finalization chain and
1802       --  deallocate the ATCB when the task object is deallocated. However,
1803       --  this change is not likely to gain anything significant, since all
1804       --  this storage should be recovered en-masse when the process exits.
1805
1806       while To_Be_Freed /= null loop
1807          T := To_Be_Freed;
1808          To_Be_Freed := T.Common.All_Tasks_Link;
1809
1810          --  ??? On SGI there is currently no Interrupt_Manager, that's why we
1811          --  need to check if the Interrupt_Manager_ID is null.
1812
1813          if T.Interrupt_Entry and then Interrupt_Manager_ID /= null then
1814             declare
1815                Detach_Interrupt_Entries_Index : constant Task_Entry_Index := 1;
1816                --  Corresponds to the entry index of System.Interrupts.
1817                --  Interrupt_Manager.Detach_Interrupt_Entries.
1818                --  Be sure to update this value when changing
1819                --  Interrupt_Manager specs.
1820
1821                type Param_Type is access all Task_Id;
1822
1823                Param : aliased Param_Type := T'Access;
1824
1825             begin
1826                System.Tasking.Rendezvous.Call_Simple
1827                  (Interrupt_Manager_ID, Detach_Interrupt_Entries_Index,
1828                   Param'Address);
1829             end;
1830          end if;
1831
1832          if (T.Common.Parent /= null
1833               and then T.Common.Parent.Common.Parent /= null)
1834            or else T.Master_of_Task > Library_Task_Level
1835          then
1836             Initialization.Task_Lock (Self_ID);
1837
1838             --  If Sec_Stack_Addr is not null, it means that Destroy_TSD
1839             --  has not been called yet (case of an unactivated task).
1840
1841             if T.Common.Compiler_Data.Sec_Stack_Addr /= Null_Address then
1842                SSL.Destroy_TSD (T.Common.Compiler_Data);
1843             end if;
1844
1845             Vulnerable_Free_Task (T);
1846             Initialization.Task_Unlock (Self_ID);
1847          end if;
1848       end loop;
1849
1850       --  It might seem nice to let the terminated task deallocate its own
1851       --  ATCB. That would not cover the case of unactivated tasks. It also
1852       --  would force us to keep the underlying thread around past termination,
1853       --  since references to the ATCB are possible past termination.
1854
1855       --  Currently, we get rid of the thread as soon as the task terminates,
1856       --  and let the parent recover the ATCB later.
1857
1858       --  Some day, if we want to recover the ATCB earlier, at task
1859       --  termination, we could consider using "fat task IDs", that include the
1860       --  serial number with the ATCB pointer, to catch references to tasks
1861       --  that no longer have ATCBs. It is not clear how much this would gain,
1862       --  since the user-level task object would still be occupying storage.
1863
1864       --  Make next master level up active. We don't need to lock the ATCB,
1865       --  since the value is only updated by each task for itself.
1866
1867       Self_ID.Master_Within := CM - 1;
1868    end Vulnerable_Complete_Master;
1869
1870    ------------------------------
1871    -- Vulnerable_Complete_Task --
1872    ------------------------------
1873
1874    --  Complete the calling task
1875
1876    --  This procedure must be called with abort deferred. It should only be
1877    --  called by Complete_Task and Finalize_Global_Tasks (for the environment
1878    --  task).
1879
1880    --  The effect is similar to that of Complete_Master. Differences include
1881    --  the closing of entries here, and computation of the number of active
1882    --  dependent tasks in Complete_Master.
1883
1884    --  We don't lock Self_ID before the call to Vulnerable_Complete_Activation,
1885    --  because that does its own locking, and because we do not need the lock
1886    --  to test Self_ID.Common.Activator. That value should only be read and
1887    --  modified by Self.
1888
1889    procedure Vulnerable_Complete_Task (Self_ID : Task_Id) is
1890    begin
1891       pragma Assert
1892         (Self_ID.Deferral_Level > 0
1893           or else not System.Restrictions.Abort_Allowed);
1894       pragma Assert (Self_ID = Self);
1895       pragma Assert (Self_ID.Master_Within = Self_ID.Master_of_Task + 1
1896                        or else
1897                      Self_ID.Master_Within = Self_ID.Master_of_Task + 2);
1898       pragma Assert (Self_ID.Common.Wait_Count = 0);
1899       pragma Assert (Self_ID.Open_Accepts = null);
1900       pragma Assert (Self_ID.ATC_Nesting_Level = 1);
1901
1902       pragma Debug (Debug.Trace (Self_ID, "V_Complete_Task", 'C'));
1903
1904       if Single_Lock then
1905          Lock_RTS;
1906       end if;
1907
1908       Write_Lock (Self_ID);
1909       Self_ID.Callable := False;
1910
1911       --  In theory, Self should have no pending entry calls left on its
1912       --  call-stack. Each async. select statement should clean its own call,
1913       --  and blocking entry calls should defer abort until the calls are
1914       --  cancelled, then clean up.
1915
1916       Utilities.Cancel_Queued_Entry_Calls (Self_ID);
1917       Unlock (Self_ID);
1918
1919       if Self_ID.Common.Activator /= null then
1920          Vulnerable_Complete_Activation (Self_ID);
1921       end if;
1922
1923       if Single_Lock then
1924          Unlock_RTS;
1925       end if;
1926
1927       --  If Self_ID.Master_Within = Self_ID.Master_of_Task + 2 we may have
1928       --  dependent tasks for which we need to wait. Otherwise we just exit.
1929
1930       if Self_ID.Master_Within = Self_ID.Master_of_Task + 2 then
1931          Vulnerable_Complete_Master (Self_ID);
1932       end if;
1933    end Vulnerable_Complete_Task;
1934
1935    --------------------------
1936    -- Vulnerable_Free_Task --
1937    --------------------------
1938
1939    --  Recover all runtime system storage associated with the task T. This
1940    --  should only be called after T has terminated and will no longer be
1941    --  referenced.
1942
1943    --  For tasks created by an allocator that fails, due to an exception, it
1944    --  is called from Expunge_Unactivated_Tasks.
1945
1946    --  For tasks created by elaboration of task object declarations it is
1947    --  called from the finalization code of the Task_Wrapper procedure. It is
1948    --  also called from Ada.Unchecked_Deallocation, for objects that are or
1949    --  contain tasks.
1950
1951    procedure Vulnerable_Free_Task (T : Task_Id) is
1952    begin
1953       pragma Debug (Debug.Trace (Self, "Vulnerable_Free_Task", 'C', T));
1954
1955       if Single_Lock then
1956          Lock_RTS;
1957       end if;
1958
1959       Write_Lock (T);
1960       Initialization.Finalize_Attributes_Link.all (T);
1961       Unlock (T);
1962
1963       if Single_Lock then
1964          Unlock_RTS;
1965       end if;
1966
1967       Free_Entry_Names (T);
1968       System.Task_Primitives.Operations.Finalize_TCB (T);
1969    end Vulnerable_Free_Task;
1970
1971 --  Package elaboration code
1972
1973 begin
1974    --  Establish the Adafinal oftlink
1975
1976    --  This is not done inside the central RTS initialization routine
1977    --  to avoid with-ing this package from System.Tasking.Initialization.
1978
1979    SSL.Adafinal := Finalize_Global_Tasks'Access;
1980
1981    --  Establish soft links for subprograms that manipulate master_id's.
1982    --  This cannot be done when the RTS is initialized, because of various
1983    --  elaboration constraints.
1984
1985    SSL.Current_Master  := Stages.Current_Master'Access;
1986    SSL.Enter_Master    := Stages.Enter_Master'Access;
1987    SSL.Complete_Master := Stages.Complete_Master'Access;
1988 end System.Tasking.Stages;