OSDN Git Service

* gcc.dg/tree-ssa/ssa-dse-10.c: Clean up all dse dump files.
[pf3gnuchains/gcc-fork.git] / gcc / ada / s-taprop-vxworks.adb
index f83fc02..7ba1ba5 100644 (file)
@@ -1,12 +1,12 @@
 ------------------------------------------------------------------------------
 --                                                                          --
---                 GNU ADA RUN-TIME LIBRARY (GNARL) COMPONENTS              --
+--                  GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                --
 --                                                                          --
 --     S Y S T E M . T A S K _ P R I M I T I V E S . O P E R A T I O N S    --
 --                                                                          --
 --                                  B o d y                                 --
 --                                                                          --
---         Copyright (C) 1992-2004, Free Software Foundation, Inc.          --
+--         Copyright (C) 1992-2007, Free Software Foundation, Inc.          --
 --                                                                          --
 -- GNARL is free software; you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -16,8 +16,8 @@
 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 -- for  more details.  You should have  received  a copy of the GNU General --
 -- Public License  distributed with GNARL; see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
+-- Boston, MA 02110-1301, USA.                                              --
 --                                                                          --
 -- As a special exception,  if other files  instantiate  generics from this --
 -- unit, or you link  this unit with other files  to produce an executable, --
@@ -45,44 +45,33 @@ with System.Tasking.Debug;
 
 with System.Interrupt_Management;
 --  used for Keep_Unmasked
---           Abort_Task_Signal
+--           Abort_Task_Interrupt
 --           Signal_ID
 --           Initialize_Interrupts
 
-with System.Soft_Links;
---  used for Defer/Undefer_Abort
-
---  Note that we do not use System.Tasking.Initialization directly since
---  this is a higher level package that we shouldn't depend on. For example
---  when using the restricted run time, it is replaced by
---  System.Tasking.Restricted.Initialization
-
-with System.OS_Interface;
---  used for various type, constant, and operations
-
-with System.Parameters;
---  used for Size_Type
+with Interfaces.C;
 
-with System.Tasking;
---  used for Ada_Task_Control_Block
---           Task_Id
---           ATCB components and types
+with System.Soft_Links;
+--  used for Abort_Defer/Undefer
 
-with Interfaces.C;
+--  We use System.Soft_Links instead of System.Tasking.Initialization
+--  because the later is a higher level package that we shouldn't depend on.
+--  For example when using the restricted run time, it is replaced by
+--  System.Tasking.Restricted.Stages.
 
-with Unchecked_Conversion;
-with Unchecked_Deallocation;
+with Ada.Unchecked_Conversion;
+with Ada.Unchecked_Deallocation;
 
 package body System.Task_Primitives.Operations is
 
+   package SSL renames System.Soft_Links;
+
    use System.Tasking.Debug;
    use System.Tasking;
    use System.OS_Interface;
    use System.Parameters;
    use type Interfaces.C.int;
 
-   package SSL renames System.Soft_Links;
-
    subtype int is System.OS_Interface.int;
 
    Relative : constant := 0;
@@ -91,30 +80,21 @@ package body System.Task_Primitives.Operations is
    -- Local Data --
    ----------------
 
-   --  The followings are logically constants, but need to be initialized
-   --  at run time.
+   --  The followings are logically constants, but need to be initialized at
+   --  run time.
 
    Single_RTS_Lock : aliased RTS_Lock;
-   --  This is a lock to allow only one thread of control in the RTS at
-   --  time; it is used to execute in mutual exclusion from all other tasks.
+   --  This is a lock to allow only one thread of control in the RTS at a
+   --  time; it is used to execute in mutual exclusion from all other tasks.
    --  Used mainly in Single_Lock mode, but also to protect All_Tasks_List
 
-   ATCB_Key : aliased System.Address := System.Null_Address;
-   --  Key used to find the Ada Task_Id associated with a thread
-
-   ATCB_Key_Addr : System.Address := ATCB_Key'Address;
-   pragma Export (Ada, ATCB_Key_Addr, "__gnat_ATCB_key_addr");
-   --  Exported to support the temporary AE653 task registration
-   --  implementation. This mechanism is used to minimize impact on other
-   --  targets.
-
    Environment_Task_Id : Task_Id;
-   --  A variable to hold Task_Id for the environment task.
+   --  A variable to hold Task_Id for the environment task
 
    Unblocked_Signal_Mask : aliased sigset_t;
    --  The set of signals that should unblocked in all tasks
 
-   --  The followings are internal configuration constants needed.
+   --  The followings are internal configuration constants needed
 
    Time_Slice_Val : Integer;
    pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
@@ -125,13 +105,14 @@ package body System.Task_Primitives.Operations is
    Dispatching_Policy : Character;
    pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
 
-   FIFO_Within_Priorities : constant Boolean := Dispatching_Policy = 'F';
-   --  Indicates whether FIFO_Within_Priorities is set.
+   function Get_Policy (Prio : System.Any_Priority) return Character;
+   pragma Import (C, Get_Policy, "__gnat_get_specific_dispatching");
+   --  Get priority specific dispatching policy
 
    Mutex_Protocol : Priority_Type;
 
    Foreign_Task_Elaborated : aliased Boolean := True;
-   --  Used to identified fake tasks (i.e., non-Ada Threads).
+   --  Used to identified fake tasks (i.e., non-Ada Threads)
 
    --------------------
    -- Local Packages --
@@ -139,29 +120,37 @@ package body System.Task_Primitives.Operations is
 
    package Specific is
 
+      procedure Initialize;
+      pragma Inline (Initialize);
+      --  Initialize task specific data
+
       function Is_Valid_Task return Boolean;
       pragma Inline (Is_Valid_Task);
       --  Does executing thread have a TCB?
 
       procedure Set (Self_Id : Task_Id);
       pragma Inline (Set);
-      --  Set the self id for the current task.
+      --  Set the self id for the current task
+
+      procedure Delete;
+      pragma Inline (Delete);
+      --  Delete the task specific data associated with the current task
 
       function Self return Task_Id;
       pragma Inline (Self);
-      --  Return a pointer to the Ada Task Control Block of the calling task.
+      --  Return a pointer to the Ada Task Control Block of the calling task
 
    end Specific;
 
    package body Specific is separate;
-   --  The body of this package is target specific.
+   --  The body of this package is target specific
 
    ---------------------------------
    -- Support for foreign threads --
    ---------------------------------
 
    function Register_Foreign_Thread (Thread : Thread_Id) return Task_Id;
-   --  Allocate and Initialize a new ATCB for the current Thread.
+   --  Allocate and Initialize a new ATCB for the current Thread
 
    function Register_Foreign_Thread
      (Thread : Thread_Id) return Task_Id is separate;
@@ -171,12 +160,13 @@ package body System.Task_Primitives.Operations is
    -----------------------
 
    procedure Abort_Handler (signo : Signal);
-   --  Handler for the abort (SIGABRT) signal to handle asynchronous abortion.
+   --  Handler for the abort (SIGABRT) signal to handle asynchronous abort
 
    procedure Install_Signal_Handlers;
    --  Install the default signal handlers for the current task
 
-   function To_Address is new Unchecked_Conversion (Task_Id, System.Address);
+   function To_Address is
+     new Ada.Unchecked_Conversion (Task_Id, System.Address);
 
    -------------------
    -- Abort_Handler --
@@ -205,8 +195,11 @@ package body System.Task_Primitives.Operations is
 
          --  Make sure signals used for RTS internal purpose are unmasked
 
-         Result := pthread_sigmask (SIG_UNBLOCK,
-           Unblocked_Signal_Mask'Unchecked_Access, Old_Set'Unchecked_Access);
+         Result :=
+           pthread_sigmask
+             (SIG_UNBLOCK,
+              Unblocked_Signal_Mask'Unchecked_Access,
+              Old_Set'Unchecked_Access);
          pragma Assert (Result = 0);
 
          raise Standard'Abort_Signal;
@@ -262,7 +255,7 @@ package body System.Task_Primitives.Operations is
 
       Result :=
         sigaction
-          (Signal (Interrupt_Management.Abort_Task_Signal),
+          (Signal (Interrupt_Management.Abort_Task_Interrupt),
            act'Unchecked_Access,
            old_act'Unchecked_Access);
       pragma Assert (Result = 0);
@@ -274,7 +267,10 @@ package body System.Task_Primitives.Operations is
    -- Initialize_Lock --
    ---------------------
 
-   procedure Initialize_Lock (Prio : System.Any_Priority; L : access Lock) is
+   procedure Initialize_Lock
+     (Prio : System.Any_Priority;
+      L    : not null access Lock)
+   is
    begin
       L.Mutex := semMCreate (SEM_Q_PRIORITY + SEM_INVERSION_SAFE);
       L.Prio_Ceiling := int (Prio);
@@ -282,9 +278,11 @@ package body System.Task_Primitives.Operations is
       pragma Assert (L.Mutex /= 0);
    end Initialize_Lock;
 
-   procedure Initialize_Lock (L : access RTS_Lock; Level : Lock_Level) is
+   procedure Initialize_Lock
+     (L     : not null access RTS_Lock;
+      Level : Lock_Level)
+   is
       pragma Unreferenced (Level);
-
    begin
       L.Mutex := semMCreate (SEM_Q_PRIORITY + SEM_INVERSION_SAFE);
       L.Prio_Ceiling := int (System.Any_Priority'Last);
@@ -296,17 +294,15 @@ package body System.Task_Primitives.Operations is
    -- Finalize_Lock --
    -------------------
 
-   procedure Finalize_Lock (L : access Lock) is
+   procedure Finalize_Lock (L : not null access Lock) is
       Result : int;
-
    begin
       Result := semDelete (L.Mutex);
       pragma Assert (Result = 0);
    end Finalize_Lock;
 
-   procedure Finalize_Lock (L : access RTS_Lock) is
+   procedure Finalize_Lock (L : not null access RTS_Lock) is
       Result : int;
-
    begin
       Result := semDelete (L.Mutex);
       pragma Assert (Result = 0);
@@ -316,7 +312,10 @@ package body System.Task_Primitives.Operations is
    -- Write_Lock --
    ----------------
 
-   procedure Write_Lock (L : access Lock; Ceiling_Violation : out Boolean) is
+   procedure Write_Lock
+     (L                 : not null access Lock;
+      Ceiling_Violation : out Boolean)
+   is
       Result : int;
 
    begin
@@ -334,11 +333,10 @@ package body System.Task_Primitives.Operations is
    end Write_Lock;
 
    procedure Write_Lock
-     (L           : access RTS_Lock;
+     (L           : not null access RTS_Lock;
       Global_Lock : Boolean := False)
    is
       Result : int;
-
    begin
       if not Single_Lock or else Global_Lock then
          Result := semTake (L.Mutex, WAIT_FOREVER);
@@ -348,7 +346,6 @@ package body System.Task_Primitives.Operations is
 
    procedure Write_Lock (T : Task_Id) is
       Result : int;
-
    begin
       if not Single_Lock then
          Result := semTake (T.Common.LL.L.Mutex, WAIT_FOREVER);
@@ -360,7 +357,10 @@ package body System.Task_Primitives.Operations is
    -- Read_Lock --
    ---------------
 
-   procedure Read_Lock (L : access Lock; Ceiling_Violation : out Boolean) is
+   procedure Read_Lock
+     (L                 : not null access Lock;
+      Ceiling_Violation : out Boolean)
+   is
    begin
       Write_Lock (L, Ceiling_Violation);
    end Read_Lock;
@@ -369,17 +369,18 @@ package body System.Task_Primitives.Operations is
    -- Unlock --
    ------------
 
-   procedure Unlock (L : access Lock) is
-      Result  : int;
-
+   procedure Unlock (L : not null access Lock) is
+      Result : int;
    begin
       Result := semGive (L.Mutex);
       pragma Assert (Result = 0);
    end Unlock;
 
-   procedure Unlock (L : access RTS_Lock; Global_Lock : Boolean := False) is
+   procedure Unlock
+     (L           : not null access RTS_Lock;
+      Global_Lock : Boolean := False)
+   is
       Result : int;
-
    begin
       if not Single_Lock or else Global_Lock then
          Result := semGive (L.Mutex);
@@ -389,7 +390,6 @@ package body System.Task_Primitives.Operations is
 
    procedure Unlock (T : Task_Id) is
       Result : int;
-
    begin
       if not Single_Lock then
          Result := semGive (T.Common.LL.L.Mutex);
@@ -397,6 +397,21 @@ package body System.Task_Primitives.Operations is
       end if;
    end Unlock;
 
+   -----------------
+   -- Set_Ceiling --
+   -----------------
+
+   --  Dynamic priority ceilings are not supported by the underlying system
+
+   procedure Set_Ceiling
+     (L    : not null access Lock;
+      Prio : System.Any_Priority)
+   is
+      pragma Unreferenced (L, Prio);
+   begin
+      null;
+   end Set_Ceiling;
+
    -----------
    -- Sleep --
    -----------
@@ -409,7 +424,8 @@ package body System.Task_Primitives.Operations is
    begin
       pragma Assert (Self_ID = Self);
 
-      --  Release the mutex before sleeping.
+      --  Release the mutex before sleeping
+
       if Single_Lock then
          Result := semGive (Single_RTS_Lock.Mutex);
       else
@@ -418,15 +434,16 @@ package body System.Task_Primitives.Operations is
 
       pragma Assert (Result = 0);
 
-      --  Perform a blocking operation to take the CV semaphore.
-      --  Note that a blocking operation in VxWorks will reenable
-      --  task scheduling. When we are no longer blocked and control
-      --  is returned, task scheduling will again be disabled.
+      --  Perform a blocking operation to take the CV semaphore. Note that a
+      --  blocking operation in VxWorks will reenable task scheduling. When we
+      --  are no longer blocked and control is returned, task scheduling will
+      --  again be disabled.
 
       Result := semTake (Self_ID.Common.LL.CV, WAIT_FOREVER);
       pragma Assert (Result = 0);
 
-      --  Take the mutex back.
+      --  Take the mutex back
+
       if Single_Lock then
          Result := semTake (Single_RTS_Lock.Mutex, WAIT_FOREVER);
       else
@@ -440,9 +457,8 @@ package body System.Task_Primitives.Operations is
    -- Timed_Sleep --
    -----------------
 
-   --  This is for use within the run-time system, so abort is
-   --  assumed to be already deferred, and the caller should be
-   --  holding its own ATCB lock.
+   --  This is for use within the run-time system, so abort is assumed to be
+   --  already deferred, and the caller should be holding its own ATCB lock.
 
    procedure Timed_Sleep
      (Self_ID  : Task_Id;
@@ -467,9 +483,9 @@ package body System.Task_Primitives.Operations is
       if Mode = Relative then
          Absolute := Orig + Time;
 
-         --  Systematically add one since the first tick will delay
-         --  *at most* 1 / Rate_Duration seconds, so we need to add one to
-         --  be on the safe side.
+         --  Systematically add one since the first tick will delay *at most*
+         --  1 / Rate_Duration seconds, so we need to add one to be on the
+         --  safe side.
 
          Ticks := To_Clock_Ticks (Time);
 
@@ -484,7 +500,8 @@ package body System.Task_Primitives.Operations is
 
       if Ticks > 0 then
          loop
-            --  Release the mutex before sleeping.
+            --  Release the mutex before sleeping
+
             if Single_Lock then
                Result := semGive (Single_RTS_Lock.Mutex);
             else
@@ -493,14 +510,15 @@ package body System.Task_Primitives.Operations is
 
             pragma Assert (Result = 0);
 
-            --  Perform a blocking operation to take the CV semaphore.
-            --  Note that a blocking operation in VxWorks will reenable
-            --  task scheduling. When we are no longer blocked and control
-            --  is returned, task scheduling will again be disabled.
+            --  Perform a blocking operation to take the CV semaphore. Note
+            --  that a blocking operation in VxWorks will reenable task
+            --  scheduling. When we are no longer blocked and control is
+            --  returned, task scheduling will again be disabled.
 
             Result := semTake (Self_ID.Common.LL.CV, Ticks);
 
             if Result = 0 then
+
                --  Somebody may have called Wakeup for us
 
                Wakeup := True;
@@ -508,13 +526,15 @@ package body System.Task_Primitives.Operations is
             else
                if errno /= S_objLib_OBJ_TIMEOUT then
                   Wakeup := True;
+
                else
-                  --  If Ticks = int'last, it was most probably truncated
-                  --  so let's make another round after recomputing Ticks
-                  --  from the the absolute time.
+                  --  If Ticks = int'last, it was most probably truncated so
+                  --  let's make another round after recomputing Ticks from
+                  --  the the absolute time.
 
                   if Ticks /= int'Last then
                      Timedout := True;
+
                   else
                      Ticks := To_Clock_Ticks (Absolute - Monotonic_Clock);
 
@@ -525,7 +545,8 @@ package body System.Task_Primitives.Operations is
                end if;
             end if;
 
-            --  Take the mutex back.
+            --  Take the mutex back
+
             if Single_Lock then
                Result := semTake (Single_RTS_Lock.Mutex, WAIT_FOREVER);
             else
@@ -540,7 +561,8 @@ package body System.Task_Primitives.Operations is
       else
          Timedout := True;
 
-         --  Should never hold a lock while yielding.
+         --  Should never hold a lock while yielding
+
          if Single_Lock then
             Result := semGive (Single_RTS_Lock.Mutex);
             taskDelay (0);
@@ -558,33 +580,32 @@ package body System.Task_Primitives.Operations is
    -- Timed_Delay --
    -----------------
 
-   --  This is for use in implementing delay statements, so
-   --  we assume the caller is holding no locks.
+   --  This is for use in implementing delay statements, so we assume the
+   --  caller is holding no locks.
 
    procedure Timed_Delay
-     (Self_ID  : Task_Id;
-      Time     : Duration;
-      Mode     : ST.Delay_Modes)
+     (Self_ID : Task_Id;
+      Time    : Duration;
+      Mode    : ST.Delay_Modes)
    is
       Orig     : constant Duration := Monotonic_Clock;
       Absolute : Duration;
       Ticks    : int;
       Timedout : Boolean;
-      Result   : int;
       Aborted  : Boolean := False;
 
-   begin
-      SSL.Abort_Defer.all;
+      Result : int;
+      pragma Warnings (Off, Result);
 
+   begin
       if Mode = Relative then
          Absolute := Orig + Time;
          Ticks    := To_Clock_Ticks (Time);
 
          if Ticks > 0 and then Ticks < int'Last then
 
-            --  The first tick will delay anytime between 0 and
-            --  1 / sysClkRateGet seconds, so we need to add one to
-            --  be on the safe side.
+            --  First tick will delay anytime between 0 and 1 / sysClkRateGet
+            --  seconds, so we need to add one to be on the safe side.
 
             Ticks := Ticks + 1;
          end if;
@@ -595,7 +616,9 @@ package body System.Task_Primitives.Operations is
       end if;
 
       if Ticks > 0 then
-         --  Modifying State and Pending_Priority_Change, locking the TCB.
+
+         --  Modifying State, locking the TCB
+
          if Single_Lock then
             Result := semTake (Single_RTS_Lock.Mutex, WAIT_FOREVER);
          else
@@ -608,12 +631,6 @@ package body System.Task_Primitives.Operations is
          Timedout := False;
 
          loop
-            if Self_ID.Pending_Priority_Change then
-               Self_ID.Pending_Priority_Change := False;
-               Self_ID.Common.Base_Priority    := Self_ID.New_Base_Priority;
-               Set_Priority (Self_ID, Self_ID.Common.Base_Priority);
-            end if;
-
             Aborted := Self_ID.Pending_ATC_Level < Self_ID.ATC_Nesting_Level;
 
             --  Release the TCB before sleeping
@@ -630,6 +647,7 @@ package body System.Task_Primitives.Operations is
             Result := semTake (Self_ID.Common.LL.CV, Ticks);
 
             if Result /= 0 then
+
                --  If Ticks = int'last, it was most probably truncated
                --  so let's make another round after recomputing Ticks
                --  from the the absolute time.
@@ -646,7 +664,7 @@ package body System.Task_Primitives.Operations is
             end if;
 
             --  Take back the lock after having slept, to protect further
-            --  access to Self_ID
+            --  access to Self_ID.
 
             if Single_Lock then
                Result := semTake (Single_RTS_Lock.Mutex, WAIT_FOREVER);
@@ -670,8 +688,6 @@ package body System.Task_Primitives.Operations is
       else
          taskDelay (0);
       end if;
-
-      SSL.Abort_Undefer.all;
    end Timed_Delay;
 
    ---------------------
@@ -746,33 +762,32 @@ package body System.Task_Primitives.Operations is
           (T.Common.LL.Thread, To_VxWorks_Priority (int (Prio)));
       pragma Assert (Result = 0);
 
-      if FIFO_Within_Priorities then
+      if (Dispatching_Policy = 'F' or else Get_Policy (Prio) = 'F')
+        and then Loss_Of_Inheritance
+        and then Prio < T.Common.Current_Priority
+      then
+         --  Annex D requirement (RM D.2.2(9))
 
-         --  Annex D requirement [RM D.2.2 par. 9]:
          --    If the task drops its priority due to the loss of inherited
          --    priority, it is added at the head of the ready queue for its
          --    new active priority.
 
-         if Loss_Of_Inheritance
-           and then Prio < T.Common.Current_Priority
-         then
-            Array_Item := Prio_Array (T.Common.Base_Priority) + 1;
-            Prio_Array (T.Common.Base_Priority) := Array_Item;
+         Array_Item := Prio_Array (T.Common.Base_Priority) + 1;
+         Prio_Array (T.Common.Base_Priority) := Array_Item;
 
-            loop
-               --  Give some processes a chance to arrive
+         loop
+            --  Give some processes a chance to arrive
 
-               taskDelay (0);
+            taskDelay (0);
 
-               --  Then wait for our turn to proceed
+            --  Then wait for our turn to proceed
 
-               exit when Array_Item = Prio_Array (T.Common.Base_Priority)
-                 or else Prio_Array (T.Common.Base_Priority) = 1;
-            end loop;
+            exit when Array_Item = Prio_Array (T.Common.Base_Priority)
+              or else Prio_Array (T.Common.Base_Priority) = 1;
+         end loop;
 
-            Prio_Array (T.Common.Base_Priority) :=
-              Prio_Array (T.Common.Base_Priority) - 1;
-         end if;
+         Prio_Array (T.Common.Base_Priority) :=
+           Prio_Array (T.Common.Base_Priority) - 1;
       end if;
 
       T.Common.Current_Priority := Prio;
@@ -794,15 +809,22 @@ package body System.Task_Primitives.Operations is
    procedure Enter_Task (Self_ID : Task_Id) is
       procedure Init_Float;
       pragma Import (C, Init_Float, "__gnat_init_float");
-      --  Properly initializes the FPU for PPC/MIPS systems.
+      --  Properly initializes the FPU for PPC/MIPS systems
 
    begin
+      --  Store the user-level task id in the Thread field (to be used
+      --  internally by the run-time system) and the kernel-level task id in
+      --  the LWP field (to be used by the debugger).
+
       Self_ID.Common.LL.Thread := taskIdSelf;
+      Self_ID.Common.LL.LWP := getpid;
+
       Specific.Set (Self_ID);
 
       Init_Float;
 
-      --  Install the signal handlers.
+      --  Install the signal handlers
+
       --  This is called for each task since there is no signal inheritance
       --  between VxWorks tasks.
 
@@ -860,6 +882,7 @@ package body System.Task_Primitives.Operations is
 
       if Self_ID.Common.LL.CV = 0 then
          Succeeded := False;
+
       else
          Succeeded := True;
 
@@ -882,64 +905,66 @@ package body System.Task_Primitives.Operations is
    is
       Adjusted_Stack_Size : size_t;
    begin
-      if Stack_Size = Unspecified_Size then
-         Adjusted_Stack_Size := size_t (Default_Stack_Size);
+      --  Ask for four extra bytes of stack space so that the ATCB pointer can
+      --  be stored below the stack limit, plus extra space for the frame of
+      --  Task_Wrapper. This is so the user gets the amount of stack requested
+      --  exclusive of the needs.
 
-      elsif Stack_Size < Minimum_Stack_Size then
-         Adjusted_Stack_Size := size_t (Minimum_Stack_Size);
+      --  We also have to allocate n more bytes for the task name storage and
+      --  enough space for the Wind Task Control Block which is around 0x778
+      --  bytes. VxWorks also seems to carve out additional space, so use 2048
+      --  as a nice round number. We might want to increment to the nearest
+      --  page size in case we ever support VxVMI.
 
-      else
-         Adjusted_Stack_Size := size_t (Stack_Size);
-      end if;
+      --  ??? - we should come back and visit this so we can set the task name
+      --        to something appropriate.
 
-      --  Ask for 4 extra bytes of stack space so that the ATCB
-      --  pointer can be stored below the stack limit, plus extra
-      --  space for the frame of Task_Wrapper.  This is so the user
-      --  gets the amount of stack requested exclusive of the needs
-      --  of the runtime.
-      --
-      --  We also have to allocate n more bytes for the task name
-      --  storage and enough space for the Wind Task Control Block
-      --  which is around 0x778 bytes.  VxWorks also seems to carve out
-      --  additional space, so use 2048 as a nice round number.
-      --  We might want to increment to the nearest page size in
-      --  case we ever support VxVMI.
-      --
-      --  XXX - we should come back and visit this so we can
-      --        set the task name to something appropriate.
-
-      Adjusted_Stack_Size := Adjusted_Stack_Size + 2048;
+      Adjusted_Stack_Size := size_t (Stack_Size) + 2048;
 
       --  Since the initial signal mask of a thread is inherited from the
-      --  creator, and the Environment task has all its signals masked, we
-      --  do not need to manipulate caller's signal mask at this point.
-      --  All tasks in RTS will have All_Tasks_Mask initially.
-
-      if T.Common.Task_Image_Len = 0 then
-         T.Common.LL.Thread := taskSpawn
-           (System.Null_Address,
-            To_VxWorks_Priority (int (Priority)),
-            VX_FP_TASK,
-            Adjusted_Stack_Size,
-            Wrapper,
-            To_Address (T));
-      else
-         declare
-            Name : aliased String (1 .. T.Common.Task_Image_Len + 1);
-         begin
+      --  creator, and the Environment task has all its signals masked, we do
+      --  not need to manipulate caller's signal mask at this point. All tasks
+      --  in RTS will have All_Tasks_Mask initially.
+
+      --  We now compute the VxWorks task name and options, then spawn ...
+
+      declare
+         Name         : aliased String (1 .. T.Common.Task_Image_Len + 1);
+         Name_Address : System.Address;
+         --  Task name we are going to hand down to VxWorks
+
+         function Get_Task_Options return int;
+         pragma Import (C, Get_Task_Options, "__gnat_get_task_options");
+         --  Function that returns the options to be set for the task that we
+         --  are creating. We fetch the options assigned to the current task,
+         --  so offering some user level control over the options for a task
+         --  hierarchy, and force VX_FP_TASK because it is almost always
+         --  required.
+
+      begin
+         --  If there is no Ada task name handy, let VxWorks choose one.
+         --  Otherwise, tell VxWorks what the Ada task name is.
+
+         if T.Common.Task_Image_Len = 0 then
+            Name_Address := System.Null_Address;
+         else
             Name (1 .. Name'Last - 1) :=
               T.Common.Task_Image (1 .. T.Common.Task_Image_Len);
             Name (Name'Last) := ASCII.NUL;
+            Name_Address := Name'Address;
+         end if;
 
-            T.Common.LL.Thread := taskSpawn
-              (Name'Address,
-               To_VxWorks_Priority (int (Priority)),
-               VX_FP_TASK,
-               Adjusted_Stack_Size,
-               Wrapper,
-               To_Address (T));
-         end;
-      end if;
+         --  Now spawn the VxWorks task for real
+
+         T.Common.LL.Thread :=
+           taskSpawn
+             (Name_Address,
+              To_VxWorks_Priority (int (Priority)),
+              Get_Task_Options,
+              Adjusted_Stack_Size,
+              Wrapper,
+              To_Address (T));
+      end;
 
       if T.Common.LL.Thread = -1 then
          Succeeded := False;
@@ -961,7 +986,7 @@ package body System.Task_Primitives.Operations is
       Is_Self : constant Boolean := (T = Self);
 
       procedure Free is new
-        Unchecked_Deallocation (Ada_Task_Control_Block, Task_Id);
+        Ada.Unchecked_Deallocation (Ada_Task_Control_Block, Task_Id);
 
    begin
       if not Single_Lock then
@@ -981,8 +1006,7 @@ package body System.Task_Primitives.Operations is
       Free (Tmp);
 
       if Is_Self then
-         Result := taskVarDelete (taskIdSelf, ATCB_Key'Access);
-         pragma Assert (Result /= ERROR);
+         Specific.Delete;
       end if;
    end Finalize_TCB;
 
@@ -1001,14 +1025,179 @@ package body System.Task_Primitives.Operations is
 
    procedure Abort_Task (T : Task_Id) is
       Result : int;
-
    begin
-      Result := kill (T.Common.LL.Thread,
-        Signal (Interrupt_Management.Abort_Task_Signal));
+      Result :=
+        kill
+          (T.Common.LL.Thread,
+           Signal (Interrupt_Management.Abort_Task_Interrupt));
       pragma Assert (Result = 0);
    end Abort_Task;
 
    ----------------
+   -- Initialize --
+   ----------------
+
+   procedure Initialize (S : in out Suspension_Object) is
+   begin
+      --  Initialize internal state (always to False (RM D.10(6)))
+
+      S.State := False;
+      S.Waiting := False;
+
+      --  Initialize internal mutex
+
+      --  Use simpler binary semaphore instead of VxWorks
+      --  mutual exclusion semaphore, because we don't need
+      --  the fancier semantics and their overhead.
+
+      S.L := semBCreate (SEM_Q_FIFO, SEM_FULL);
+
+      --  Initialize internal condition variable
+
+      S.CV := semBCreate (SEM_Q_FIFO, SEM_EMPTY);
+   end Initialize;
+
+   --------------
+   -- Finalize --
+   --------------
+
+   procedure Finalize (S : in out Suspension_Object) is
+      Result : STATUS;
+
+   begin
+      --  Destroy internal mutex
+
+      Result := semDelete (S.L);
+      pragma Assert (Result = OK);
+
+      --  Destroy internal condition variable
+
+      Result := semDelete (S.CV);
+      pragma Assert (Result = OK);
+   end Finalize;
+
+   -------------------
+   -- Current_State --
+   -------------------
+
+   function Current_State (S : Suspension_Object) return Boolean is
+   begin
+      --  We do not want to use lock on this read operation. State is marked
+      --  as Atomic so that we ensure that the value retrieved is correct.
+
+      return S.State;
+   end Current_State;
+
+   ---------------
+   -- Set_False --
+   ---------------
+
+   procedure Set_False (S : in out Suspension_Object) is
+      Result : STATUS;
+
+   begin
+      SSL.Abort_Defer.all;
+
+      Result := semTake (S.L, WAIT_FOREVER);
+      pragma Assert (Result = OK);
+
+      S.State := False;
+
+      Result := semGive (S.L);
+      pragma Assert (Result = OK);
+
+      SSL.Abort_Undefer.all;
+   end Set_False;
+
+   --------------
+   -- Set_True --
+   --------------
+
+   procedure Set_True (S : in out Suspension_Object) is
+      Result : STATUS;
+
+   begin
+      SSL.Abort_Defer.all;
+
+      Result := semTake (S.L, WAIT_FOREVER);
+      pragma Assert (Result = OK);
+
+      --  If there is already a task waiting on this suspension object then
+      --  we resume it, leaving the state of the suspension object to False,
+      --  as it is specified in ARM D.10 par. 9. Otherwise, it just leaves
+      --  the state to True.
+
+      if S.Waiting then
+         S.Waiting := False;
+         S.State := False;
+
+         Result := semGive (S.CV);
+         pragma Assert (Result = OK);
+      else
+         S.State := True;
+      end if;
+
+      Result := semGive (S.L);
+      pragma Assert (Result = OK);
+
+      SSL.Abort_Undefer.all;
+   end Set_True;
+
+   ------------------------
+   -- Suspend_Until_True --
+   ------------------------
+
+   procedure Suspend_Until_True (S : in out Suspension_Object) is
+      Result : STATUS;
+
+   begin
+      SSL.Abort_Defer.all;
+
+      Result := semTake (S.L, WAIT_FOREVER);
+
+      if S.Waiting then
+
+         --  Program_Error must be raised upon calling Suspend_Until_True
+         --  if another task is already waiting on that suspension object
+         --  (ARM D.10 par. 10).
+
+         Result := semGive (S.L);
+         pragma Assert (Result = OK);
+
+         SSL.Abort_Undefer.all;
+
+         raise Program_Error;
+
+      else
+         --  Suspend the task if the state is False. Otherwise, the task
+         --  continues its execution, and the state of the suspension object
+         --  is set to False (ARM D.10 par. 9).
+
+         if S.State then
+            S.State := False;
+
+            Result := semGive (S.L);
+            pragma Assert (Result = 0);
+
+            SSL.Abort_Undefer.all;
+
+         else
+            S.Waiting := True;
+
+            --  Release the mutex before sleeping
+
+            Result := semGive (S.L);
+            pragma Assert (Result = OK);
+
+            SSL.Abort_Undefer.all;
+
+            Result := semTake (S.CV, WAIT_FOREVER);
+            pragma Assert (Result = 0);
+         end if;
+      end if;
+   end Suspend_Until_True;
+
+   ----------------
    -- Check_Exit --
    ----------------
 
@@ -1093,6 +1282,49 @@ package body System.Task_Primitives.Operations is
       end if;
    end Resume_Task;
 
+   --------------------
+   -- Stop_All_Tasks --
+   --------------------
+
+   procedure Stop_All_Tasks
+   is
+      Thread_Self : constant Thread_Id := taskIdSelf;
+      C           : Task_Id;
+
+      Dummy : int;
+      pragma Unreferenced (Dummy);
+
+   begin
+      Dummy := Int_Lock;
+
+      C := All_Tasks_List;
+      while C /= null loop
+         if C.Common.LL.Thread /= 0
+           and then C.Common.LL.Thread /= Thread_Self
+         then
+            Dummy := Task_Stop (C.Common.LL.Thread);
+         end if;
+
+         C := C.Common.All_Tasks_Link;
+      end loop;
+
+      Dummy := Int_Unlock;
+   end Stop_All_Tasks;
+
+   -------------------
+   -- Continue_Task --
+   -------------------
+
+   function Continue_Task (T : ST.Task_Id) return Boolean
+   is
+   begin
+      if T.Common.LL.Thread /= 0 then
+         return Task_Cont (T.Common.LL.Thread) = 0;
+      else
+         return True;
+      end if;
+   end Continue_Task;
+
    ----------------
    -- Initialize --
    ----------------
@@ -1101,6 +1333,11 @@ package body System.Task_Primitives.Operations is
       Result : int;
 
    begin
+      Environment_Task_Id := Environment_Task;
+
+      Interrupt_Management.Initialize;
+      Specific.Initialize;
+
       if Locking_Policy = 'C' then
          Mutex_Protocol := Prio_Protect;
       elsif Locking_Policy = 'I' then
@@ -1110,9 +1347,14 @@ package body System.Task_Primitives.Operations is
       end if;
 
       if Time_Slice_Val > 0 then
-         Result := kernelTimeSlice
-           (To_Clock_Ticks
-             (Duration (Time_Slice_Val) / Duration (1_000_000.0)));
+         Result :=
+           Set_Time_Slice
+             (To_Clock_Ticks
+                (Duration (Time_Slice_Val) / Duration (1_000_000.0)));
+
+      elsif Dispatching_Policy = 'R' then
+         Result := Set_Time_Slice (To_Clock_Ticks (0.01));
+
       end if;
 
       Result := sigemptyset (Unblocked_Signal_Mask'Access);
@@ -1125,9 +1367,7 @@ package body System.Task_Primitives.Operations is
          end if;
       end loop;
 
-      Environment_Task_Id := Environment_Task;
-
-      --  Initialize the lock used to synchronize chain of all ATCBs.
+      --  Initialize the lock used to synchronize chain of all ATCBs
 
       Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);