DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ B T

⟦facd871c6⟧ TextFile

    Length: 39057 (0x9891)
    Types: TextFile
    Names: »B«

Derivation

└─⟦afbc8121e⟧ Bits:30000532 8mm tape, Rational 1000, MC68020_OS2000 7_2_2
    └─ ⟦77aa8350c⟧ »DATA« 
        └─⟦f794ecd1d⟧ 
            └─⟦24d1ddd49⟧ 
                └─⟦this⟧ 

TextFile

--    The use of this system is subject to the software license terms and
--    conditions agreed upon between Rational and the Customer.
--
--                Copyright 1988 by Rational.
--
--                          RESTRICTED RIGHTS LEGEND
--
--    Use, duplication, or disclosure by the Government is subject to
--    restrictions as set forth in subdivision (b)(3)(ii) of the Rights in
--    Technical Data and Computer Software clause at 52.227-7013.
--
--
--                Rational
--                3320 Scott Boulevard
--                Santa Clara, California 95054-3197
--
--   PROPRIETARY AND CONFIDENTIAL INFORMATION OF RATIONAL;
--   USE OR COPYING WITHOUT EXPRESS WRITTEN AUTHORIZATION
--   IS STRICTLY PROHIBITED.  THIS MATERIAL IS PROTECTED AS
--   AN UNPUBLISHED WORK UNDER THE U.S. COPYRIGHT ACT OF
--   1976.  CREATED 1988.  ALL RIGHTS RESERVED.
--
--

separate (Task_Management)
package body Accepting_And_Selecting is

    pragma Suppress_All;

    -- procedure Await_Call (Wait_List : Tt.Wait_List_Skin;
    --                       Conditional : Boolean;
    --                       Selected : out Entry_Id;
    --                       Wakeup : out Reply_Kind;
    --                       Parameter_Location : Address_Ref;
    --                       Current_Task : Task_Id) is
    --     pragma Routine_Number (Runtime_Ids.Internal);
    --     --
    --     -- Upon return, Wakeup contains a useful value iff
    --     -- Selected = Null_Entry_Id.
    --
    --     Available : Mq.Wait_List_Index;
    --     Call_Msg : Entry_Call_Message;
    --     Status : Mq.Stratus;
    --     Buffer : Integer := 0;
    --     Retry : Boolean; -- only used in IPC case
    -- begin
    --     -- if Debug_Mode then
    --     --     Debugging.Put_Message ("Entered Await_Call");
    --     --     Debugging.Put_Message ("    Wait_List'First =" &
    --     --                            Integer'Image (Wait_List.List'First) &
    --     --                            ", Wait_List'Last =" &
    --     --                            Integer'Image (Wait_List.List'Last));
    --     --     Debugging.Put_Message ("    Active Wait_List Elements =");
    --     --     for I in Wait_List.List'Range loop
    --     --         if not Wait_List.List (I).Not_Active then
    --     --             if Wait_List.List (I).Ipc_Queue then
    --     --                 Debugging.Put_Message
    --     --                    ("    " & Integer'Image (I) & " is IPC queue");
    --     --             else
    --     --                 Debugging.Put_Message ("    " & Integer'Image (I));
    --     --             end if;
    --     --         end if;
    --     --     end loop;
    --     -- end if;
    --     --
    --     -- if Safety_Check and then
    --     --    not Current_Task.Action_State (Activation_Done) then
    --     --     Runtime_Exceptions.Raise_Runtime_Error
    --     --        ("Await_Call", "acceptor has not completed activation",
    --     --         Err.Acceptor_Not_Done_Activating,
    --     --         Current_Task => Current_Task);
    --     -- end if;
    --
    --     Retry_Loop:
    --         loop
    --             -- Wakeup := No_Reply;
    --             -- Call_Msg := Null_Entry_Call_Message;
    --
    --             if Conditional then
    --                 Mq.Wait_Nonblocking
    --                    (Wait_List.List'Address,
    --                     Wait_List.List'Length, Status, Available);
    --
    --                 if Status = Mq.Q_Quesemp then
    --                     Selected := Null_Entry_Id;
    --                     Wakeup := No_Reply;
    --                     return;
    --                 end if;
    --
    --                 -- if Safety_Check then
    --                 --     Checking.Check_Message_Queue_Status
    --                 --        (Status, Err.Bad_Status_From_Wait_Nonblocking,
    --                 --         Current_Task => Current_Task);
    --                 -- end if;
    --             else
    --                 Current_Task.Suspension_State := Awaiting_Entry_Call;
    --                 Release_Lock;
    --                 Mq.Wait (Wait_List.List'Address,
    --                          Wait_List.List'Length, Available);
    --                 Reacquire_Lock;
    --
    --                 -- if Debug_Mode then
    --                 --     Debugging.Put_Message ("Reply received in Await_Call");
    --                 -- end if;
    --                 --
    --                 -- if Safety_Check then
    --                 --     if Status = Mq.Q_Quedel then
    --                 --         if not Current_Task.Action_State (Abnormal) then
    --                 --             Runtime_Exceptions.Raise_Runtime_Error
    --                 --                ("Await_Call",
    --                 --                 "queues deleted, but not abnormal",
    --                 --                 Err.Reply_Queue_Already_Deleted,
    --                 --                 Current_Task => Current_Task);
    --                 --         end if;
    --                 --     else
    --                 --         Checking.Check_Message_Queue_Status
    --                 --            (Status, Err.Bad_Status_From_Wait,
    --                 --             Current_Task => Current_Task);
    --                 --     end if;
    --                 -- end if;
    --
    --                 Current_Task.Suspension_State := Not_Suspended;
    --             end if;
    --
    --             if Current_Task.Action_State (Abnormal) then
    --                 Selected := Null_Entry_Id;
    --                 Wakeup := Task_Aborted;
    --                 Message_Queue_Utilities.Purge_Reply_Queue
    --                    (Current_Task => Current_Task);
    --                 return;
    --
    --             elsif Available = 1 then
    --                 Selected := Null_Entry_Id;
    --                 Mq.Retrieve_Message
    --                    (Wait_List.List (Reply_Queue_Index).Wait_Queue,
    --                     Wakeup'Address, Reply_Message_Size);
    --                 return;
    --             else
    --                 -- Call_Msg := Message_Queue_Utilities.
    --                 --                Retrieve_Entry_Call_Message
    --                 --                (Wait_List.List (Available - 1).Wait_Queue,
    --                 --                 Current_Task => Current_Task);
    --                 Mq.Retrieve_Message
    --                    (Wait_List.List (Available - 1).Wait_Queue,
    --                     Call_Msg'Address, Entry_Call_Message_Size);
    --                 if Call_Msg.Caller /= Null_Caller then
    --                     declare
    --                         The_Caller : Task_Id :=
    --                            To_Task_Id (Call_Msg.Caller);
    --                     begin
    --                         The_Caller.Callers_Link :=
    --                            Current_Task.Callers_Head;
    --                         Current_Task.Callers_Head.Next := The_Caller;
    --                         The_Caller.Partner_Priority :=
    --                            Current_Task.Current_Priority;
    --
    --                         if Current_Task.Current_Priority <
    --                            The_Caller.Current_Priority then
    --                             Current_Task.Current_Priority :=
    --                                The_Caller.Current_Priority;
    --                         end if;
    --                     end;
    --
    --                     if Call_Msg.Timer_Id /= Null_Timer then
    --                         Message_Queue_Utilities.Cancel_Timer
    --                            (Call_Msg.Timer_Id,
    --                             Current_Task => Current_Task);
    --                     end if;
    --                     exit Retry_Loop;
    --                 else    -- IPC message
    --                     if Safety_Check and then
    --                        not Wait_List.List (Available - 1).Ipc_Queue then
    --                         Runtime_Exceptions.Raise_Runtime_Error
    --                            ("Await_Call", "IPC msg in non-IPC queue",
    --                             Err.Bad_Message_In_Queue,
    --                             Current_Task => Current_Task);
    --                     end if;
    --
    --                     Buffer := Call_Msg.Rendezvous_Params;
    --
    --                     -- Handle_Protocol may raise an exception, which
    --                     -- will try to Acquire lock
    --                     Release_Lock;
    --                     Ipc.Handle_Protocol
    --                        (Buffer => Buffer,
    --                         Slot_Data => Ipc.Message_Slot_Data
    --                                         (Call_Msg.Timer_Id),
    --                         Queue_Data =>
    --                            Message_Queue_Utilities.Get_Associated_Data
    --                               (Wait_List.List (Available - 1).Wait_Queue,
    --                                Current_Task),
    --                         Parameters => Call_Msg.Rendezvous_Params,
    --                         Ignore_Message => Retry);
    --                     Reacquire_Lock;
    --
    --                     exit when not Retry; -- only IPC case
    --                 end if;
    --             end if;
    --         end loop Retry_Loop;
    --
    --     Parameter_Location.all := Convert (Call_Msg.Rendezvous_Params);
    --
    --     if Buffer /= 0 or else Current_Task.Ipc_Buffer_List /= null then
    --         if Debug_Mode then
    --             Debugging.Put_Message ("  creating buffer stack");
    --         end if;
    --
    --         Current_Task.Ipc_Buffer_List :=
    --            Storage_Manager.New_Buffer_Item
    --               (With_Buffer => Buffer,
    --                Slot_Data => Integer (Mq.Associated_Data
    --                                         (Call_Msg.Timer_Id)),
    --                Next_Item => Current_Task.Ipc_Buffer_List);
    --     end if;
    --
    --     Selected := Entry_Id (Available - 1);
    -- end Await_Call;
    --
    -- -- pragma Inline (Await_Call);

    function Select_Rendezvous (Select_Var : Select_Info;
                                Round_Robin : in Integer;   -- really in out
                                Parameter_Location : Address_Ref)
                               --return Alternative_Number is
                               --!!Kludge workaround for MP problem
                               return Integer is
        pragma Routine_Number (Runtime_Ids.Select_Rendezvous);
        Current_Task : constant Task_Id := Get_Current_Task_And_Acquire_Lock;
        Wait_List    : Wait_List_Skin renames Current_Task.Queues.Wait_List.all;
        Branch_Table : Select_Branch_Table_Skin
            renames Current_Task.Queues.Branch_Table.all;

        subtype Index is Mq.Wait_List_Index;

        The_Entry : Entry_Id;
        Wakeup    : Reply_Kind;

        Delay_Time : Duration := Select_Var.Delay_Time;
        Delay_Alternative_Open : constant Boolean :=
           Select_Var.Form = Tt.Delay_Form and then Select_Var.Delay_Arm /= 0;
        Terminate_Alternative_Open : constant Boolean :=
           Select_Var.Form = Tt.Terminate_Form and then
              Select_Var.Delay_Arm /= 0;
        Else_Part_Present : constant Boolean := Select_Var.Form = Tt.Else_Form;
        Treat_As_Else : constant Boolean :=
           Else_Part_Present or else
              (Delay_Alternative_Open and then Delay_Time <= 0.0);
        Doing_Delay : constant Boolean :=
           (Delay_Alternative_Open and then Delay_Time > 0.0);
        Some_Accept_Open : Boolean := False;

        Timer_Id  : Timer.Id;  
        Call_Msg  : Entry_Call_Message;
        Result    : Alternative_Number;
        Available : Index;
        Status    : Mq.Stratus;
        Buffer    : Integer := 0;
        Retry     : Boolean; -- only used in IPC case
    begin
        -- if Debug_Mode then
        --     Debugging.Put_Message ("Entered Select_Rendezvous");
        --     Debugging.Put_Message ("   Form is " &
        --                            Select_Form'Image (Select_Var.Form));
        --     Debugging.Put_Message ("   Number of arms is " &
        --                            Alternative_Number'Image (Select_Var.Arms));
        --     Debugging.Put_Message ("   Delay arm is " &
        --                            Alternative_Number'Image
        --                               (Select_Var.Delay_Arm));
        --     for I in 1 .. Select_Var.Arms loop
        --         Debugging.Put_Message
        --            ("Arm " & Alternative_Number'Image (I) & " maps to entry " &
        --             Entry_Id'Image (Select_Var.Map (I).Entry_Number) &
        --             " and quick => " &
        --             Boolean'Image (Select_Var.Map (I).Quick));
        --     end loop;
        --     Debugging.Put_Message ("Delay open => " &
        --                            Boolean'Image (Delay_Alternative_Open));
        --     Debugging.Put_Message ("Terminate open => " &
        --                            Boolean'Image (Terminate_Alternative_Open));
        --     Debugging.Put_Message ("Else present => " &
        --                            Boolean'Image (Else_Part_Present));
        --     Debugging.Put_Message ("Treating as else => " &
        --                            Boolean'Image (Treat_As_Else));
        -- end if;

        if Current_Task.Action_State (Abnormal) then
            Runtime_Exceptions.Raise_Abnormal_Task_Error (Current_Task);
        end if;

        -- first close all entries
        for I in First_Entry_Index .. Wait_List.List'Last loop
            Wait_List.List (I).Not_Active := True;
        end loop;

        declare
            The_Entry_Map : Tt.Entry_Vector renames Select_Var.Map;
        begin
            for I in 1 .. Select_Var.Arms loop
                The_Entry := The_Entry_Map (I).Entry_Number;

                if The_Entry /= Null_Entry_Id then
                    Wait_List.List (Mq.Wait_List_Index (The_Entry)).
                       Not_Active                  := False;
                    Branch_Table.Table (The_Entry) := I;
                    Some_Accept_Open               := True;
                end if;
            end loop;
        end;

        -- if Debug_Mode then
        --     Debugging.Put_Message ("    Wait_List'First =" &
        --                            Integer'Image (Wait_List.List'First) &
        --                            ", Wait_List'Last =" &
        --                            Integer'Image (Wait_List.List'Last));
        --     Debugging.Put_Message ("    Active Wait_List Elements =");
        --     for I in Wait_List.List'Range loop
        --         if not Wait_List.List (I).Not_Active then
        --             if Wait_List.List (I).Ipc_Queue then
        --                 Debugging.Put_Message
        --                    ("    " & Integer'Image (I) & " is IPC queue");
        --             else
        --                 Debugging.Put_Message ("    " & Integer'Image (I));
        --             end if;
        --         end if;
        --     end loop;
        -- end if;

        if not Some_Accept_Open and then not Delay_Alternative_Open and then
           not Terminate_Alternative_Open and then not Else_Part_Present then
            Runtime_Exceptions.Raise_Program_Error;
        end if;

        if Doing_Delay then
            Timer_Id := Message_Queue_Utilities.Start_Timer
                           (Delay_Time, Select_Timed_Out,
                            Current_Task => Current_Task);

        elsif Terminate_Alternative_Open then
            Termination_And_Abortion.Make_Eligible_For_Termination
               (Current_Task => Current_Task);
        end if;

        -- Await_Call (Current_Task => Current_Task,
        --             Wait_List => Wait_List,
        --             Conditional => Treat_As_Else,
        --             Selected => The_Entry,
        --             Wakeup => Wakeup,
        --             Parameter_Location => Parameter_Location);

        <<Await_Call_In_Select>> null;

        if Treat_As_Else then
            Mq.Wait_Nonblocking (Wait_List.List'Address,
                                 Wait_List.List'Length, Status, Available);

            if Status = Mq.Q_Quesemp or else -- no callers
               Status = Mq.Q_Empws then      -- no open alternatives
                Release_Lock;

                if Else_Part_Present then
                    return 0;
                else -- non-positive delay
                     --!! Kludge
                    return Integer (Select_Var.Delay_Arm);
                end if;
            end if;

            -- if Safety_Check then
            --     Checking.Check_Message_Queue_Status
            --        (Status, Err.Bad_Status_From_Wait_Nonblocking,
            --         Current_Task => Current_Task);
            -- end if;
        else
            Current_Task.Suspension_State := Awaiting_Entry_Call;
            Release_Lock;
            Mq.Wait (Wait_List.List'Address, Wait_List.List'Length, Available);
            Reacquire_Lock;

            -- if Debug_Mode then
            --     Debugging.Put_Message ("Reply received in Select_Rendezvous");
            -- end if;
            --
            -- if Safety_Check then
            --     if Status = Mq.Q_Quedel then
            --         if not Current_Task.Action_State (Abnormal) then
            --             Runtime_Exceptions.Raise_Runtime_Error
            --                ("Select_Rendezvous",
            --                 "queues deleted, but not abnormal",
            --                 Err.Reply_Queue_Already_Deleted,
            --                 Current_Task => Current_Task);
            --         end if;
            --     else
            --         Checking.Check_Message_Queue_Status
            --            (Status, Err.Bad_Status_From_Wait,
            --             Current_Task => Current_Task);
            --     end if;
            -- end if;

            Current_Task.Suspension_State := Not_Suspended;

            if Current_Task.Action_State (Abnormal) then
                Message_Queue_Utilities.Purge_Reply_Queue
                   (Current_Task => Current_Task);

                if Terminate_Alternative_Open then
                    Termination_And_Abortion.Make_Ineligible_For_Termination
                       (Current_Task => Current_Task);

                elsif Doing_Delay then
                    Message_Queue_Utilities.Cancel_Timer
                       (Timer_Id, Current_Task => Current_Task);
                end if;

                Runtime_Exceptions.Raise_Abnormal_Task_Error
                   (Current_Task => Current_Task);
            end if;
        end if;

        The_Entry := Entry_Id (Available - 1);

        if The_Entry = Null_Entry_Id then
            Mq.Retrieve_Message (Wait_List.List (Reply_Queue_Index).Wait_Queue,
                                 Wakeup'Address, Reply_Message_Size);

            if Terminate_Alternative_Open then
                if Safety_Check then
                    Checking.Check_Reply (Wakeup, Termination_Selected,
                                          Current_Task => Current_Task);
                end if;
                Current_Task.Action_State (Selecting_Termination) := True;
                Runtime_Exceptions.Raise_Force_Term_Error
                   (Current_Task => Current_Task);

            elsif Doing_Delay then
                if Safety_Check then
                    Checking.Check_Reply (Wakeup, Select_Timed_Out,
                                          Current_Task => Current_Task);
                end if;
                Release_Lock;
                --!!Kludge
                return Integer (Select_Var.Delay_Arm);

            elsif Safety_Check then
                Runtime_Exceptions.Raise_Runtime_Error
                   ("Select_Rendezvous",
                    "unexpected wakeup reason: " & Reply_Kind'Image (Wakeup),
                    Err.Unexpected_Reply,
                    Current_Task => Current_Task);
            end if;
        else
            -- Call_Msg := Message_Queue_Utilities.
            --                Retrieve_Entry_Call_Message
            --                (Wait_List.List (Index (The_Entry)).Wait_Queue,
            --                 Current_Task => Current_Task);
            Mq.Retrieve_Message (Wait_List.List (Index (The_Entry)).Wait_Queue,
                                 Call_Msg'Address, Entry_Call_Message_Size);

            if Terminate_Alternative_Open then
                Termination_And_Abortion.Make_Ineligible_For_Termination
                   (Current_Task => Current_Task);

            elsif Doing_Delay then
                Message_Queue_Utilities.Cancel_Timer
                   (Timer_Id,
                    Purge_If_Expired => True,
                    Current_Task     => Current_Task);
            end if;

            if Call_Msg.Caller /= Null_Caller then
                declare
                    The_Caller : Task_Id := To_Task_Id (Call_Msg.Caller);
                begin
                    The_Caller.Callers_Link        := Current_Task.Callers_Head;
                    Current_Task.Callers_Head.Next := The_Caller;
                    The_Caller.Partner_Priority    :=
                       Current_Task.Current_Priority;

                    if Current_Task.Current_Priority <
                       The_Caller.Current_Priority then
                        Current_Task.Current_Priority :=
                           The_Caller.Current_Priority;
                    end if;
                end;

                if Call_Msg.Timer_Id /= Null_Timer then
                    Message_Queue_Utilities.Cancel_Timer
                       (Call_Msg.Timer_Id, Current_Task => Current_Task);
                end if;
            else
                -- IPC message
                -- if Safety_Check and then
                --    not Wait_List.List (Index (The_Entry)).Ipc_Queue then
                --     Runtime_Exceptions.Raise_Runtime_Error
                --        ("Select_Rendezvous", "IPC msg in non-IPC queue",
                --         Err.Bad_Message_In_Queue,
                --         Current_Task => Current_Task);
                -- end if;

                Buffer := Call_Msg.Rendezvous_Params;

                -- Handle_Protocol may raise an exception, which
                -- will try to Acquire lock
                Release_Lock;
                Ipc.Handle_Protocol
                   (Buffer         => Buffer,
                    Slot_Data      => Ipc.Message_Slot_Data (Call_Msg.Timer_Id),
                    Queue_Data     =>
                       Message_Queue_Utilities.Get_Associated_Data
                          (Wait_List.List (Index (The_Entry)).Wait_Queue,
                           Current_Task),
                    Parameters     => Call_Msg.Rendezvous_Params,
                    Ignore_Message => Retry);
                Reacquire_Lock;

                if Retry then
                    goto Await_Call_In_Select;
                end if;
            end if;
        end if;

        Parameter_Location.all := Convert (Call_Msg.Rendezvous_Params);

        Result := Branch_Table.Table (The_Entry);

        if Buffer /= 0 or else Current_Task.Ipc_Buffer_List /= null then
            -- if Debug_Mode then
            --     Debugging.Put_Message ("  creating buffer item");
            -- end if;

            -- Storage_Manager.New_Buffer_Item will release the lock
            --
            Current_Task.Ipc_Buffer_List :=
               Storage_Manager.New_Buffer_Item
                  (With_Buffer => Buffer,
                   Slot_Data   => Integer (Mq.Associated_Data
                                              (Call_Msg.Timer_Id)),
                   Next_Item   => Current_Task.Ipc_Buffer_List);
        else
            Release_Lock;
        end if;

        if Select_Var.Map (Result).Quick then
            End_Accept (With_Exception => False);
        end if;

        -- if Safety_Check then
        --     Message_Queue_Utilities.Assert_Empty_Reply_Queue
        --        ("Select_Rendezvous", Current_Task => Current_Task);
        -- end if;
        --
        -- if Debug_Mode then
        --     Debugging.Put_Message ("Select_Rendezvous returning" &
        --                            Alternative_Number'Image (Result));
        -- end if;

        --!!Kludge
        return Integer (Result);
    end Select_Rendezvous;



    procedure Begin_Accept (For_Entry          : Entry_Id;
                            Parameter_Location : Address_Ref) is
        pragma Routine_Number (Runtime_Ids.Begin_Accept);

        Current_Task : constant Task_Id := Get_Current_Task_And_Acquire_Lock;
        Entry_Wait_Item : Mq.Wait_Item
            renames Current_Task.Queues.Wait_List.all.List
                       (Integer (For_Entry));
        Accept_Wait_List : Wait_List_Skin
            renames Current_Task.Queues.Accept_List.all;
        -- reply queue already set up as 0th element of accept list

        Available : Mq.Wait_List_Index;
        Call_Msg  : Entry_Call_Message;
        Buffer    : Integer := 0;
        Retry     : Boolean; -- only used in IPC case
    begin
        -- use the explicit representation of queue id here is a real
        -- kludge, but better code is generated.
        Accept_Wait_List.List (1).Wait_Queue.Upper :=
           Entry_Wait_Item.Wait_Queue.Upper;
        Accept_Wait_List.List (1).Wait_Queue.Lower :=
           Entry_Wait_Item.Wait_Queue.Lower;

        -- .. List (1).Not_Active already false

        -- if Debug_Mode then
        --     Debugging.Put_Message ("Entered Begin_Accept, Entry_Number =" &
        --                            Integer'Image (Integer (For_Entry)));
        -- end if;

        --Runtime_Exceptions.Check_For_Abnormality (Current_Task => Current_Task);
        if Current_Task.Action_State (Abnormal) then
            Runtime_Exceptions.Raise_Abnormal_Task_Error
               (Current_Task => Current_Task);
        end if;

        <<Await_Call_In_Accept>> null;

        Current_Task.Suspension_State := Awaiting_Entry_Call;
        Release_Lock;
        Mq.Wait (Accept_Wait_List.List'Address,
                 Accept_Wait_List.List'Length, Available);

        Reacquire_Lock;
        Current_Task.Suspension_State := Not_Suspended;

        -- the only possible outcomes from the wait for an accept
        -- are an abort message in the reply queue or an entry
        -- call message in the entry queue

        if Current_Task.Action_State (Abnormal) then
            Message_Queue_Utilities.Purge_Reply_Queue
               (Current_Task => Current_Task);
            Runtime_Exceptions.Raise_Abnormal_Task_Error
               (Current_Task => Current_Task);
        else
            -- Call_Msg := Message_Queue_Utilities.
            --                Retrieve_Entry_Call_Message
            --                (Wait_List.List (Available - 1).Wait_Queue,
            --                 Current_Task => Current_Task);
            Mq.Retrieve_Message (Accept_Wait_List.List (1).Wait_Queue,
                                 Call_Msg'Address, Entry_Call_Message_Size);

            if Call_Msg.Caller /= Null_Caller then
                declare
                    The_Caller : Task_Id := To_Task_Id (Call_Msg.Caller);
                begin
                    The_Caller.Callers_Link        := Current_Task.Callers_Head;
                    Current_Task.Callers_Head.Next := The_Caller;
                    The_Caller.Partner_Priority    :=
                       Current_Task.Current_Priority;

                    if Current_Task.Current_Priority <
                       The_Caller.Current_Priority then
                        Current_Task.Current_Priority :=
                           The_Caller.Current_Priority;
                    end if;
                end;

                if Call_Msg.Timer_Id /= Null_Timer then
                    Message_Queue_Utilities.Cancel_Timer
                       (Call_Msg.Timer_Id, Current_Task => Current_Task);
                end if;

            else -- IPC message

                Buffer := Call_Msg.Rendezvous_Params;

                -- Handle_Protocol may raise an exception, which
                -- will try to Acquire lock
                Release_Lock;
                Ipc.Handle_Protocol
                   (Buffer => Buffer,
                    Slot_Data => Ipc.Message_Slot_Data (Call_Msg.Timer_Id),
                    Queue_Data => Message_Queue_Utilities.Get_Associated_Data
                                     (Accept_Wait_List.List (1).Wait_Queue,
                                      Current_Task),
                    Parameters => Call_Msg.Rendezvous_Params,
                    Ignore_Message => Retry);
                Reacquire_Lock;

                if Retry then
                    goto Await_Call_In_Accept;
                end if;-- only IPC case
            end if;
        end if;

        Parameter_Location.all := Convert (Call_Msg.Rendezvous_Params);

        if Buffer /= 0 or else Current_Task.Ipc_Buffer_List /= null then
            -- Storage_Manager.New_Buffer_Item will release the lock
            --
            Current_Task.Ipc_Buffer_List :=
               Storage_Manager.New_Buffer_Item
                  (With_Buffer => Buffer,
                   Slot_Data   => Integer (Mq.Associated_Data
                                              (Call_Msg.Timer_Id)),
                   Next_Item   => Current_Task.Ipc_Buffer_List);
        else
            Release_Lock;
        end if;
    end Begin_Accept;


    procedure End_Accept (With_Exception : Boolean) is  
        pragma Routine_Number (Runtime_Ids.End_Accept);
        Current_Task : constant Task_Id := Get_Current_Task_And_Acquire_Lock;
        Have_Buffer_Stack : constant Boolean :=
           (Current_Task.Ipc_Buffer_List /= null);
        Caller : Task_Id;
        Prior_Priority : Priority;
    begin
        -- if Debug_Mode then
        --     Debugging.Put_Message ("Entered End_Accept with exception => " &
        --                            Boolean'Image (With_Exception));
        -- end if;

        if not Have_Buffer_Stack or else
           Current_Task.Ipc_Buffer_List.Buffer = 0 then
            -- not an IPC rendezvous

            Caller         := Current_Task.Callers_Head.Next;
            Prior_Priority := Caller.Partner_Priority;

            -- if Safety_Check then
            --     Checking.Check_Task (Caller, "End_Accept",
            --                          Current_Task => Current_Task);
            -- end if;

            if Current_Task.Action_State (Abnormal) then
                Caller.Exception_Id := Exceptions.Tasking_Error;
                Caller.Action_State (Exception_Pending) := True;  
            elsif With_Exception then
                Caller.Exception_Id := Current_Task.Exception_Id;
                Caller.Action_State (Exception_Pending) := True;  
            end if;

            Current_Task.Callers_Head := Caller.Callers_Link;
            Caller.Callers_Link.Next  := null;

            --  Message_Queue_Utilities.Send_Reply
            --    (Caller, Rendezvous_Done, Current_Task => Current_Task);
            declare
                Status     : Mq.Stratus;
                Message_Id : Mq.Message_Id;
                The_Reply  : Reply_Kind := Rendezvous_Done;
            begin
                Mq.Send_Without_Priority
                   (Value => Integer (Rendezvous_Done),
                    Queue => Caller.Queues.Wait_List.List (Reply_Queue_Index).
                                Wait_Queue);
            end;

            if Prior_Priority /= Current_Task.Current_Priority then
                Current_Task.Current_Priority := Prior_Priority;
                declare
                    Reset_Priority : Integer := Integer (Prior_Priority);
                begin
                    if Reset_Priority < Minimum_Os_Priority then
                        Reset_Priority := Minimum_Os_Priority;
                    end if;

                    Release_Lock;

                    Process_Ops.Set_Priority
                       (Process_Id => Current_Task.Process_Id,
                        Priority   => Reset_Priority);

                    -- if Safety_Check then
                    --     Checking.Check_Os9_Ops_Status
                    --        (Status, Err.Bad_Status_From_Set_Priority,
                    --         Current_Task => Current_Task);
                    -- end if;
                end;
            else
                Release_Lock;
            end if;

        else    -- an IPC rendezvous
            Release_Lock;
            Ipc.Release_Buffer (Current_Task.Ipc_Buffer_List.Buffer,
                                Ipc.Message_Slot_Data
                                   (Current_Task.Ipc_Buffer_List.Slot_Data));
            Current_Task.Ipc_Buffer_List.Buffer := 0;
        end if;

        if Have_Buffer_Stack then  -- pop a level
            declare
                Temp : Buffer_List := Current_Task.Ipc_Buffer_List.Next;
            begin
                Current_Task.Ipc_Buffer_List.Next := Buffer_Free_List;
                Buffer_Free_List := Current_Task.Ipc_Buffer_List;
                Current_Task.Ipc_Buffer_List := Temp;
            end;
        end if;

        --Runtime_Exceptions.Check_For_Abnormality (Current_Task => Current_Task);
        if Current_Task.Action_State (Abnormal) then
            -- must reacquire lock, since already released, and
            -- raise will also release.
            Reacquire_Lock;
            Runtime_Exceptions.Raise_Abnormal_Task_Error
               (Current_Task => Current_Task);
        end if;
    end End_Accept;

    procedure Quick_Accept (For_Entry : Entry_Id) is
        pragma Routine_Number (Runtime_Ids.Quick_Accept);

        Current_Task : constant Task_Id := Get_Current_Task_And_Acquire_Lock;
        Entry_Wait_Item : Mq.Wait_Item
            renames Current_Task.Queues.Wait_List.all.List
                       (Integer (For_Entry));
        Accept_Wait_List : Wait_List_Skin
            renames Current_Task.Queues.Accept_List.all;
        -- reply queue already set up as 0th element of accept list

        Available : Mq.Wait_List_Index;
        Call_Msg  : Entry_Call_Message;

        -- NOTE:  assume that all IPC messages have paraemeters, and
        --        hence will never be accepted via Quick_Accept.
        --
    begin
        -- do work of Begin_Accept

        -- use the explicit representation of queue id here is a real
        -- kludge, but better code is generated.
        Accept_Wait_List.List (1).Wait_Queue.Upper :=
           Entry_Wait_Item.Wait_Queue.Upper;
        Accept_Wait_List.List (1).Wait_Queue.Lower :=
           Entry_Wait_Item.Wait_Queue.Lower;

        -- .. List (1).Not_Active already false

        -- if Debug_Mode then
        --     Debugging.Put_Message ("Entered Quick_Accept, Entry_Number =" &
        --                            Integer'Image (Integer (For_Entry)));
        -- end if;

        --Runtime_Exceptions.Check_For_Abnormality (Current_Task => Current_Task);
        if Current_Task.Action_State (Abnormal) then
            Runtime_Exceptions.Raise_Abnormal_Task_Error
               (Current_Task => Current_Task);
        end if;

        Current_Task.Suspension_State := Awaiting_Entry_Call;
        Release_Lock;
        Mq.Wait (Accept_Wait_List.List'Address,
                 Accept_Wait_List.List'Length, Available);

        Reacquire_Lock;
        Current_Task.Suspension_State := Not_Suspended;

        -- the only possible outcomes from the wait for an accept
        -- are an abort message in the reply queue or an entry
        -- call message in the entry queue

        if Current_Task.Action_State (Abnormal) then
            Message_Queue_Utilities.Purge_Reply_Queue
               (Current_Task => Current_Task);

            -- raise will release the lock
            Runtime_Exceptions.Raise_Abnormal_Task_Error
               (Current_Task => Current_Task);
        else
            -- Call_Msg := Message_Queue_Utilities.
            --                Retrieve_Entry_Call_Message
            --                (Wait_List.List (Available - 1).Wait_Queue,
            --                 Current_Task => Current_Task);
            Mq.Retrieve_Message (Accept_Wait_List.List (1).Wait_Queue,
                                 Call_Msg'Address, Entry_Call_Message_Size);

            declare
                The_Caller : Task_Id := To_Task_Id (Call_Msg.Caller);
            begin
                if Call_Msg.Timer_Id /= Null_Timer then
                    Message_Queue_Utilities.Cancel_Timer
                       (Call_Msg.Timer_Id, Current_Task => Current_Task);
                end if;

                -- do work of End_Accept (With_Exception => False);

                --  Message_Queue_Utilities.Send_Reply
                --    (Caller, Rendezvous_Done, Current_Task => Current_Task);
                declare
                    Status     : Mq.Stratus;
                    Message_Id : Mq.Message_Id;
                    The_Reply  : Reply_Kind := Rendezvous_Done;
                begin
                    Mq.Send_Without_Priority
                       (Value => Integer (Rendezvous_Done),
                        Queue => The_Caller.Queues.Wait_List.List
                                    (Reply_Queue_Index).Wait_Queue);
                end;

                if Current_Task.Current_Priority <
                   The_Caller.Current_Priority then
                    declare
                        Reset_Priority : Integer :=
                           Integer (Current_Task.Current_Priority);
                    begin
                        if Reset_Priority < Minimum_Os_Priority then
                            Reset_Priority := Minimum_Os_Priority;
                        end if;

                        Release_Lock;

                        Process_Ops.Set_Priority
                           (Process_Id => Current_Task.Process_Id,
                            Priority   => Reset_Priority);

                        -- if Safety_Check then
                        --     Checking.Check_Os9_Ops_Status
                        --        (Status, Err.Bad_Status_From_Set_Priority,
                        --         Current_Task => Current_Task);
                        -- end if;
                    end;
                else
                    Release_Lock;
                end if;
            end;
        end if;
    end Quick_Accept;

end Accepting_And_Selecting;
pragma Runtime_Unit (Unit_Number         => Runtime_Ids.Runtime_Compunit,
                     Elab_Routine_Number => Runtime_Ids.Internal);