------------------------------------------------------------------------------
--                                                                          --
--                GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                  --
--                                                                          --
--            S Y S T E M . T A S K I N G . R E N D E Z V O U S             --
--                                                                          --
--                                 B o d y                                  --
--                                                                          --
--         Copyright (C) 1992-2021, 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- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
--                                                                          --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception,   --
-- version 3.1, as published by the Free Software Foundation.               --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
-- GNARL was developed by the GNARL team at Florida State University.       --
-- Extensive contributions were provided by Ada Core Technologies, Inc.     --
--                                                                          --
------------------------------------------------------------------------------

with System.Task_Primitives.Operations;
with System.Tasking.Entry_Calls;
with System.Tasking.Initialization;
with System.Tasking.Queuing;
with System.Tasking.Utilities;
with System.Tasking.Protected_Objects.Operations;
with System.Tasking.Debug;
with System.Restrictions;

package body System.Tasking.Rendezvous is

   package STPO renames System.Task_Primitives.Operations;
   package POO renames Protected_Objects.Operations;
   package POE renames Protected_Objects.Entries;

   use Task_Primitives.Operations;

   type Select_Treatment is (
     Accept_Alternative_Selected,   --  alternative with non-null body
     Accept_Alternative_Completed,  --  alternative with null body
     Else_Selected,
     Terminate_Selected,
     Accept_Alternative_Open,
     No_Alternative_Open);

   ----------------
   -- Local Data --
   ----------------

   Default_Treatment : constant array (Select_Modes) of Select_Treatment :=
     (Simple_Mode         => No_Alternative_Open,
      Else_Mode           => Else_Selected,
      Terminate_Mode      => Terminate_Selected,
      Delay_Mode          => No_Alternative_Open);

   New_State : constant array (Boolean, Entry_Call_State)
     of Entry_Call_State :=
       (True =>
         (Never_Abortable   => Never_Abortable,
          Not_Yet_Abortable => Now_Abortable,
          Was_Abortable     => Now_Abortable,
          Now_Abortable     => Now_Abortable,
          Done              => Done,
          Cancelled         => Cancelled),
        False =>
         (Never_Abortable   => Never_Abortable,
          Not_Yet_Abortable => Not_Yet_Abortable,
          Was_Abortable     => Was_Abortable,
          Now_Abortable     => Now_Abortable,
          Done              => Done,
          Cancelled         => Cancelled)
       );

   -----------------------
   -- Local Subprograms --
   -----------------------

   procedure Local_Defer_Abort (Self_Id : Task_Id) renames
     System.Tasking.Initialization.Defer_Abort_Nestable;

   procedure Local_Undefer_Abort (Self_Id : Task_Id) renames
     System.Tasking.Initialization.Undefer_Abort_Nestable;

   --  Florist defers abort around critical sections that make entry calls
   --  to the Interrupt_Manager task, which violates the general rule about
   --  top-level runtime system calls from abort-deferred regions. It is not
   --  that this is unsafe, but when it occurs in "normal" programs it usually
   --  means either the user is trying to do a potentially blocking operation
   --  from within a protected object, or there is a runtime system/compiler
   --  error that has failed to undefer an earlier abort deferral. Thus, for
   --  debugging it may be wise to modify the above renamings to the
   --  non-nestable forms.

   procedure Local_Complete_Rendezvous (Ex : Ada.Exceptions.Exception_Id);
   --  Internal version of Complete_Rendezvous, used to implement
   --  Complete_Rendezvous and Exceptional_Complete_Rendezvous.
   --  Should be called holding no locks, generally with abort
   --  not yet deferred.

   procedure Boost_Priority (Call : Entry_Call_Link; Acceptor : Task_Id);
   pragma Inline (Boost_Priority);
   --  Call this only with abort deferred and holding lock of Acceptor

   procedure Call_Synchronous
     (Acceptor              : Task_Id;
      E                     : Task_Entry_Index;
      Uninterpreted_Data    : System.Address;
      Mode                  : Call_Modes;
      Rendezvous_Successful : out Boolean);
   pragma Inline (Call_Synchronous);
   --  This call is used to make a simple or conditional entry call.
   --  Called from Call_Simple and Task_Entry_Call.

   procedure Setup_For_Rendezvous_With_Body
     (Entry_Call : Entry_Call_Link;
      Acceptor   : Task_Id);
   pragma Inline (Setup_For_Rendezvous_With_Body);
   --  Call this only with abort deferred and holding lock of Acceptor. When
   --  a rendezvous selected (ready for rendezvous) we need to save previous
   --  caller and adjust the priority. Also we need to make this call not
   --  Abortable (Cancellable) since the rendezvous has already been started.

   procedure Wait_For_Call (Self_Id : Task_Id);
   pragma Inline (Wait_For_Call);
   --  Call this only with abort deferred and holding lock of Self_Id. An
   --  accepting task goes into Sleep by calling this routine waiting for a
   --  call from the caller or waiting for an abort. Make sure Self_Id is
   --  locked before calling this routine.

   -----------------
   -- Accept_Call --
   -----------------

   procedure Accept_Call
     (E                  : Task_Entry_Index;
      Uninterpreted_Data : out System.Address)
   is
      Self_Id      : constant Task_Id := STPO.Self;
      Caller       : Task_Id          := null;
      Open_Accepts : aliased Accept_List (1 .. 1);
      Entry_Call   : Entry_Call_Link;

   begin
      Initialization.Defer_Abort (Self_Id);
      STPO.Write_Lock (Self_Id);

      if not Self_Id.Callable then
         pragma Assert (Self_Id.Pending_ATC_Level = Level_Completed_Task);

         pragma Assert (Self_Id.Pending_Action);

         STPO.Unlock (Self_Id);
         Initialization.Undefer_Abort (Self_Id);

         --  Should never get here ???

         pragma Assert (Standard.False);
         raise Standard'Abort_Signal;
      end if;

      Queuing.Dequeue_Head (Self_Id.Entry_Queues (E), Entry_Call);

      if Entry_Call /= null then
         Caller := Entry_Call.Self;
         Setup_For_Rendezvous_With_Body (Entry_Call, Self_Id);
         Uninterpreted_Data := Entry_Call.Uninterpreted_Data;

      else
         --  Wait for a caller

         Open_Accepts (1).Null_Body := False;
         Open_Accepts (1).S := E;
         Self_Id.Open_Accepts := Open_Accepts'Unrestricted_Access;

         --  Wait for normal call

         pragma Debug
           (Debug.Trace (Self_Id, "Accept_Call: wait", 'R'));
         Wait_For_Call (Self_Id);

         pragma Assert (Self_Id.Open_Accepts = null);

         if Self_Id.Common.Call /= null then
            Caller := Self_Id.Common.Call.Self;

            pragma Assert (Caller.ATC_Nesting_Level > Level_No_ATC_Occurring);

            Uninterpreted_Data :=
              Caller.Entry_Calls (Caller.ATC_Nesting_Level).Uninterpreted_Data;
         else
            --  Case of an aborted task

            Uninterpreted_Data := System.Null_Address;
         end if;
      end if;

      --  Self_Id.Common.Call should already be updated by the Caller. On
      --  return, we will start the rendezvous.

      STPO.Unlock (Self_Id);
      Initialization.Undefer_Abort (Self_Id);
   end Accept_Call;

   --------------------
   -- Accept_Trivial --
   --------------------

   procedure Accept_Trivial (E : Task_Entry_Index) is
      Self_Id      : constant Task_Id := STPO.Self;
      Caller       : Task_Id          := null;
      Open_Accepts : aliased Accept_List (1 .. 1);
      Entry_Call   : Entry_Call_Link;

   begin
      Initialization.Defer_Abort_Nestable (Self_Id);
      STPO.Write_Lock (Self_Id);

      if not Self_Id.Callable then
         pragma Assert (Self_Id.Pending_ATC_Level = Level_Completed_Task);

         pragma Assert (Self_Id.Pending_Action);

         STPO.Unlock (Self_Id);
         Initialization.Undefer_Abort_Nestable (Self_Id);

         --  Should never get here ???

         pragma Assert (Standard.False);
         raise Standard'Abort_Signal;
      end if;

      Queuing.Dequeue_Head (Self_Id.Entry_Queues (E), Entry_Call);

      if Entry_Call = null then

         --  Need to wait for entry call

         Open_Accepts (1).Null_Body := True;
         Open_Accepts (1).S := E;
         Self_Id.Open_Accepts := Open_Accepts'Unrestricted_Access;

         pragma Debug
          (Debug.Trace (Self_Id, "Accept_Trivial: wait", 'R'));

         Wait_For_Call (Self_Id);

         pragma Assert (Self_Id.Open_Accepts = null);

         --  No need to do anything special here for pending abort.
         --  Abort_Signal will be raised by Undefer on exit.

         STPO.Unlock (Self_Id);

      --  Found caller already waiting

      else
         pragma Assert (Entry_Call.State < Done);

         STPO.Unlock (Self_Id);
         Caller := Entry_Call.Self;

         STPO.Write_Lock (Caller);
         Initialization.Wakeup_Entry_Caller (Self_Id, Entry_Call, Done);
         STPO.Unlock (Caller);
      end if;

      Initialization.Undefer_Abort_Nestable (Self_Id);
   end Accept_Trivial;

   --------------------
   -- Boost_Priority --
   --------------------

   procedure Boost_Priority (Call : Entry_Call_Link; Acceptor : Task_Id) is
      Caller        : constant Task_Id             := Call.Self;
      Caller_Prio   : constant System.Any_Priority := Get_Priority (Caller);
      Acceptor_Prio : constant System.Any_Priority := Get_Priority (Acceptor);
   begin
      if Caller_Prio > Acceptor_Prio then
         Call.Acceptor_Prev_Priority := Acceptor_Prio;
         Set_Priority (Acceptor, Caller_Prio);
      else
         Call.Acceptor_Prev_Priority := Priority_Not_Boosted;
      end if;
   end Boost_Priority;

   -----------------
   -- Call_Simple --
   -----------------

   procedure Call_Simple
     (Acceptor           : Task_Id;
      E                  : Task_Entry_Index;
      Uninterpreted_Data : System.Address)
   is
      Rendezvous_Successful : Boolean;
      pragma Unreferenced (Rendezvous_Successful);

   begin
      --  If pragma Detect_Blocking is active then Program_Error must be
      --  raised if this potentially blocking operation is called from a
      --  protected action.

      if System.Tasking.Detect_Blocking
        and then STPO.Self.Common.Protected_Action_Nesting > 0
      then
         raise Program_Error with
           "potentially blocking operation";
      end if;

      Call_Synchronous
        (Acceptor, E, Uninterpreted_Data, Simple_Call, Rendezvous_Successful);
   end Call_Simple;

   ----------------------
   -- Call_Synchronous --
   ----------------------

   procedure Call_Synchronous
     (Acceptor              : Task_Id;
      E                     : Task_Entry_Index;
      Uninterpreted_Data    : System.Address;
      Mode                  : Call_Modes;
      Rendezvous_Successful : out Boolean)
   is
      Self_Id    : constant Task_Id := STPO.Self;
      Level      : ATC_Level;
      Entry_Call : Entry_Call_Link;

   begin
      pragma Assert (Mode /= Asynchronous_Call);

      Local_Defer_Abort (Self_Id);
      Self_Id.ATC_Nesting_Level := Self_Id.ATC_Nesting_Level + 1;
      pragma Debug
        (Debug.Trace (Self_Id, "CS: entered ATC level: " &
         ATC_Level'Image (Self_Id.ATC_Nesting_Level), 'A'));
      Level := Self_Id.ATC_Nesting_Level;
      Entry_Call := Self_Id.Entry_Calls (Level)'Access;
      Entry_Call.Next := null;
      Entry_Call.Mode := Mode;
      Entry_Call.Cancellation_Attempted := False;

      --  If this is a call made inside of an abort deferred region,
      --  the call should be never abortable.

      Entry_Call.State :=
        (if Self_Id.Deferral_Level > 1
         then Never_Abortable
         else Now_Abortable);

      Entry_Call.E := Entry_Index (E);
      Entry_Call.Prio := Get_Priority (Self_Id);
      Entry_Call.Uninterpreted_Data := Uninterpreted_Data;
      Entry_Call.Called_Task := Acceptor;
      Entry_Call.Exception_To_Raise := Ada.Exceptions.Null_Id;
      Entry_Call.With_Abort := True;

      --  Note: the caller will undefer abort on return (see WARNING above)

      if not Task_Do_Or_Queue (Self_Id, Entry_Call) then
         STPO.Write_Lock (Self_Id);
         Utilities.Exit_One_ATC_Level (Self_Id);
         STPO.Unlock (Self_Id);
         Local_Undefer_Abort (Self_Id);

         raise Tasking_Error;
      end if;

      STPO.Write_Lock (Self_Id);
      pragma Debug
        (Debug.Trace (Self_Id, "Call_Synchronous: wait", 'R'));
      Entry_Calls.Wait_For_Completion (Entry_Call);
      pragma Debug
        (Debug.Trace (Self_Id, "Call_Synchronous: done waiting", 'R'));
      Rendezvous_Successful := Entry_Call.State = Done;
      STPO.Unlock (Self_Id);
      Local_Undefer_Abort (Self_Id);
      Entry_Calls.Check_Exception (Self_Id, Entry_Call);
   end Call_Synchronous;

   --------------
   -- Callable --
   --------------

   function Callable (T : Task_Id) return Boolean is
      Result  : Boolean;
      Self_Id : constant Task_Id := STPO.Self;

   begin
      Initialization.Defer_Abort_Nestable (Self_Id);
      STPO.Write_Lock (T);
      Result := T.Callable;
      STPO.Unlock (T);
      Initialization.Undefer_Abort_Nestable (Self_Id);

      return Result;
   end Callable;

   ----------------------------
   -- Cancel_Task_Entry_Call --
   ----------------------------

   procedure Cancel_Task_Entry_Call (Cancelled : out Boolean) is
   begin
      Entry_Calls.Try_To_Cancel_Entry_Call (Cancelled);
   end Cancel_Task_Entry_Call;

   -------------------------
   -- Complete_Rendezvous --
   -------------------------

   procedure Complete_Rendezvous is
   begin
      Local_Complete_Rendezvous (Ada.Exceptions.Null_Id);
   end Complete_Rendezvous;

   -------------------------------------
   -- Exceptional_Complete_Rendezvous --
   -------------------------------------

   procedure Exceptional_Complete_Rendezvous
     (Ex : Ada.Exceptions.Exception_Id)
   is
      procedure Internal_Reraise;
      pragma No_Return (Internal_Reraise);
      pragma Import (C, Internal_Reraise, "__gnat_reraise");

   begin
      Local_Complete_Rendezvous (Ex);
      Internal_Reraise;

      --  ??? Do we need to give precedence to Program_Error that might be
      --  raised due to failure of finalization, over Tasking_Error from
      --  failure of requeue?
   end Exceptional_Complete_Rendezvous;

   -------------------------------
   -- Local_Complete_Rendezvous --
   -------------------------------

   procedure Local_Complete_Rendezvous (Ex : Ada.Exceptions.Exception_Id) is
      Self_Id                : constant Task_Id := STPO.Self;
      Entry_Call             : Entry_Call_Link := Self_Id.Common.Call;
      Caller                 : Task_Id;
      Called_PO              : STPE.Protection_Entries_Access;
      Acceptor_Prev_Priority : Integer;

      Ceiling_Violation : Boolean;

      use type Ada.Exceptions.Exception_Id;
      procedure Transfer_Occurrence
        (Target : Ada.Exceptions.Exception_Occurrence_Access;
         Source : Ada.Exceptions.Exception_Occurrence);
      pragma Import (C, Transfer_Occurrence, "__gnat_transfer_occurrence");

   begin
      --  The deferral level is critical here, since we want to raise an
      --  exception or allow abort to take place, if there is an exception or
      --  abort pending.

      pragma Debug
        (Debug.Trace (Self_Id, "Local_Complete_Rendezvous", 'R'));

      Initialization.Defer_Abort (Self_Id);

      --  We need to clean up any accepts which Self may have been serving when
      --  it was aborted.

      if Ex = Standard'Abort_Signal'Identity then
         while Entry_Call /= null loop
            Entry_Call.Exception_To_Raise := Tasking_Error'Identity;

            --  All forms of accept make sure that the acceptor is not
            --  completed, before accepting further calls, so that we
            --  can be sure that no further calls are made after the
            --  current calls are purged.

            Caller := Entry_Call.Self;

            --  Take write lock. This follows the lock precedence rule that
            --  Caller may be locked while holding lock of Acceptor. Complete
            --  the call abnormally, with exception.

            STPO.Write_Lock (Caller);
            Initialization.Wakeup_Entry_Caller (Self_Id, Entry_Call, Done);
            STPO.Unlock (Caller);
            Entry_Call := Entry_Call.Acceptor_Prev_Call;
         end loop;
      else
         Caller := Entry_Call.Self;

         if Entry_Call.Needs_Requeue then

            --  We dare not lock Self_Id at the same time as Caller, for fear
            --  of deadlock.

            Entry_Call.Needs_Requeue := False;
            Self_Id.Common.Call := Entry_Call.Acceptor_Prev_Call;

            if Entry_Call.Called_Task /= null then

               --  Requeue to another task entry

               if not Task_Do_Or_Queue (Self_Id, Entry_Call) then
                  Initialization.Undefer_Abort (Self_Id);
                  raise Tasking_Error;
               end if;
            else
               --  Requeue to a protected entry

               Called_PO := POE.To_Protection (Entry_Call.Called_PO);
               STPE.Lock_Entries_With_Status (Called_PO, Ceiling_Violation);

               if Ceiling_Violation then
                  pragma Assert (Ex = Ada.Exceptions.Null_Id);
                  Entry_Call.Exception_To_Raise := Program_Error'Identity;
                  STPO.Write_Lock (Caller);
                  Initialization.Wakeup_Entry_Caller
                    (Self_Id, Entry_Call, Done);
                  STPO.Unlock (Caller);

               else
                  POO.PO_Do_Or_Queue (Self_Id, Called_PO, Entry_Call);
                  POO.PO_Service_Entries (Self_Id, Called_PO);
               end if;
            end if;

            Entry_Calls.Reset_Priority
              (Self_Id, Entry_Call.Acceptor_Prev_Priority);

         else
            --  The call does not need to be requeued

            Self_Id.Common.Call := Entry_Call.Acceptor_Prev_Call;
            Entry_Call.Exception_To_Raise := Ex;
            STPO.Write_Lock (Caller);

            --  Done with Caller locked to make sure that Wakeup is not lost

            if Ex /= Ada.Exceptions.Null_Id then
               Transfer_Occurrence
                 (Caller.Common.Compiler_Data.Current_Excep'Access,
                  Self_Id.Common.Compiler_Data.Current_Excep);
            end if;

            Acceptor_Prev_Priority := Entry_Call.Acceptor_Prev_Priority;
            Initialization.Wakeup_Entry_Caller (Self_Id, Entry_Call, Done);

            STPO.Unlock (Caller);
            Entry_Calls.Reset_Priority (Self_Id, Acceptor_Prev_Priority);
         end if;
      end if;

      Initialization.Undefer_Abort (Self_Id);
   end Local_Complete_Rendezvous;

   -------------------------------------
   -- Requeue_Protected_To_Task_Entry --
   -------------------------------------

   procedure Requeue_Protected_To_Task_Entry
     (Object     : STPE.Protection_Entries_Access;
      Acceptor   : Task_Id;
      E          : Task_Entry_Index;
      With_Abort : Boolean)
   is
      Entry_Call : constant Entry_Call_Link := Object.Call_In_Progress;
   begin
      pragma Assert (STPO.Self.Deferral_Level > 0);

      Entry_Call.E := Entry_Index (E);
      Entry_Call.Called_Task := Acceptor;
      Entry_Call.Called_PO := Null_Address;
      Entry_Call.With_Abort := With_Abort;
      Object.Call_In_Progress := null;
   end Requeue_Protected_To_Task_Entry;

   ------------------------
   -- Requeue_Task_Entry --
   ------------------------

   procedure Requeue_Task_Entry
     (Acceptor   : Task_Id;
      E          : Task_Entry_Index;
      With_Abort : Boolean)
   is
      Self_Id    : constant Task_Id := STPO.Self;
      Entry_Call : constant Entry_Call_Link := Self_Id.Common.Call;
   begin
      Initialization.Defer_Abort (Self_Id);
      Entry_Call.Needs_Requeue := True;
      Entry_Call.With_Abort := With_Abort;
      Entry_Call.E := Entry_Index (E);
      Entry_Call.Called_Task := Acceptor;
      Initialization.Undefer_Abort (Self_Id);
   end Requeue_Task_Entry;

   --------------------
   -- Selective_Wait --
   --------------------

   procedure Selective_Wait
     (Open_Accepts       : Accept_List_Access;
      Select_Mode        : Select_Modes;
      Uninterpreted_Data : out System.Address;
      Index              : out Select_Index)
   is
      Self_Id          : constant Task_Id := STPO.Self;
      Entry_Call       : Entry_Call_Link;
      Treatment        : Select_Treatment;
      Caller           : Task_Id;
      Selection        : Select_Index;
      Open_Alternative : Boolean;

   begin
      Initialization.Defer_Abort (Self_Id);
      STPO.Write_Lock (Self_Id);

      if not Self_Id.Callable then
         pragma Assert (Self_Id.Pending_ATC_Level = Level_Completed_Task);

         pragma Assert (Self_Id.Pending_Action);

         STPO.Unlock (Self_Id);

         --  ??? In some cases abort is deferred more than once. Need to
         --  figure out why this happens.

         if Self_Id.Deferral_Level > 1 then
            Self_Id.Deferral_Level := 1;
         end if;

         Initialization.Undefer_Abort (Self_Id);

         --  Should never get here ???

         pragma Assert (Standard.False);
         raise Standard'Abort_Signal;
      end if;

      pragma Assert (Open_Accepts /= null);

      Uninterpreted_Data := Null_Address;

      Queuing.Select_Task_Entry_Call
        (Self_Id, Open_Accepts, Entry_Call, Selection, Open_Alternative);

      --  Determine the kind and disposition of the select

      Treatment := Default_Treatment (Select_Mode);
      Self_Id.Chosen_Index := No_Rendezvous;

      if Open_Alternative then
         if Entry_Call /= null then
            if Open_Accepts (Selection).Null_Body then
               Treatment := Accept_Alternative_Completed;
            else
               Setup_For_Rendezvous_With_Body (Entry_Call, Self_Id);
               Treatment := Accept_Alternative_Selected;
            end if;

            Self_Id.Chosen_Index := Selection;

         elsif Treatment = No_Alternative_Open then
            Treatment := Accept_Alternative_Open;
         end if;
      end if;

      --  Handle the select according to the disposition selected above

      case Treatment is
         when Accept_Alternative_Selected =>

            --  Ready to rendezvous

            Uninterpreted_Data := Self_Id.Common.Call.Uninterpreted_Data;

            --  In this case the accept body is not Null_Body. Defer abort
            --  until it gets into the accept body. The compiler has inserted
            --  a call to Abort_Undefer as part of the entry expansion.

            pragma Assert (Self_Id.Deferral_Level = 1);

            Initialization.Defer_Abort_Nestable (Self_Id);
            STPO.Unlock (Self_Id);

         when Accept_Alternative_Completed =>

            --  Accept body is null, so rendezvous is over immediately

            STPO.Unlock (Self_Id);
            Caller := Entry_Call.Self;

            STPO.Write_Lock (Caller);
            Initialization.Wakeup_Entry_Caller (Self_Id, Entry_Call, Done);
            STPO.Unlock (Caller);

         when Accept_Alternative_Open =>

            --  Wait for caller

            Self_Id.Open_Accepts := Open_Accepts;
            pragma Debug
              (Debug.Trace (Self_Id, "Selective_Wait: wait", 'R'));

            Wait_For_Call (Self_Id);

            pragma Assert (Self_Id.Open_Accepts = null);

            --  Self_Id.Common.Call should already be updated by the Caller if
            --  not aborted. It might also be ready to do rendezvous even if
            --  this wakes up due to an abort. Therefore, if the call is not
            --  empty we need to do the rendezvous if the accept body is not
            --  Null_Body.

            --  Aren't the first two conditions below redundant???

            if Self_Id.Chosen_Index /= No_Rendezvous
              and then Self_Id.Common.Call /= null
              and then not Open_Accepts (Self_Id.Chosen_Index).Null_Body
            then
               Uninterpreted_Data := Self_Id.Common.Call.Uninterpreted_Data;

               pragma Assert
                 (Self_Id.Deferral_Level = 1
                   or else
                     (Self_Id.Deferral_Level = 0
                       and then not Restrictions.Abort_Allowed));

               Initialization.Defer_Abort_Nestable (Self_Id);

               --  Leave abort deferred until the accept body
               --  The compiler has inserted a call to Abort_Undefer as part of
               --  the entry expansion.
            end if;

            STPO.Unlock (Self_Id);

         when Else_Selected =>
            pragma Assert (Self_Id.Open_Accepts = null);

            STPO.Unlock (Self_Id);

         when Terminate_Selected =>

            --  Terminate alternative is open

            Self_Id.Open_Accepts := Open_Accepts;
            Self_Id.Common.State := Acceptor_Sleep;

            --  Notify ancestors that this task is on a terminate alternative

            STPO.Unlock (Self_Id);
            Utilities.Make_Passive (Self_Id, Task_Completed => False);
            STPO.Write_Lock (Self_Id);

            --  Wait for normal entry call or termination

            Wait_For_Call (Self_Id);

            pragma Assert (Self_Id.Open_Accepts = null);

            if Self_Id.Terminate_Alternative then

               --  An entry call should have reset this to False, so we must be
               --  aborted. We cannot be in an async. select, since that is not
               --  legal, so the abort must be of the entire task. Therefore,
               --  we do not need to cancel the terminate alternative. The
               --  cleanup will be done in Complete_Master.

               pragma Assert
                  (Self_Id.Pending_ATC_Level = Level_Completed_Task);
               pragma Assert (Self_Id.Awake_Count = 0);

               STPO.Unlock (Self_Id);

               Index := Self_Id.Chosen_Index;
               Initialization.Undefer_Abort_Nestable (Self_Id);

               if Self_Id.Pending_Action then
                  Initialization.Do_Pending_Action (Self_Id);
               end if;

               return;

            else
               --  Self_Id.Common.Call and Self_Id.Chosen_Index
               --  should already be updated by the Caller.

               if Self_Id.Chosen_Index /= No_Rendezvous
                 and then not Open_Accepts (Self_Id.Chosen_Index).Null_Body
               then
                  Uninterpreted_Data := Self_Id.Common.Call.Uninterpreted_Data;

                  pragma Assert (Self_Id.Deferral_Level = 1);

                  --  We need an extra defer here, to keep abort
                  --  deferred until we get into the accept body
                  --  The compiler has inserted a call to Abort_Undefer as part
                  --  of the entry expansion.

                  Initialization.Defer_Abort_Nestable (Self_Id);
               end if;
            end if;

            STPO.Unlock (Self_Id);

         when No_Alternative_Open =>

            --  In this case, Index will be No_Rendezvous on return, which
            --  should cause a Program_Error if it is not a Delay_Mode.

            --  If delay alternative exists (Delay_Mode) we should suspend
            --  until the delay expires.

            Self_Id.Open_Accepts := null;

            if Select_Mode = Delay_Mode then
               Self_Id.Common.State := Delay_Sleep;

               loop
                  exit when
                    Self_Id.Pending_ATC_Level < Self_Id.ATC_Nesting_Level;
                  Sleep (Self_Id, Delay_Sleep);
               end loop;

               Self_Id.Common.State := Runnable;
               STPO.Unlock (Self_Id);

            else
               STPO.Unlock (Self_Id);
               Initialization.Undefer_Abort (Self_Id);
               raise Program_Error with "entry call not a delay mode";
            end if;
      end case;

      --  Caller has been chosen

      --  Self_Id.Common.Call should already be updated by the Caller.

      --  Self_Id.Chosen_Index should either be updated by the Caller
      --  or by Test_Selective_Wait.

      --  On return, we sill start rendezvous unless the accept body is
      --  null. In the latter case, we will have already completed the RV.

      Index := Self_Id.Chosen_Index;
      Initialization.Undefer_Abort_Nestable (Self_Id);
   end Selective_Wait;

   ------------------------------------
   -- Setup_For_Rendezvous_With_Body --
   ------------------------------------

   procedure Setup_For_Rendezvous_With_Body
     (Entry_Call : Entry_Call_Link;
      Acceptor   : Task_Id) is
   begin
      Entry_Call.Acceptor_Prev_Call := Acceptor.Common.Call;
      Acceptor.Common.Call := Entry_Call;

      if Entry_Call.State = Now_Abortable then
         Entry_Call.State := Was_Abortable;
      end if;

      Boost_Priority (Entry_Call, Acceptor);
   end Setup_For_Rendezvous_With_Body;

   ----------------
   -- Task_Count --
   ----------------

   function Task_Count (E : Task_Entry_Index) return Natural is
      Self_Id      : constant Task_Id := STPO.Self;
      Return_Count : Natural;

   begin
      Initialization.Defer_Abort (Self_Id);
      STPO.Write_Lock (Self_Id);
      Return_Count := Queuing.Count_Waiting (Self_Id.Entry_Queues (E));
      STPO.Unlock (Self_Id);
      Initialization.Undefer_Abort (Self_Id);

      return Return_Count;
   end Task_Count;

   ----------------------
   -- Task_Do_Or_Queue --
   ----------------------

   function Task_Do_Or_Queue
     (Self_ID    : Task_Id;
      Entry_Call : Entry_Call_Link) return Boolean
   is
      E             : constant Task_Entry_Index :=
                        Task_Entry_Index (Entry_Call.E);
      Old_State     : constant Entry_Call_State := Entry_Call.State;
      Acceptor      : constant Task_Id := Entry_Call.Called_Task;
      Parent        : constant Task_Id := Acceptor.Common.Parent;
      Null_Body     : Boolean;

   begin
      --  Find out whether Entry_Call can be accepted immediately

      --    If the Acceptor is not callable, return False.
      --    If the rendezvous can start, initiate it.
      --    If the accept-body is trivial, also complete the rendezvous.
      --    If the acceptor is not ready, enqueue the call.

      --  This should have a special case for Accept_Call and Accept_Trivial,
      --  so that we don't have the loop setup overhead, below.

      --  The call state Done is used here and elsewhere to include both the
      --  case of normal successful completion, and the case of an exception
      --  being raised. The difference is that if an exception is raised no one
      --  will pay attention to the fact that State = Done. Instead the
      --  exception will be raised in Undefer_Abort, and control will skip past
      --  the place where we normally would resume from an entry call.

      pragma Assert (not Queuing.Onqueue (Entry_Call));

      --  We rely that the call is off-queue for protection, that the caller
      --  will not exit the Entry_Caller_Sleep, and so will not reuse the call
      --  record for another call. We rely on the Caller's lock for call State
      --  mod's.

      --  If Acceptor.Terminate_Alternative is True, we need to lock Parent and
      --  Acceptor, in that order; otherwise, we only need a lock on Acceptor.
      --  However, we can't check Acceptor.Terminate_Alternative until Acceptor
      --  is locked. Therefore, we need to lock both. Attempts to avoid locking
      --  Parent tend to result in race conditions. It would work to unlock
      --  Parent immediately upon finding Acceptor.Terminate_Alternative to be
      --  False, but that violates the rule of properly nested locking (see
      --  System.Tasking).

      STPO.Write_Lock (Parent);
      STPO.Write_Lock (Acceptor);

      --  If the acceptor is not callable, abort the call and return False

      if not Acceptor.Callable then
         STPO.Unlock (Acceptor);
         STPO.Unlock (Parent);

         pragma Assert (Entry_Call.State < Done);

         --  In case we are not the caller, set up the caller
         --  to raise Tasking_Error when it wakes up.

         STPO.Write_Lock (Entry_Call.Self);
         Entry_Call.Exception_To_Raise := Tasking_Error'Identity;
         Initialization.Wakeup_Entry_Caller (Self_ID, Entry_Call, Done);
         STPO.Unlock (Entry_Call.Self);

         return False;
      end if;

      --  Try to serve the call immediately

      if Acceptor.Open_Accepts /= null then
         for J in Acceptor.Open_Accepts'Range loop
            if Entry_Call.E = Entry_Index (Acceptor.Open_Accepts (J).S) then

               --  Commit acceptor to rendezvous with us

               Acceptor.Chosen_Index := J;
               Null_Body := Acceptor.Open_Accepts (J).Null_Body;
               Acceptor.Open_Accepts := null;

               --  Prevent abort while call is being served

               if Entry_Call.State = Now_Abortable then
                  Entry_Call.State := Was_Abortable;
               end if;

               if Acceptor.Terminate_Alternative then

                  --  Cancel terminate alternative. See matching code in
                  --  Selective_Wait and Vulnerable_Complete_Master.

                  Acceptor.Terminate_Alternative := False;
                  Acceptor.Awake_Count := Acceptor.Awake_Count + 1;

                  if Acceptor.Awake_Count = 1 then

                     --  Notify parent that acceptor is awake

                     pragma Assert (Parent.Awake_Count > 0);

                     Parent.Awake_Count := Parent.Awake_Count + 1;

                     if Parent.Common.State = Master_Completion_Sleep
                       and then Acceptor.Master_Of_Task = Parent.Master_Within
                     then
                        Parent.Common.Wait_Count :=
                          Parent.Common.Wait_Count + 1;
                     end if;
                  end if;
               end if;

               if Null_Body then

                  --  Rendezvous is over immediately

                  STPO.Wakeup (Acceptor, Acceptor_Sleep);
                  STPO.Unlock (Acceptor);
                  STPO.Unlock (Parent);

                  STPO.Write_Lock (Entry_Call.Self);
                  Initialization.Wakeup_Entry_Caller
                    (Self_ID, Entry_Call, Done);
                  STPO.Unlock (Entry_Call.Self);

               else
                  Setup_For_Rendezvous_With_Body (Entry_Call, Acceptor);

                  --  For terminate_alternative, acceptor may not be asleep
                  --  yet, so we skip the wakeup

                  if Acceptor.Common.State /= Runnable then
                     STPO.Wakeup (Acceptor, Acceptor_Sleep);
                  end if;

                  STPO.Unlock (Acceptor);
                  STPO.Unlock (Parent);
               end if;

               return True;
            end if;
         end loop;

         --  The acceptor is accepting, but not this entry
      end if;

      --  If the acceptor was ready to accept this call,
      --  we would not have gotten this far, so now we should
      --  (re)enqueue the call, if the mode permits that.

      --  If the call is timed, it may have timed out before the requeue,
      --  in the unusual case where the current accept has taken longer than
      --  the given delay. In that case the requeue is cancelled, and the
      --  outer timed call will be aborted.

      if Entry_Call.Mode = Conditional_Call
        or else
          (Entry_Call.Mode = Timed_Call
            and then Entry_Call.With_Abort
            and then Entry_Call.Cancellation_Attempted)
      then
         STPO.Unlock (Acceptor);
         STPO.Unlock (Parent);

         STPO.Write_Lock (Entry_Call.Self);

         pragma Assert (Entry_Call.State >= Was_Abortable);

         Initialization.Wakeup_Entry_Caller (Self_ID, Entry_Call, Cancelled);
         STPO.Unlock (Entry_Call.Self);

      else
         --  Timed_Call, Simple_Call, or Asynchronous_Call

         Queuing.Enqueue (Acceptor.Entry_Queues (E), Entry_Call);

         --  Update abortability of call

         pragma Assert (Old_State < Done);

         Entry_Call.State :=
           New_State (Entry_Call.With_Abort, Entry_Call.State);

         STPO.Unlock (Acceptor);
         STPO.Unlock (Parent);

         if Old_State /= Entry_Call.State
           and then Entry_Call.State = Now_Abortable
           and then Entry_Call.Mode /= Simple_Call
           and then Entry_Call.Self /= Self_ID

         --  Asynchronous_Call or Conditional_Call

         then
            --  Because of ATCB lock ordering rule

            STPO.Write_Lock (Entry_Call.Self);

            if Entry_Call.Self.Common.State = Async_Select_Sleep then

               --  Caller may not yet have reached wait-point

               STPO.Wakeup (Entry_Call.Self, Async_Select_Sleep);
            end if;

            STPO.Unlock (Entry_Call.Self);
         end if;
      end if;

      return True;
   end Task_Do_Or_Queue;

   ---------------------
   -- Task_Entry_Call --
   ---------------------

   procedure Task_Entry_Call
     (Acceptor              : Task_Id;
      E                     : Task_Entry_Index;
      Uninterpreted_Data    : System.Address;
      Mode                  : Call_Modes;
      Rendezvous_Successful : out Boolean)
   is
      Self_Id    : constant Task_Id := STPO.Self;
      Entry_Call : Entry_Call_Link;

   begin
      --  If pragma Detect_Blocking is active then Program_Error must be
      --  raised if this potentially blocking operation is called from a
      --  protected action.

      if System.Tasking.Detect_Blocking
        and then Self_Id.Common.Protected_Action_Nesting > 0
      then
         raise Program_Error with
           "potentially blocking operation";
      end if;

      if Mode = Simple_Call or else Mode = Conditional_Call then
         Call_Synchronous
           (Acceptor, E, Uninterpreted_Data, Mode, Rendezvous_Successful);

      else
         --  This is an asynchronous call

         --  Abort must already be deferred by the compiler-generated code.
         --  Without this, an abort that occurs between the time that this
         --  call is made and the time that the abortable part's cleanup
         --  handler is set up might miss the cleanup handler and leave the
         --  call pending.

         Self_Id.ATC_Nesting_Level := Self_Id.ATC_Nesting_Level + 1;
         pragma Debug
           (Debug.Trace (Self_Id, "TEC: entered ATC level: " &
            ATC_Level'Image (Self_Id.ATC_Nesting_Level), 'A'));
         Entry_Call := Self_Id.Entry_Calls (Self_Id.ATC_Nesting_Level)'Access;
         Entry_Call.Next := null;
         Entry_Call.Mode := Mode;
         Entry_Call.Cancellation_Attempted := False;
         Entry_Call.State := Not_Yet_Abortable;
         Entry_Call.E := Entry_Index (E);
         Entry_Call.Prio := Get_Priority (Self_Id);
         Entry_Call.Uninterpreted_Data := Uninterpreted_Data;
         Entry_Call.Called_Task := Acceptor;
         Entry_Call.Called_PO := Null_Address;
         Entry_Call.Exception_To_Raise := Ada.Exceptions.Null_Id;
         Entry_Call.With_Abort := True;

         if not Task_Do_Or_Queue (Self_Id, Entry_Call) then
            STPO.Write_Lock (Self_Id);
            Utilities.Exit_One_ATC_Level (Self_Id);
            STPO.Unlock (Self_Id);
            Initialization.Undefer_Abort (Self_Id);

            raise Tasking_Error;
         end if;

         --  The following is special for async. entry calls. If the call was
         --  not queued abortably, we need to wait until it is before
         --  proceeding with the abortable part.

         --  Wait_Until_Abortable can be called unconditionally here, but it is
         --  expensive.

         if Entry_Call.State < Was_Abortable then
            Entry_Calls.Wait_Until_Abortable (Self_Id, Entry_Call);
         end if;

         --  Note: following assignment needs to be atomic

         Rendezvous_Successful := Entry_Call.State = Done;
      end if;
   end Task_Entry_Call;

   -----------------------
   -- Task_Entry_Caller --
   -----------------------

   function Task_Entry_Caller (D : Task_Entry_Nesting_Depth) return Task_Id is
      Self_Id    : constant Task_Id := STPO.Self;
      Entry_Call : Entry_Call_Link;

   begin
      Entry_Call := Self_Id.Common.Call;

      for Depth in 1 .. D loop
         Entry_Call := Entry_Call.Acceptor_Prev_Call;
         pragma Assert (Entry_Call /= null);
      end loop;

      return Entry_Call.Self;
   end Task_Entry_Caller;

   --------------------------
   -- Timed_Selective_Wait --
   --------------------------

   procedure Timed_Selective_Wait
     (Open_Accepts       : Accept_List_Access;
      Select_Mode        : Select_Modes;
      Uninterpreted_Data : out System.Address;
      Timeout            : Duration;
      Mode               : Delay_Modes;
      Index              : out Select_Index)
   is
      Self_Id          : constant Task_Id := STPO.Self;
      Treatment        : Select_Treatment;
      Entry_Call       : Entry_Call_Link;
      Caller           : Task_Id;
      Selection        : Select_Index;
      Open_Alternative : Boolean;
      Timedout         : Boolean := False;
      Yielded          : Boolean := True;

   begin
      pragma Assert (Select_Mode = Delay_Mode);

      Initialization.Defer_Abort (Self_Id);

      --  If we are aborted here, the effect will be pending

      STPO.Write_Lock (Self_Id);

      if not Self_Id.Callable then
         pragma Assert (Self_Id.Pending_ATC_Level = Level_Completed_Task);

         pragma Assert (Self_Id.Pending_Action);

         STPO.Unlock (Self_Id);
         Initialization.Undefer_Abort (Self_Id);

         --  Should never get here ???

         pragma Assert (Standard.False);
         raise Standard'Abort_Signal;
      end if;

      Uninterpreted_Data := Null_Address;

      pragma Assert (Open_Accepts /= null);

      Queuing.Select_Task_Entry_Call
        (Self_Id, Open_Accepts, Entry_Call, Selection, Open_Alternative);

      --  Determine the kind and disposition of the select

      Treatment := Default_Treatment (Select_Mode);
      Self_Id.Chosen_Index := No_Rendezvous;

      if Open_Alternative then
         if Entry_Call /= null then
            if Open_Accepts (Selection).Null_Body then
               Treatment := Accept_Alternative_Completed;

            else
               Setup_For_Rendezvous_With_Body (Entry_Call, Self_Id);
               Treatment := Accept_Alternative_Selected;
            end if;

            Self_Id.Chosen_Index := Selection;

         elsif Treatment = No_Alternative_Open then
            Treatment := Accept_Alternative_Open;
         end if;
      end if;

      --  Handle the select according to the disposition selected above

      case Treatment is
         when Accept_Alternative_Selected =>

            --  Ready to rendezvous. In this case the accept body is not
            --  Null_Body. Defer abort until it gets into the accept body.

            Uninterpreted_Data := Self_Id.Common.Call.Uninterpreted_Data;
            Initialization.Defer_Abort_Nestable (Self_Id);
            STPO.Unlock (Self_Id);

         when Accept_Alternative_Completed =>

            --  Rendezvous is over

            STPO.Unlock (Self_Id);
            Caller := Entry_Call.Self;

            STPO.Write_Lock (Caller);
            Initialization.Wakeup_Entry_Caller (Self_Id, Entry_Call, Done);
            STPO.Unlock (Caller);

         when Accept_Alternative_Open =>

            --  Wait for caller

            Self_Id.Open_Accepts := Open_Accepts;

            --  Wait for a normal call and a pending action until the
            --  Wakeup_Time is reached.

            Self_Id.Common.State := Acceptor_Delay_Sleep;

            --  Try to remove calls to Sleep in the loop below by letting the
            --  caller a chance of getting ready immediately, using Unlock
            --  Yield. See similar action in Wait_For_Completion/Wait_For_Call.

            Unlock (Self_Id);

            if Self_Id.Open_Accepts /= null then
               Yield;
            end if;

            Write_Lock (Self_Id);

            --  Check if this task has been aborted while the lock was released

            if Self_Id.Pending_ATC_Level < Self_Id.ATC_Nesting_Level then
               Self_Id.Open_Accepts := null;
            end if;

            loop
               exit when Self_Id.Open_Accepts = null;

               if Timedout then
                  Sleep (Self_Id, Acceptor_Delay_Sleep);
               else
                  STPO.Timed_Sleep (Self_Id, Timeout, Mode,
                    Acceptor_Delay_Sleep, Timedout, Yielded);
               end if;

               if Timedout then
                  Self_Id.Open_Accepts := null;
               end if;
            end loop;

            Self_Id.Common.State := Runnable;

            --  Self_Id.Common.Call should already be updated by the Caller if
            --  not aborted. It might also be ready to do rendezvous even if
            --  this wakes up due to an abort. Therefore, if the call is not
            --  empty we need to do the rendezvous if the accept body is not
            --  Null_Body.

            if Self_Id.Chosen_Index /= No_Rendezvous
              and then Self_Id.Common.Call /= null
              and then not Open_Accepts (Self_Id.Chosen_Index).Null_Body
            then
               Uninterpreted_Data := Self_Id.Common.Call.Uninterpreted_Data;

               pragma Assert (Self_Id.Deferral_Level = 1);

               Initialization.Defer_Abort_Nestable (Self_Id);

               --  Leave abort deferred until the accept body
            end if;

            STPO.Unlock (Self_Id);

         when No_Alternative_Open =>

            --  In this case, Index will be No_Rendezvous on return. We sleep
            --  for the time we need to.

            --  Wait for a signal or timeout. A wakeup can be made
            --  for several reasons:
            --    1) Delay is expired
            --    2) Pending_Action needs to be checked
            --       (Abort, Priority change)
            --    3) Spurious wakeup

            Self_Id.Open_Accepts := null;
            Self_Id.Common.State := Acceptor_Delay_Sleep;

            STPO.Timed_Sleep (Self_Id, Timeout, Mode, Acceptor_Delay_Sleep,
              Timedout, Yielded);

            Self_Id.Common.State := Runnable;

            STPO.Unlock (Self_Id);

         when others =>

            --  Should never get here

            pragma Assert (Standard.False);
            null;
      end case;

      if not Yielded then
         Yield;
      end if;

      --  Caller has been chosen

      --  Self_Id.Common.Call should already be updated by the Caller

      --  Self_Id.Chosen_Index should either be updated by the Caller
      --  or by Test_Selective_Wait

      Index := Self_Id.Chosen_Index;
      Initialization.Undefer_Abort_Nestable (Self_Id);

      --  Start rendezvous, if not already completed
   end Timed_Selective_Wait;

   ---------------------------
   -- Timed_Task_Entry_Call --
   ---------------------------

   procedure Timed_Task_Entry_Call
     (Acceptor              : Task_Id;
      E                     : Task_Entry_Index;
      Uninterpreted_Data    : System.Address;
      Timeout               : Duration;
      Mode                  : Delay_Modes;
      Rendezvous_Successful : out Boolean)
   is
      Self_Id    : constant Task_Id := STPO.Self;
      Level      : ATC_Level;
      Entry_Call : Entry_Call_Link;

      Yielded : Boolean;
      pragma Unreferenced (Yielded);

   begin
      --  If pragma Detect_Blocking is active then Program_Error must be
      --  raised if this potentially blocking operation is called from a
      --  protected action.

      if System.Tasking.Detect_Blocking
        and then Self_Id.Common.Protected_Action_Nesting > 0
      then
         raise Program_Error with
           "potentially blocking operation";
      end if;

      Initialization.Defer_Abort (Self_Id);
      Self_Id.ATC_Nesting_Level := Self_Id.ATC_Nesting_Level + 1;

      pragma Debug
        (Debug.Trace (Self_Id, "TTEC: entered ATC level: " &
         ATC_Level'Image (Self_Id.ATC_Nesting_Level), 'A'));

      Level := Self_Id.ATC_Nesting_Level;
      Entry_Call := Self_Id.Entry_Calls (Level)'Access;
      Entry_Call.Next := null;
      Entry_Call.Mode := Timed_Call;
      Entry_Call.Cancellation_Attempted := False;

      --  If this is a call made inside of an abort deferred region,
      --  the call should be never abortable.

      Entry_Call.State :=
        (if Self_Id.Deferral_Level > 1
         then Never_Abortable
         else Now_Abortable);

      Entry_Call.E := Entry_Index (E);
      Entry_Call.Prio := Get_Priority (Self_Id);
      Entry_Call.Uninterpreted_Data := Uninterpreted_Data;
      Entry_Call.Called_Task := Acceptor;
      Entry_Call.Called_PO := Null_Address;
      Entry_Call.Exception_To_Raise := Ada.Exceptions.Null_Id;
      Entry_Call.With_Abort := True;

      --  Note: the caller will undefer abort on return (see WARNING above)

      if not Task_Do_Or_Queue (Self_Id, Entry_Call) then
         STPO.Write_Lock (Self_Id);
         Utilities.Exit_One_ATC_Level (Self_Id);
         STPO.Unlock (Self_Id);
         Initialization.Undefer_Abort (Self_Id);

         raise Tasking_Error;
      end if;

      Write_Lock (Self_Id);
      Entry_Calls.Wait_For_Completion_With_Timeout
        (Entry_Call, Timeout, Mode, Yielded);
      Unlock (Self_Id);

      --  ??? Do we need to yield in case Yielded is False

      Rendezvous_Successful := Entry_Call.State = Done;
      Initialization.Undefer_Abort (Self_Id);
      Entry_Calls.Check_Exception (Self_Id, Entry_Call);
   end Timed_Task_Entry_Call;

   -------------------
   -- Wait_For_Call --
   -------------------

   procedure Wait_For_Call (Self_Id : Task_Id) is
   begin
      Self_Id.Common.State := Acceptor_Sleep;

      --  Try to remove calls to Sleep in the loop below by letting the caller
      --  a chance of getting ready immediately, using Unlock & Yield.
      --  See similar action in Wait_For_Completion & Timed_Selective_Wait.

      Unlock (Self_Id);

      if Self_Id.Open_Accepts /= null then
         Yield;
      end if;

      Write_Lock (Self_Id);

      --  Check if this task has been aborted while the lock was released

      if Self_Id.Pending_ATC_Level < Self_Id.ATC_Nesting_Level then
         Self_Id.Open_Accepts := null;
      end if;

      loop
         exit when Self_Id.Open_Accepts = null;
         Sleep (Self_Id, Acceptor_Sleep);
      end loop;

      Self_Id.Common.State := Runnable;
   end Wait_For_Call;

end System.Tasking.Rendezvous;
