home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / adav313.zip / gnat-3_13p-os2-bin-20010916.zip / emx / gnatlib / s-tarest.adb < prev    next >
Text File  |  2000-07-19  |  25KB  |  699 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS               --
  4. --                                                                          --
  5. --     S Y S T E M . T A S K I N G . R E S T R I C T E D . S T A G E S      --
  6. --                                                                          --
  7. --                                  B o d y                                 --
  8. --                                                                          --
  9. --                             $Revision: 1.8 $
  10. --                                                                          --
  11. --            Copyright (C) 1991-1999 Florida State University              --
  12. --                                                                          --
  13. -- GNARL is free software; you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNARL; see file COPYING.  If not, write --
  21. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  22. -- MA 02111-1307, USA.                                                      --
  23. --                                                                          --
  24. -- As a special exception,  if other files  instantiate  generics from this --
  25. -- unit, or you link  this unit with other files  to produce an executable, --
  26. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  27. -- covered  by the  GNU  General  Public  License.  This exception does not --
  28. -- however invalidate  any other reasons why  the executable file  might be --
  29. -- covered by the  GNU Public License.                                      --
  30. --                                                                          --
  31. -- GNARL was developed by the GNARL team at Florida State University. It is --
  32. -- now maintained by Ada Core Technologies Inc. in cooperation with Florida --
  33. -- State University (http://www.gnat.com).                                  --
  34. --                                                                          --
  35. ------------------------------------------------------------------------------
  36.  
  37. --  This is a simplified version of the System.Tasking.Stages package,
  38. --  intended to be used in a restricted run time.
  39.  
  40. --  This package represents the high level tasking interface used by the
  41. --  compiler to expand Ada 95 tasking constructs into simpler run time calls.
  42.  
  43. pragma Polling (Off);
  44. --  Turn off polling, we do not want ATC polling to take place during
  45. --  tasking operations. It causes infinite loops and other problems.
  46.  
  47. with System.Parameters;
  48. --  used for Size_Type
  49.  
  50. with System.Task_Info;
  51. --  used for Task_Info_Type
  52. --           Task_Image_Type
  53.  
  54. with System.Task_Primitives.Operations;
  55. --  used for Enter_Task
  56. --           Write_Lock
  57. --           Unlock
  58. --           Wakeup
  59. --           Get_Priority
  60. --           Lock/Unlock_All_Tasks_List
  61.  
  62. with System.Soft_Links;
  63. --  used for the non-tasking routines (*_NT) that refer to global data.
  64. --  They are needed here before the tasking run time has been elaborated.
  65. --  used for Create_TSD
  66. --  This package also provides initialization routines for task specific data.
  67. --  The GNARL must call these to be sure that all non-tasking
  68. --  Ada constructs will work.
  69.  
  70. with System.Secondary_Stack;
  71. --  used for SS_Init;
  72.  
  73. with System.Storage_Elements;
  74. --  used for Storage_Array;
  75.  
  76. package body System.Tasking.Restricted.Stages is
  77.  
  78.    package STPO renames System.Task_Primitives.Operations;
  79.    package SSL  renames System.Soft_Links;
  80.    package SSE  renames System.Storage_Elements;
  81.    package SST  renames System.Secondary_Stack;
  82.  
  83.    use System.Task_Primitives;
  84.    use System.Task_Primitives.Operations;
  85.    use System.Task_Info;
  86.  
  87.    Global_Task_Lock : aliased System.Task_Primitives.RTS_Lock;
  88.    --  This is a global lock; it is used to execute in mutual exclusion
  89.    --  from all other tasks.  It is only used by Task_Lock,
  90.    --  Task_Unlock, and Final_Task_Unlock.
  91.  
  92.    -----------------------------------------------------------------
  93.    -- Tasking versions of services needed by non-tasking programs --
  94.    -----------------------------------------------------------------
  95.  
  96.    procedure Task_Lock;
  97.    --  Locks out other tasks. Preceding a section of code by Task_Lock and
  98.    --  following it by Task_Unlock creates a critical region. This is used
  99.    --  for ensuring that a region of non-tasking code (such as code used to
  100.    --  allocate memory) is tasking safe. Note that it is valid for calls to
  101.    --  Task_Lock/Task_Unlock to be nested, and this must work properly, i.e.
  102.    --  only the corresponding outer level Task_Unlock will actually unlock.
  103.  
  104.    procedure Task_Unlock;
  105.    --  Releases lock previously set by call to Task_Lock. In the nested case,
  106.    --  all nested locks must be released before other tasks competing for the
  107.    --  tasking lock are released.
  108.  
  109.    function Get_Jmpbuf_Address return Address;
  110.    procedure Set_Jmpbuf_Address (Addr : Address);
  111.  
  112.    function Get_Sec_Stack_Addr return Address;
  113.    procedure Set_Sec_Stack_Addr (Addr : Address);
  114.  
  115.    function Get_Exc_Stack_Addr return Address;
  116.    --  Get the exception stack for the current task
  117.  
  118.    procedure Set_Exc_Stack_Addr (Self_ID : Address; Addr : Address);
  119.    --  Self_ID is the Task_ID of the task that gets the exception stack.
  120.    --  For Self_ID = Null_Address, the current task gets the exception stack.
  121.  
  122.    function  Get_Machine_State_Addr return Address;
  123.    procedure Set_Machine_State_Addr (Addr : Address);
  124.  
  125.    function Get_Current_Excep return SSL.EOA;
  126.  
  127.    procedure Timed_Delay_T (Time : Duration; Mode : Integer);
  128.  
  129.    ------------------------
  130.    --  Local Subprograms --
  131.    ------------------------
  132.  
  133.    procedure Task_Wrapper (Self_ID : Task_ID);
  134.    --  This is the procedure that is called by the GNULL from the
  135.    --  new context when a task is created. It waits for activation
  136.    --  and then calls the task body procedure. When the task body
  137.    --  procedure completes, it terminates the task.
  138.  
  139.    procedure Terminate_Task (Self_ID : Task_ID);
  140.    --  Terminate the calling task.
  141.    --  This should only be called by the Task_Wrapper procedure.
  142.  
  143.    procedure Vulnerable_Complete_Activation (Self_ID : Task_ID);
  144.    --  Signal to Self_ID's activator that Self_ID has
  145.    --  completed activation.
  146.  
  147.    ---------------
  148.    -- Task_Lock --
  149.    ---------------
  150.  
  151.    procedure Task_Lock is
  152.    begin
  153.       STPO.Write_Lock (Global_Task_Lock'Access);
  154.    end Task_Lock;
  155.  
  156.    -----------------
  157.    -- Task_Unlock --
  158.    -----------------
  159.  
  160.    procedure Task_Unlock is
  161.    begin
  162.       STPO.Unlock (Global_Task_Lock'Access);
  163.    end Task_Unlock;
  164.  
  165.    -----------------------
  166.    --  Soft-Link Bodies --
  167.    -----------------------
  168.  
  169.    function Get_Jmpbuf_Address return  Address is
  170.       Me : constant Task_ID := STPO.Self;
  171.  
  172.    begin
  173.       return Me.Common.Compiler_Data.Jmpbuf_Address;
  174.    end Get_Jmpbuf_Address;
  175.  
  176.    procedure Set_Jmpbuf_Address (Addr : Address) is
  177.       Me : constant Task_ID := STPO.Self;
  178.  
  179.    begin
  180.       Me.Common.Compiler_Data.Jmpbuf_Address := Addr;
  181.    end Set_Jmpbuf_Address;
  182.  
  183.    function Get_Sec_Stack_Addr return  Address is
  184.       Me : constant Task_ID := STPO.Self;
  185.  
  186.    begin
  187.       return Me.Common.Compiler_Data.Sec_Stack_Addr;
  188.    end Get_Sec_Stack_Addr;
  189.  
  190.    procedure Set_Sec_Stack_Addr (Addr : Address) is
  191.       Me : constant Task_ID := STPO.Self;
  192.  
  193.    begin
  194.       Me.Common.Compiler_Data.Sec_Stack_Addr := Addr;
  195.    end Set_Sec_Stack_Addr;
  196.  
  197.    function Get_Exc_Stack_Addr return Address is
  198.       Me : constant Task_ID := STPO.Self;
  199.  
  200.    begin
  201.       return Me.Common.Compiler_Data.Exc_Stack_Addr;
  202.    end Get_Exc_Stack_Addr;
  203.  
  204.    procedure Set_Exc_Stack_Addr (Self_ID : Address; Addr : Address) is
  205.       Me : Task_ID := To_Task_Id (Self_ID);
  206.  
  207.    begin
  208.       if Me = Null_Task then
  209.          Me := STPO.Self;
  210.       end if;
  211.  
  212.       Me.Common.Compiler_Data.Exc_Stack_Addr := Addr;
  213.    end Set_Exc_Stack_Addr;
  214.  
  215.    function Get_Machine_State_Addr return Address is
  216.       Me : constant Task_ID := STPO.Self;
  217.  
  218.    begin
  219.       return Me.Common.Compiler_Data.Machine_State_Addr;
  220.    end Get_Machine_State_Addr;
  221.  
  222.    procedure Set_Machine_State_Addr (Addr : Address) is
  223.       Me : constant Task_ID := STPO.Self;
  224.  
  225.    begin
  226.       Me.Common.Compiler_Data.Machine_State_Addr := Addr;
  227.    end Set_Machine_State_Addr;
  228.  
  229.    function Get_Current_Excep return SSL.EOA is
  230.       Me : constant Task_ID := STPO.Self;
  231.  
  232.    begin
  233.       return Me.Common.Compiler_Data.Current_Excep'Access;
  234.    end Get_Current_Excep;
  235.  
  236.    procedure Timed_Delay_T (Time : Duration; Mode : Integer) is
  237.    begin
  238.       STPO.Timed_Delay (STPO.Self, Time, Mode);
  239.    end Timed_Delay_T;
  240.  
  241.    ------------------
  242.    -- Task_Wrapper --
  243.    ------------------
  244.  
  245.    --  The task wrapper is a procedure that is called first for each task
  246.    --  task body, and which in turn calls the compiler-generated task body
  247.    --  procedure. The wrapper's main job is to do initialization for the task.
  248.    --  It also has some locally declared objects that server as per-task local
  249.    --  data. Task finalization is done by Complete_Task, which is called from
  250.    --  an at-end handler that the compiler generates.
  251.  
  252.    --  The variable ID in the task wrapper is used to implement the Self
  253.    --  function on targets where there is a fast way to find the stack base
  254.    --  of the current thread, since it should be at a fixed offset from the
  255.    --  stack base.
  256.  
  257.    --  The variable Magic_Number is also used in such implementations
  258.    --  of Self, to check whether the current task is an Ada task, as
  259.    --  compared to other-language threads.
  260.  
  261.    --  Both act as constants, once initialized, but need to be marked as
  262.    --  volatile or aliased to prevent the compiler from optimizing away the
  263.    --  storage. See System.Task_Primitives.Operations.Self for more info.
  264.  
  265.    procedure Task_Wrapper (Self_ID : Task_ID) is
  266.       ID : Task_ID := Self_ID;
  267.       pragma Volatile (ID);
  268.  
  269.       --  Do not delete this variable.
  270.       --  In some targets, we need this variable to implement a fast Self.
  271.  
  272.       use type System.Parameters.Size_Type;
  273.       Secondary_Stack : aliased SSE.Storage_Array
  274.         (1 .. SSE.Storage_Offset
  275.           (ID.Common.Stack_Size * Parameters.Sec_Stack_Ratio / 100));
  276.       Secondary_Stack_Address : System.Address := Secondary_Stack'Address;
  277.  
  278.    begin
  279.       if not Parameters.Sec_Stack_Dynamic then
  280.          ID.Common.Compiler_Data.Sec_Stack_Addr := Secondary_Stack'Address;
  281.          SST.SS_Init (Secondary_Stack_Address, Integer (Secondary_Stack'Last));
  282.       end if;
  283.  
  284.       --  Set the guard page at the bottom of the stack.
  285.       --  The call to unprotect the page is done in Terminate_Task
  286.  
  287.       Stack_Guard (Self_ID, True);
  288.  
  289.       --  Initialize low-level TCB components, that
  290.       --  cannot be initialized by the creator.
  291.  
  292.       Enter_Task (Self_ID);
  293.  
  294.       --  We lock All_Tasks_L to wait for activator to finish activating
  295.       --  the rest of the chain, so that everyone in the chain comes out
  296.       --  in priority order.
  297.       --  This also protects the value of Self_ID.Activator.Wait_Count
  298.  
  299.       Lock_All_Tasks_List;
  300.       Unlock_All_Tasks_List;
  301.  
  302.       begin
  303.          --  We are separating the following portion of the code in order to
  304.          --  place the exception handlers in a different block.
  305.          --  In this way we do not call Set_Jmpbuf_Address (which needs
  306.          --  Self) before we set Self in Enter_Task
  307.  
  308.          --  Call the task body procedure.
  309.  
  310.          Self_ID.Common.Task_Entry_Point (Self_ID.Common.Task_Arg);
  311.          Terminate_Task (Self_ID);
  312.  
  313.       exception
  314.          when others =>
  315.             Terminate_Task (Self_ID);
  316.       end;
  317.    end Task_Wrapper;
  318.  
  319.    -------------------------
  320.    --  Restricted GNARLI  --
  321.    -------------------------
  322.  
  323.    ----------------------------
  324.    -- Create_Restricted_Task --
  325.    ----------------------------
  326.  
  327.    procedure Create_Restricted_Task
  328.      (Priority      : Integer;
  329.       Size          : System.Parameters.Size_Type;
  330.       Task_Info     : System.Task_Info.Task_Info_Type;
  331.       State         : Task_Procedure_Access;
  332.       Discriminants : System.Address;
  333.       Elaborated    : Access_Boolean;
  334.       Chain         : in out Activation_Chain;
  335.       Task_Image    : System.Task_Info.Task_Image_Type;
  336.       Created_Task  : out Task_ID)
  337.    is
  338.       T             : Task_ID;
  339.       Self_ID       : constant Task_ID := STPO.Self;
  340.       Base_Priority : System.Any_Priority;
  341.       Success       : Boolean;
  342.  
  343.    begin
  344.       if Priority = Unspecified_Priority then
  345.          Base_Priority := Self_ID.Common.Base_Priority;
  346.       else
  347.          Base_Priority := System.Any_Priority (Priority);
  348.       end if;
  349.  
  350.       begin
  351.          T := New_ATCB (0);
  352.       exception
  353.          when others =>
  354.             raise Storage_Error;
  355.       end;
  356.  
  357.       --  All_Tasks_L is used by Abort_Dependents and Abort_Tasks.
  358.       --  Up to this point, it is possible that we may be part of
  359.       --  a family of tasks that is being aborted.
  360.  
  361.       Lock_All_Tasks_List;
  362.       Write_Lock (Self_ID);
  363.  
  364.       --  With no task hierarchy, the parent of all non-Environment tasks that
  365.       --  are created must be the Environment task
  366.  
  367.       Initialize_ATCB
  368.         (Self_ID, State, Discriminants, Self_ID, Elaborated, Base_Priority,
  369.          Task_Info, Size, Library_Task_Level, T, Success);
  370.  
  371.       --  If we do our job right then there should never be any failures,
  372.       --  which was probably said about the Titanic; so just to be safe,
  373.       --  let's retain this code for now
  374.  
  375.       if not Success then
  376.          Unlock (Self_ID);
  377.          Unlock_All_Tasks_List;
  378.          raise Storage_Error;
  379.       end if;
  380.  
  381.       T.Common.Task_Image := Task_Image;
  382.       Unlock (Self_ID);
  383.       Unlock_All_Tasks_List;
  384.  
  385.       --  Create TSD as early as possible in the creation of a task, since it
  386.       --  may be used by the operation of Ada code within the task.
  387.  
  388.       SSL.Create_TSD (T.Common.Compiler_Data);
  389.       T.Common.Activation_Link := Chain.T_ID;
  390.       Chain.T_ID := T;
  391.       Created_Task := T;
  392.    end Create_Restricted_Task;
  393.  
  394.    -------------------------------
  395.    -- Activate_Restricted_Tasks --
  396.    -------------------------------
  397.  
  398.    --  Note that locks of activator and activated task are both locked
  399.    --  here. This is necessary because C.State and Self.Wait_Count
  400.    --  have to be synchronized. This is safe from deadlock because
  401.    --  the activator is always created before the activated task.
  402.    --  That satisfies our in-order-of-creation ATCB locking policy.
  403.  
  404.    --  At one point, we may also lock the parent, if the parent is
  405.    --  different from the activator.  That is also consistent with the
  406.    --  lock ordering policy, since the activator cannot be created
  407.    --  before the parent.
  408.  
  409.    --  Since we are holding both the activator's lock, and Task_Wrapper
  410.    --  locks that before it does anything more than initialize the
  411.    --  low-level ATCB components, it should be safe to wait to update
  412.    --  the counts until we see that the thread creation is successful.
  413.  
  414.    procedure Activate_Restricted_Tasks
  415.      (Chain_Access : Activation_Chain_Access)
  416.    is
  417.       Self_ID        : constant Task_ID := STPO.Self;
  418.       P              : Task_ID;
  419.       C              : Task_ID;
  420.       Activate_Prio  : System.Any_Priority;
  421.       Success        : Boolean;
  422.  
  423.    begin
  424.       pragma Assert (Self_ID.Common.Wait_Count = 0);
  425.  
  426.       --  Lock All_Tasks_L, to prevent activated tasks
  427.       --  from racing ahead before we finish activating the chain.
  428.  
  429.       --  ?????
  430.       --  Is there some less heavy-handed way?
  431.       --  In an earlier version, we used the activator's lock here,
  432.       --  but that violated the locking order rule when we had
  433.       --  to lock the parent later.
  434.  
  435.       Lock_All_Tasks_List;
  436.  
  437.       --  Activate all the tasks in the chain.
  438.       --  Creation of the thread of control was deferred until
  439.       --  activation. So create it now.
  440.  
  441.       C := Chain_Access.T_ID;
  442.  
  443.       while C /= null loop
  444.          if C.Common.State /= Terminated then
  445.             pragma Assert (C.Common.State = Unactivated);
  446.  
  447.             P := C.Common.Parent;
  448.             Write_Lock (P);
  449.             Write_Lock (C);
  450.  
  451.             if C.Common.Base_Priority < Get_Priority (Self_ID) then
  452.                Activate_Prio := Get_Priority (Self_ID);
  453.             else
  454.                Activate_Prio := C.Common.Base_Priority;
  455.             end if;
  456.  
  457.             STPO.Create_Task
  458.               (C, Task_Wrapper'Address, C.Common.Stack_Size,
  459.                Activate_Prio, Success);
  460.  
  461.             --  There would be a race between the created task and
  462.             --  the creator to do the following initialization,
  463.             --  if we did not have a Lock/Unlock_All_Tasks_List pair
  464.             --  in the task wrapper, to prevent it from racing ahead.
  465.  
  466.             if Success then
  467.                C.Common.State := Runnable;
  468.  
  469.             else
  470.                --  No need to set Awake_Count, State, etc. here since the loop
  471.                --  below will do that for any Unactivated tasks.
  472.  
  473.                Self_ID.Common.Activation_Failed := True;
  474.             end if;
  475.  
  476.             Unlock (C);
  477.             Unlock (P);
  478.          end if;
  479.  
  480.          C := C.Common.Activation_Link;
  481.       end loop;
  482.  
  483.       Unlock_All_Tasks_List;
  484.  
  485.       --  Close the entries of any tasks that failed thread creation,
  486.       --  and count those that have not finished activation.
  487.  
  488.       Write_Lock (Self_ID);
  489.       Self_ID.Common.State := Activator_Sleep;
  490.  
  491.       C := Chain_Access.T_ID;
  492.  
  493.       while C /= null loop
  494.          Write_Lock (C);
  495.  
  496.          if C.Common.State = Unactivated then
  497.             C.Common.Activator := null;
  498.             C.Common.State := Terminated;
  499.  
  500.          elsif C.Common.Activator /= null then
  501.             Self_ID.Common.Wait_Count := Self_ID.Common.Wait_Count + 1;
  502.          end if;
  503.  
  504.          Unlock (C);
  505.          P := C.Common.Activation_Link;
  506.          C.Common.Activation_Link := null;
  507.          C := P;
  508.       end loop;
  509.  
  510.       --  Wait for the activated tasks to complete activation.
  511.       --  It is unsafe to abort any of these tasks until the count goes to
  512.       --  zero.
  513.  
  514.       loop
  515.          exit when Self_ID.Common.Wait_Count = 0;
  516.          Sleep (Self_ID, Activator_Sleep);
  517.       end loop;
  518.  
  519.       Self_ID.Common.State := Runnable;
  520.       Unlock (Self_ID);
  521.  
  522.       --  Remove the tasks from the chain.
  523.  
  524.       Chain_Access.T_ID := null;
  525.  
  526.       if Self_ID.Common.Activation_Failed then
  527.          Self_ID.Common.Activation_Failed := False;
  528.          raise Tasking_Error;
  529.       end if;
  530.    end Activate_Restricted_Tasks;
  531.  
  532.    ------------------------------------
  533.    -- Complete_Restricted_Activation --
  534.    ------------------------------------
  535.  
  536.    procedure Complete_Restricted_Activation is
  537.    begin
  538.       Vulnerable_Complete_Activation (STPO.Self);
  539.    end Complete_Restricted_Activation;
  540.  
  541.    ------------------------------------
  542.    -- Vulnerable_Complete_Activation --
  543.    ------------------------------------
  544.  
  545.    --  As in several other places, the locks of the activator and activated
  546.    --  task are both locked here. This follows our deadlock prevention lock
  547.    --  ordering policy, since the activated task must be created after the
  548.    --  activator.
  549.  
  550.    procedure Vulnerable_Complete_Activation (Self_ID : Task_ID) is
  551.       Activator : Task_ID := Self_ID.Common.Activator;
  552.  
  553.    begin
  554.       Write_Lock (Activator);
  555.       Write_Lock (Self_ID);
  556.  
  557.       pragma Assert (Self_ID.Common.Activator /= null);
  558.  
  559.       --  Remove dangling reference to Activator,
  560.       --  since a task may outlive its activator.
  561.  
  562.       Self_ID.Common.Activator := null;
  563.  
  564.       --  Wake up the activator, if it is waiting for a chain
  565.       --  of tasks to activate, and we are the last in the chain
  566.       --  to complete activation
  567.  
  568.       if Activator.Common.State = Activator_Sleep then
  569.          Activator.Common.Wait_Count := Activator.Common.Wait_Count - 1;
  570.  
  571.          if Activator.Common.Wait_Count = 0 then
  572.             Wakeup (Activator, Activator_Sleep);
  573.          end if;
  574.       end if;
  575.  
  576.       --  The activator raises a Tasking_Error if any task
  577.       --  it is activating is completed before the activation is
  578.       --  done. However, if the reason for the task completion is
  579.       --  an abortion, we do not raise an exception. ARM 9.2(5).
  580.  
  581.       if Self_ID.Common.State = Terminated then
  582.          Activator.Common.Activation_Failed := True;
  583.       end if;
  584.  
  585.       Unlock (Self_ID);
  586.  
  587.       --  After the activation, active priority should be the same
  588.       --  as base priority.   We must unlock the Activator first,
  589.       --  though, since it should not wait if we have lower priority.
  590.  
  591.       Unlock (Activator);
  592.  
  593.       if Get_Priority (Self_ID) /= Self_ID.Common.Base_Priority then
  594.          Write_Lock (Self_ID);
  595.          Set_Priority (Self_ID, Self_ID.Common.Base_Priority);
  596.          Unlock (Self_ID);
  597.       end if;
  598.    end Vulnerable_Complete_Activation;
  599.  
  600.    ------------------------------
  601.    -- Complete_Restricted_Task --
  602.    ------------------------------
  603.  
  604.    procedure Complete_Restricted_Task is
  605.       Self_ID  : constant Task_ID := STPO.Self;
  606.  
  607.    begin
  608.       Self_ID.Common.State := Terminated;
  609.  
  610.       if Self_ID.Common.Activator /= null then
  611.          Vulnerable_Complete_Activation (Self_ID);
  612.       end if;
  613.    end Complete_Restricted_Task;
  614.  
  615.    --------------------
  616.    -- Terminate_Task --
  617.    --------------------
  618.  
  619.    procedure Terminate_Task (Self_ID : Task_ID) is
  620.    begin
  621.       pragma Assert (Self_ID.Common.Activator = null);
  622.       pragma Assert (Self_ID.Common.Parent = STPO.Environment_Task);
  623.  
  624.       --  Unprotect the guard page if needed.
  625.  
  626.       Stack_Guard (Self_ID, False);
  627.  
  628.       Self_ID.Common.State := Terminated;
  629.  
  630.       --  WARNING
  631.       --  past this point, this thread must assume that the ATCB
  632.       --  has been deallocated. It should not be accessed again.
  633.  
  634.       STPO.Exit_Task;
  635.    end Terminate_Task;
  636.  
  637.    ---------------------------
  638.    -- Restricted_Terminated --
  639.    ---------------------------
  640.  
  641.    function Restricted_Terminated (T : Task_ID) return Boolean is
  642.    begin
  643.       return T.Common.State = Terminated;
  644.    end Restricted_Terminated;
  645.  
  646.    ---------------------------
  647.    -- Finalize_Global_Tasks --
  648.    ---------------------------
  649.  
  650.    --  This is needed to support the compiler interface; it will only be called
  651.    --  by the Environment task. Instead, it will cause the Environment to block
  652.    --  forever, since none of the dependent tasks are expected to terminate
  653.  
  654.    procedure Finalize_Global_Tasks is
  655.       Self_ID : constant Task_ID := STPO.Self;
  656.  
  657.    begin
  658.       pragma Assert (Self_ID = STPO.Environment_Task);
  659.  
  660.       Write_Lock (Self_ID);
  661.       Sleep (Self_ID, Master_Completion_Sleep);
  662.       Unlock (Self_ID);
  663.  
  664.       --  Should never return from Master Completion Sleep
  665.  
  666.       raise Program_Error;
  667.    end Finalize_Global_Tasks;
  668.  
  669. begin
  670.    --  Initialize lock used to implement mutual exclusion between all tasks
  671.  
  672.    STPO.Initialize_Lock (Global_Task_Lock'Access, STPO.Global_Task_Level);
  673.  
  674.    --  Notify that the tasking run time has been elaborated so that
  675.    --  the tasking version of the soft links can be used.
  676.  
  677.    SSL.Lock_Task              := Task_Lock'Access;
  678.    SSL.Unlock_Task            := Task_Unlock'Access;
  679.    SSL.Get_Jmpbuf_Address     := Get_Jmpbuf_Address'Access;
  680.    SSL.Set_Jmpbuf_Address     := Set_Jmpbuf_Address'Access;
  681.    SSL.Get_Sec_Stack_Addr     := Get_Sec_Stack_Addr'Access;
  682.    SSL.Set_Sec_Stack_Addr     := Set_Sec_Stack_Addr'Access;
  683.    SSL.Get_Exc_Stack_Addr     := Get_Exc_Stack_Addr'Access;
  684.    SSL.Set_Exc_Stack_Addr     := Set_Exc_Stack_Addr'Access;
  685.    SSL.Get_Machine_State_Addr := Get_Machine_State_Addr'Access;
  686.    SSL.Set_Machine_State_Addr := Set_Machine_State_Addr'Access;
  687.    SSL.Get_Current_Excep      := Get_Current_Excep'Access;
  688.    SSL.Clock                  := STPO.Clock'Access;
  689.    SSL.Timed_Delay            := Timed_Delay_T'Access;
  690.  
  691.    --  No need to create a new Secondary Stack, since we will use the
  692.    --  default one created in s-secsta.adb
  693.  
  694.    SSL.Set_Sec_Stack_Addr     (SSL.Get_Sec_Stack_Addr_NT);
  695.    SSL.Set_Exc_Stack_Addr     (Null_Address, SSL.Get_Exc_Stack_Addr_NT);
  696.    SSL.Set_Jmpbuf_Address     (SSL.Get_Jmpbuf_Address_NT);
  697.    SSL.Set_Machine_State_Addr (SSL.Get_Machine_State_Addr_NT);
  698. end System.Tasking.Restricted.Stages;
  699.