OSDN Git Service

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