1------------------------------------------------------------------------------
2--                                                                          --
3--                 GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                 --
4--                                                                          --
5--         S Y S T E M . T A S K I N G . I N I T I A L I Z A T I O N        --
6--                                                                          --
7--                                  B o d y                                 --
8--                                                                          --
9--         Copyright (C) 1992-2013, 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
32pragma Style_Checks (All_Checks);
33--  Turn off subprogram alpha ordering check, since we group soft link bodies
34--  and dummy soft link bodies together separately in this unit.
35
36pragma Polling (Off);
37--  Turn polling off for this package. We don't need polling during any of the
38--  routines in this package, and more to the point, if we try to poll it can
39--  cause infinite loops.
40
41with Ada.Exceptions;
42
43with System.Task_Primitives;
44with System.Task_Primitives.Operations;
45with System.Soft_Links;
46with System.Soft_Links.Tasking;
47with System.Tasking.Debug;
48with System.Parameters;
49
50package body System.Tasking.Initialization is
51
52   package STPO renames System.Task_Primitives.Operations;
53   package SSL  renames System.Soft_Links;
54   package AE   renames Ada.Exceptions;
55
56   use Parameters;
57   use Task_Primitives.Operations;
58
59   Global_Task_Lock : aliased System.Task_Primitives.RTS_Lock;
60   --  This is a global lock; it is used to execute in mutual exclusion from
61   --  all other tasks. It is only used by Task_Lock, Task_Unlock, and
62   --  Final_Task_Unlock.
63
64   ----------------------------------------------------------------------
65   -- Tasking versions of some services needed by non-tasking programs --
66   ----------------------------------------------------------------------
67
68   procedure Abort_Defer;
69   --  NON-INLINE versions without Self_ID for soft links
70
71   procedure Abort_Undefer;
72   --  NON-INLINE versions without Self_ID for soft links
73
74   procedure Task_Lock;
75   --  Locks out other tasks. Preceding a section of code by Task_Lock and
76   --  following it by Task_Unlock creates a critical region. This is used
77   --  for ensuring that a region of non-tasking code (such as code used to
78   --  allocate memory) is tasking safe. Note that it is valid for calls to
79   --  Task_Lock/Task_Unlock to be nested, and this must work properly, i.e.
80   --  only the corresponding outer level Task_Unlock will actually unlock.
81
82   procedure Task_Unlock;
83   --  Releases lock previously set by call to Task_Lock. In the nested case,
84   --  all nested locks must be released before other tasks competing for the
85   --  tasking lock are released.
86
87   function Get_Current_Excep return SSL.EOA;
88   --  Task-safe version of SSL.Get_Current_Excep
89
90   procedure Update_Exception
91     (X : AE.Exception_Occurrence := SSL.Current_Target_Exception);
92   --  Handle exception setting and check for pending actions
93
94   function Task_Name return String;
95   --  Returns current task's name
96
97   ------------------------
98   --  Local Subprograms --
99   ------------------------
100
101   ----------------------------
102   -- Tasking Initialization --
103   ----------------------------
104
105   procedure Init_RTS;
106   --  This procedure completes the initialization of the GNARL. The first part
107   --  of the initialization is done in the body of System.Tasking. It consists
108   --  of initializing global locks, and installing tasking versions of certain
109   --  operations used by the compiler. Init_RTS is called during elaboration.
110
111   --------------------------
112   -- Change_Base_Priority --
113   --------------------------
114
115   --  Call only with abort deferred and holding Self_ID locked
116
117   procedure Change_Base_Priority (T : Task_Id) is
118   begin
119      if T.Common.Base_Priority /= T.New_Base_Priority then
120         T.Common.Base_Priority := T.New_Base_Priority;
121         Set_Priority (T, T.Common.Base_Priority);
122      end if;
123   end Change_Base_Priority;
124
125   ------------------------
126   -- Check_Abort_Status --
127   ------------------------
128
129   function Check_Abort_Status return Integer is
130      Self_ID : constant Task_Id := Self;
131   begin
132      if Self_ID /= null
133        and then Self_ID.Deferral_Level = 0
134        and then Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level
135      then
136         return 1;
137      else
138         return 0;
139      end if;
140   end Check_Abort_Status;
141
142   -----------------
143   -- Defer_Abort --
144   -----------------
145
146   procedure Defer_Abort (Self_ID : Task_Id) is
147   begin
148      if No_Abort then
149         return;
150      end if;
151
152      pragma Assert (Self_ID.Deferral_Level = 0);
153
154      --  pragma Assert
155      --    (Self_ID.Pending_ATC_Level >= Self_ID.ATC_Nesting_Level);
156
157      --  The above check has been useful in detecting mismatched defer/undefer
158      --  pairs. You may uncomment it when testing on systems that support
159      --  preemptive abort.
160
161      --  If the OS supports preemptive abort (e.g. pthread_kill), it should
162      --  have happened already. A problem is with systems that do not support
163      --  preemptive abort, and so rely on polling. On such systems we may get
164      --  false failures of the assertion, since polling for pending abort does
165      --  no occur until the abort undefer operation.
166
167      --  Even on systems that only poll for abort, the assertion may be useful
168      --  for catching missed abort completion polling points. The operations
169      --  that undefer abort poll for pending aborts. This covers most of the
170      --  places where the core Ada semantics require abort to be caught,
171      --  without any special attention. However, this generally happens on
172      --  exit from runtime system call, which means a pending abort will not
173      --  be noticed on the way into the runtime system. We considered adding a
174      --  check for pending aborts at this point, but chose not to, because of
175      --  the overhead. Instead, we searched for RTS calls where abort
176      --  completion is required and a task could go farther than Ada allows
177      --  before undeferring abort; we then modified the code to ensure the
178      --  abort would be detected.
179
180      Self_ID.Deferral_Level := Self_ID.Deferral_Level + 1;
181   end Defer_Abort;
182
183   --------------------------
184   -- Defer_Abort_Nestable --
185   --------------------------
186
187   procedure Defer_Abort_Nestable (Self_ID : Task_Id) is
188   begin
189      if No_Abort then
190         return;
191      end if;
192
193      --  The following assertion is by default disabled. See the comment in
194      --  Defer_Abort on the situations in which it may be useful to uncomment
195      --  this assertion and enable the test.
196
197      --  pragma Assert
198      --    (Self_ID.Pending_ATC_Level >= Self_ID.ATC_Nesting_Level or else
199      --     Self_ID.Deferral_Level > 0);
200
201      Self_ID.Deferral_Level := Self_ID.Deferral_Level + 1;
202   end Defer_Abort_Nestable;
203
204   -----------------
205   -- Abort_Defer --
206   -----------------
207
208   procedure Abort_Defer is
209      Self_ID : Task_Id;
210   begin
211      if No_Abort then
212         return;
213      end if;
214
215      Self_ID := STPO.Self;
216      Self_ID.Deferral_Level := Self_ID.Deferral_Level + 1;
217   end Abort_Defer;
218
219   -----------------------
220   -- Get_Current_Excep --
221   -----------------------
222
223   function Get_Current_Excep return SSL.EOA is
224   begin
225      return STPO.Self.Common.Compiler_Data.Current_Excep'Access;
226   end Get_Current_Excep;
227
228   -----------------------
229   -- Do_Pending_Action --
230   -----------------------
231
232   --  Call only when holding no locks
233
234   procedure Do_Pending_Action (Self_ID : Task_Id) is
235      use type Ada.Exceptions.Exception_Id;
236
237   begin
238      pragma Assert (Self_ID = Self and then Self_ID.Deferral_Level = 0);
239
240      --  Needs loop to recheck for pending action in case a new one occurred
241      --  while we had abort deferred below.
242
243      loop
244         --  Temporarily defer abort so that we can lock Self_ID
245
246         Self_ID.Deferral_Level := Self_ID.Deferral_Level + 1;
247
248         if Single_Lock then
249            Lock_RTS;
250         end if;
251
252         Write_Lock (Self_ID);
253         Self_ID.Pending_Action := False;
254         Unlock (Self_ID);
255
256         if Single_Lock then
257            Unlock_RTS;
258         end if;
259
260         --  Restore the original Deferral value
261
262         Self_ID.Deferral_Level := Self_ID.Deferral_Level - 1;
263
264         if not Self_ID.Pending_Action then
265            if Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level then
266               if not Self_ID.Aborting then
267                  Self_ID.Aborting := True;
268                  pragma Debug
269                    (Debug.Trace (Self_ID, "raise Abort_Signal", 'B'));
270                  raise Standard'Abort_Signal;
271
272                  pragma Assert (not Self_ID.ATC_Hack);
273
274               elsif Self_ID.ATC_Hack then
275
276                  --  The solution really belongs in the Abort_Signal handler
277                  --  for async. entry calls.  The present hack is very
278                  --  fragile. It relies that the very next point after
279                  --  Exit_One_ATC_Level at which the task becomes abortable
280                  --  will be the call to Undefer_Abort in the
281                  --  Abort_Signal handler.
282
283                  Self_ID.ATC_Hack := False;
284
285                  pragma Debug
286                    (Debug.Trace
287                     (Self_ID, "raise Abort_Signal (ATC hack)", 'B'));
288                  raise Standard'Abort_Signal;
289               end if;
290            end if;
291
292            return;
293         end if;
294      end loop;
295   end Do_Pending_Action;
296
297   -----------------------
298   -- Final_Task_Unlock --
299   -----------------------
300
301   --  This version is only for use in Terminate_Task, when the task is
302   --  relinquishing further rights to its own ATCB.
303
304   --  There is a very interesting potential race condition there, where the
305   --  old task may run concurrently with a new task that is allocated the old
306   --  tasks (now reused) ATCB. The critical thing here is to not make any
307   --  reference to the ATCB after the lock is released. See also comments on
308   --  Terminate_Task and Unlock.
309
310   procedure Final_Task_Unlock (Self_ID : Task_Id) is
311   begin
312      pragma Assert (Self_ID.Common.Global_Task_Lock_Nesting = 1);
313      Unlock (Global_Task_Lock'Access, Global_Lock => True);
314   end Final_Task_Unlock;
315
316   --------------
317   -- Init_RTS --
318   --------------
319
320   procedure Init_RTS is
321      Self_Id : Task_Id;
322   begin
323      Tasking.Initialize;
324
325      --  Terminate run time (regular vs restricted) specific initialization
326      --  of the environment task.
327
328      Self_Id := Environment_Task;
329      Self_Id.Master_of_Task := Environment_Task_Level;
330      Self_Id.Master_Within := Self_Id.Master_of_Task + 1;
331
332      for L in Self_Id.Entry_Calls'Range loop
333         Self_Id.Entry_Calls (L).Self := Self_Id;
334         Self_Id.Entry_Calls (L).Level := L;
335      end loop;
336
337      Self_Id.Awake_Count := 1;
338      Self_Id.Alive_Count := 1;
339
340      --  Normally, a task starts out with internal master nesting level one
341      --  larger than external master nesting level. It is incremented to one
342      --  by Enter_Master, which is called in the task body only if the
343      --  compiler thinks the task may have dependent tasks. There is no
344      --  corresponding call to Enter_Master for the environment task, so we
345      --  would need to increment it to 2 here. Instead, we set it to 3. By
346      --  doing this we reserve the level 2 for server tasks of the runtime
347      --  system. The environment task does not need to wait for these server
348
349      Self_Id.Master_Within := Library_Task_Level;
350
351      --  Initialize lock used to implement mutual exclusion between all tasks
352
353      Initialize_Lock (Global_Task_Lock'Access, STPO.Global_Task_Level);
354
355      --  Notify that the tasking run time has been elaborated so that
356      --  the tasking version of the soft links can be used.
357
358      if not No_Abort then
359         SSL.Abort_Defer   := Abort_Defer'Access;
360         SSL.Abort_Undefer := Abort_Undefer'Access;
361      end if;
362
363      SSL.Lock_Task          := Task_Lock'Access;
364      SSL.Unlock_Task        := Task_Unlock'Access;
365      SSL.Check_Abort_Status := Check_Abort_Status'Access;
366      SSL.Task_Name          := Task_Name'Access;
367      SSL.Update_Exception   := Update_Exception'Access;
368      SSL.Get_Current_Excep  := Get_Current_Excep'Access;
369
370      --  Initialize the tasking soft links (if not done yet) that are common
371      --  to the full and the restricted run times.
372
373      SSL.Tasking.Init_Tasking_Soft_Links;
374
375      --  Abort is deferred in a new ATCB, so we need to undefer abort at this
376      --  stage to make the environment task abortable.
377
378      Undefer_Abort (Environment_Task);
379   end Init_RTS;
380
381   ---------------------------
382   -- Locked_Abort_To_Level--
383   ---------------------------
384
385   --  Abort a task to the specified ATC nesting level.
386   --  Call this only with T locked.
387
388   --  An earlier version of this code contained a call to Wakeup. That should
389   --  not be necessary here, if Abort_Task is implemented correctly, since
390   --  Abort_Task should include the effect of Wakeup. However, the above call
391   --  was in earlier versions of this file, and at least for some targets
392   --  Abort_Task has not been doing Wakeup. It should not hurt to uncomment
393   --  the above call, until the error is corrected for all targets.
394
395   --  See extended comments in package body System.Tasking.Abort for the
396   --  overall design of the implementation of task abort.
397   --  ??? there is no such package ???
398
399   --  If the task is sleeping it will be in an abort-deferred region, and will
400   --  not have Abort_Signal raised by Abort_Task. Such an "abort deferral" is
401   --  just to protect the RTS internals, and not necessarily required to
402   --  enforce Ada semantics. Abort_Task should wake the task up and let it
403   --  decide if it wants to complete the aborted construct immediately.
404
405   --  Note that the effect of the low-level Abort_Task is not persistent.
406   --  If the target task is not blocked, this wakeup will be missed.
407
408   --  We don't bother calling Abort_Task if this task is aborting itself,
409   --  since we are inside the RTS and have abort deferred. Similarly, We don't
410   --  bother to call Abort_Task if T is terminated, since there is no need to
411   --  abort a terminated task, and it could be dangerous to try if the task
412   --  has stopped executing.
413
414   --  Note that an earlier version of this code had some false reasoning about
415   --  being able to reliably wake up a task that had suspended on a blocking
416   --  system call that does not atomically release the task's lock (e.g., UNIX
417   --  nanosleep, which we once thought could be used to implement delays).
418   --  That still left the possibility of missed wakeups.
419
420   --  We cannot safely call Vulnerable_Complete_Activation here, since that
421   --  requires locking Self_ID.Parent. The anti-deadlock lock ordering rules
422   --  would then require us to release the lock on Self_ID first, which would
423   --  create a timing window for other tasks to lock Self_ID. This is
424   --  significant for tasks that may be aborted before their execution can
425   --  enter the task body, and so they do not get a chance to call
426   --  Complete_Task. The actual work for this case is done in Terminate_Task.
427
428   procedure Locked_Abort_To_Level
429     (Self_ID : Task_Id;
430      T       : Task_Id;
431      L       : ATC_Level)
432   is
433   begin
434      if not T.Aborting and then T /= Self_ID then
435         case T.Common.State is
436            when Unactivated | Terminated =>
437               pragma Assert (False);
438               null;
439
440            when Activating | Runnable =>
441
442               --  This is needed to cancel an asynchronous protected entry
443               --  call during a requeue with abort.
444
445               T.Entry_Calls
446                 (T.ATC_Nesting_Level).Cancellation_Attempted := True;
447
448            when Interrupt_Server_Blocked_On_Event_Flag =>
449               null;
450
451            when Delay_Sleep                              |
452                 Async_Select_Sleep                       |
453                 Interrupt_Server_Idle_Sleep              |
454                 Interrupt_Server_Blocked_Interrupt_Sleep |
455                 Timer_Server_Sleep                       |
456                 AST_Server_Sleep                         =>
457               Wakeup (T, T.Common.State);
458
459            when Acceptor_Sleep | Acceptor_Delay_Sleep =>
460               T.Open_Accepts := null;
461               Wakeup (T, T.Common.State);
462
463            when Entry_Caller_Sleep  =>
464               T.Entry_Calls
465                 (T.ATC_Nesting_Level).Cancellation_Attempted := True;
466               Wakeup (T, T.Common.State);
467
468            when Activator_Sleep         |
469                 Master_Completion_Sleep |
470                 Master_Phase_2_Sleep    |
471                 Asynchronous_Hold       =>
472               null;
473         end case;
474      end if;
475
476      if T.Pending_ATC_Level > L then
477         T.Pending_ATC_Level := L;
478         T.Pending_Action := True;
479
480         if L = 0 then
481            T.Callable := False;
482         end if;
483
484         --  This prevents aborted task from accepting calls
485
486         if T.Aborting then
487
488            --  The test above is just a heuristic, to reduce wasteful
489            --  calls to Abort_Task.  We are holding T locked, and this
490            --  value will not be set to False except with T also locked,
491            --  inside Exit_One_ATC_Level, so we should not miss wakeups.
492
493            if T.Common.State = Acceptor_Sleep
494                 or else
495               T.Common.State = Acceptor_Delay_Sleep
496            then
497               T.Open_Accepts := null;
498            end if;
499
500         elsif T /= Self_ID and then
501           (T.Common.State = Runnable
502             or else T.Common.State = Interrupt_Server_Blocked_On_Event_Flag)
503
504            --  The task is blocked on a system call waiting for the
505            --  completion event. In this case Abort_Task may need to take
506            --  special action in order to succeed. Example system: VMS.
507
508         then
509            Abort_Task (T);
510         end if;
511      end if;
512   end Locked_Abort_To_Level;
513
514   --------------------------------
515   -- Remove_From_All_Tasks_List --
516   --------------------------------
517
518   procedure Remove_From_All_Tasks_List (T : Task_Id) is
519      C        : Task_Id;
520      Previous : Task_Id;
521
522   begin
523      pragma Debug
524        (Debug.Trace (Self, "Remove_From_All_Tasks_List", 'C'));
525
526      Previous := Null_Task;
527      C := All_Tasks_List;
528      while C /= Null_Task loop
529         if C = T then
530            if Previous = Null_Task then
531               All_Tasks_List := All_Tasks_List.Common.All_Tasks_Link;
532            else
533               Previous.Common.All_Tasks_Link := C.Common.All_Tasks_Link;
534            end if;
535
536            return;
537         end if;
538
539         Previous := C;
540         C := C.Common.All_Tasks_Link;
541      end loop;
542
543      pragma Assert (False);
544   end Remove_From_All_Tasks_List;
545
546   ---------------
547   -- Task_Lock --
548   ---------------
549
550   procedure Task_Lock (Self_ID : Task_Id) is
551   begin
552      Self_ID.Common.Global_Task_Lock_Nesting :=
553        Self_ID.Common.Global_Task_Lock_Nesting + 1;
554
555      if Self_ID.Common.Global_Task_Lock_Nesting = 1 then
556         Defer_Abort_Nestable (Self_ID);
557         Write_Lock (Global_Task_Lock'Access, Global_Lock => True);
558      end if;
559   end Task_Lock;
560
561   procedure Task_Lock is
562   begin
563      Task_Lock (STPO.Self);
564   end Task_Lock;
565
566   ---------------
567   -- Task_Name --
568   ---------------
569
570   function Task_Name return String is
571      Self_Id : constant Task_Id := STPO.Self;
572   begin
573      return Self_Id.Common.Task_Image (1 .. Self_Id.Common.Task_Image_Len);
574   end Task_Name;
575
576   -----------------
577   -- Task_Unlock --
578   -----------------
579
580   procedure Task_Unlock (Self_ID : Task_Id) is
581   begin
582      pragma Assert (Self_ID.Common.Global_Task_Lock_Nesting > 0);
583      Self_ID.Common.Global_Task_Lock_Nesting :=
584        Self_ID.Common.Global_Task_Lock_Nesting - 1;
585
586      if Self_ID.Common.Global_Task_Lock_Nesting = 0 then
587         Unlock (Global_Task_Lock'Access, Global_Lock => True);
588         Undefer_Abort_Nestable (Self_ID);
589      end if;
590   end Task_Unlock;
591
592   procedure Task_Unlock is
593   begin
594      Task_Unlock (STPO.Self);
595   end Task_Unlock;
596
597   -------------------
598   -- Undefer_Abort --
599   -------------------
600
601   --  Precondition : Self does not hold any locks
602
603   --  Undefer_Abort is called on any abort completion point (aka.
604   --  synchronization point). It performs the following actions if they
605   --  are pending: (1) change the base priority, (2) abort the task.
606
607   --  The priority change has to occur before abort. Otherwise, it would
608   --  take effect no earlier than the next abort completion point.
609
610   procedure Undefer_Abort (Self_ID : Task_Id) is
611   begin
612      if No_Abort then
613         return;
614      end if;
615
616      pragma Assert (Self_ID.Deferral_Level = 1);
617
618      Self_ID.Deferral_Level := Self_ID.Deferral_Level - 1;
619
620      if Self_ID.Deferral_Level = 0 then
621         pragma Assert (Check_No_Locks (Self_ID));
622
623         if Self_ID.Pending_Action then
624            Do_Pending_Action (Self_ID);
625         end if;
626      end if;
627   end Undefer_Abort;
628
629   ----------------------------
630   -- Undefer_Abort_Nestable --
631   ----------------------------
632
633   --  An earlier version would re-defer abort if an abort is in progress.
634   --  Then, we modified the effect of the raise statement so that it defers
635   --  abort until control reaches a handler. That was done to prevent
636   --  "skipping over" a handler if another asynchronous abort occurs during
637   --  the propagation of the abort to the handler.
638
639   --  There has been talk of reversing that decision, based on a newer
640   --  implementation of exception propagation. Care must be taken to evaluate
641   --  how such a change would interact with the above code and all the places
642   --  where abort-deferral is used to bridge over critical transitions, such
643   --  as entry to the scope of a region with a finalizer and entry into the
644   --  body of an accept-procedure.
645
646   procedure Undefer_Abort_Nestable (Self_ID : Task_Id) is
647   begin
648      if No_Abort then
649         return;
650      end if;
651
652      pragma Assert (Self_ID.Deferral_Level > 0);
653
654      Self_ID.Deferral_Level := Self_ID.Deferral_Level - 1;
655
656      if Self_ID.Deferral_Level = 0 then
657
658         pragma Assert (Check_No_Locks (Self_ID));
659
660         if Self_ID.Pending_Action then
661            Do_Pending_Action (Self_ID);
662         end if;
663      end if;
664   end Undefer_Abort_Nestable;
665
666   -------------------
667   -- Abort_Undefer --
668   -------------------
669
670   procedure Abort_Undefer is
671      Self_ID : Task_Id;
672   begin
673      if No_Abort then
674         return;
675      end if;
676
677      Self_ID := STPO.Self;
678
679      if Self_ID.Deferral_Level = 0 then
680
681         --  In case there are different views on whether Abort is supported
682         --  between the expander and the run time, we may end up with
683         --  Self_ID.Deferral_Level being equal to zero, when called from
684         --  the procedure created by the expander that corresponds to a
685         --  task body. In this case, there's nothing to be done.
686
687         --  See related code in System.Tasking.Stages.Create_Task resetting
688         --  Deferral_Level when System.Restrictions.Abort_Allowed is False.
689
690         return;
691      end if;
692
693      pragma Assert (Self_ID.Deferral_Level > 0);
694      Self_ID.Deferral_Level := Self_ID.Deferral_Level - 1;
695
696      if Self_ID.Deferral_Level = 0 then
697         pragma Assert (Check_No_Locks (Self_ID));
698
699         if Self_ID.Pending_Action then
700            Do_Pending_Action (Self_ID);
701         end if;
702      end if;
703   end Abort_Undefer;
704
705   ----------------------
706   -- Update_Exception --
707   ----------------------
708
709   --  Call only when holding no locks
710
711   procedure Update_Exception
712     (X : AE.Exception_Occurrence := SSL.Current_Target_Exception)
713   is
714      Self_Id : constant Task_Id := Self;
715      use Ada.Exceptions;
716
717   begin
718      Save_Occurrence (Self_Id.Common.Compiler_Data.Current_Excep, X);
719
720      if Self_Id.Deferral_Level = 0 then
721         if Self_Id.Pending_Action then
722            Self_Id.Pending_Action := False;
723            Self_Id.Deferral_Level := Self_Id.Deferral_Level + 1;
724
725            if Single_Lock then
726               Lock_RTS;
727            end if;
728
729            Write_Lock (Self_Id);
730            Self_Id.Pending_Action := False;
731            Unlock (Self_Id);
732
733            if Single_Lock then
734               Unlock_RTS;
735            end if;
736
737            Self_Id.Deferral_Level := Self_Id.Deferral_Level - 1;
738
739            if Self_Id.Pending_ATC_Level < Self_Id.ATC_Nesting_Level then
740               if not Self_Id.Aborting then
741                  Self_Id.Aborting := True;
742                  raise Standard'Abort_Signal;
743               end if;
744            end if;
745         end if;
746      end if;
747   end Update_Exception;
748
749   --------------------------
750   -- Wakeup_Entry_Caller --
751   --------------------------
752
753   --  This is called at the end of service of an entry call, to abort the
754   --  caller if he is in an abortable part, and to wake up the caller if it
755   --  is on Entry_Caller_Sleep. It assumes that the call is already off-queue.
756
757   --  (This enforces the rule that a task must be off-queue if its state is
758   --  Done or Cancelled.) Call it holding the lock of Entry_Call.Self.
759
760   --  Timed_Call or Simple_Call:
761   --    The caller is waiting on Entry_Caller_Sleep, in
762   --    Wait_For_Completion, or Wait_For_Completion_With_Timeout.
763
764   --  Conditional_Call:
765   --    The caller might be in Wait_For_Completion,
766   --    waiting for a rendezvous (possibly requeued without abort)
767   --    to complete.
768
769   --  Asynchronous_Call:
770   --    The caller may be executing in the abortable part o
771   --    an async. select, or on a time delay,
772   --    if Entry_Call.State >= Was_Abortable.
773
774   procedure Wakeup_Entry_Caller
775     (Self_ID    : Task_Id;
776      Entry_Call : Entry_Call_Link;
777      New_State  : Entry_Call_State)
778   is
779      Caller : constant Task_Id := Entry_Call.Self;
780
781   begin
782      pragma Debug (Debug.Trace
783        (Self_ID, "Wakeup_Entry_Caller", 'E', Caller));
784      pragma Assert (New_State = Done or else New_State = Cancelled);
785
786      pragma Assert (Caller.Common.State /= Unactivated);
787
788      Entry_Call.State := New_State;
789
790      if Entry_Call.Mode = Asynchronous_Call then
791
792         --  Abort the caller in his abortable part, but do so only if call has
793         --  been queued abortably.
794
795         if Entry_Call.State >= Was_Abortable or else New_State = Done then
796            Locked_Abort_To_Level (Self_ID, Caller, Entry_Call.Level - 1);
797         end if;
798
799      elsif Caller.Common.State = Entry_Caller_Sleep then
800         Wakeup (Caller, Entry_Caller_Sleep);
801      end if;
802   end Wakeup_Entry_Caller;
803
804   -----------------------
805   -- Soft-Link Dummies --
806   -----------------------
807
808   --  These are dummies for subprograms that are only needed by certain
809   --  optional run-time system packages. If they are needed, the soft links
810   --  will be redirected to the real subprogram by elaboration of the
811   --  subprogram body where the real subprogram is declared.
812
813   procedure Finalize_Attributes (T : Task_Id) is
814      pragma Unreferenced (T);
815   begin
816      null;
817   end Finalize_Attributes;
818
819   procedure Initialize_Attributes (T : Task_Id) is
820      pragma Unreferenced (T);
821   begin
822      null;
823   end Initialize_Attributes;
824
825begin
826   Init_RTS;
827end System.Tasking.Initialization;
828