|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: B T
Length: 17174 (0x4316)
Types: TextFile
Names: »B«
└─⟦afbc8121e⟧ Bits:30000532 8mm tape, Rational 1000, MC68020_OS2000 7_2_2
└─⟦77aa8350c⟧ »DATA«
└─⟦f794ecd1d⟧
└─⟦24d1ddd49⟧
└─⟦this⟧
-- 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 Creation_And_Activation is
pragma Suppress_All;
procedure Initialize_Master (For_Layer : Layer_Id) is
pragma Routine_Number (Runtime_Ids.Initialize_Master);
Current_Task : constant Task_Id := Get_Current_Task_And_Acquire_Lock;
begin
-- if Debug_Mode then
-- Debugging.Put_Message ("Entered Initialize_Master");
-- end if;
-- For_Layer.all :=
-- Layer'(Dependent_Task_List => (Next => null),
For_Layer.Dependent_Task_List.Next := null;
-- Master_Task => Current_Task,
For_Layer.Master_Task := Current_Task;
-- Layer_Link => Current_Task.Current_Layer,
For_Layer.Layer_Link := Current_Task.Current_Layer;
-- Non_Terminated => 0,
For_Layer.Non_Terminated := 0;
-- Non_Terminable => 0,
For_Layer.Non_Terminable := 0;
-- Coldness => Warm);
For_Layer.Coldness := Warm;
Current_Task.Current_Layer := For_Layer;
-- if Safety_Check then
-- Checking.Check_Layer (For_Layer, "Initialize_Master",
-- Current_Task => Current_Task);
-- end if;
Release_Lock;
end Initialize_Master;
function Create_Task (Activation_Group : Group_Ref;
Master : Layer_Id;
Start_Addr_Ref : Address_Ref;
Entry_Count : Entry_Number;
Stack_Space : Integer;
At_Priority : Integer;
Closure : System_Address;
Instance_Variable : System_Address) return Task_Id is
pragma Routine_Number (Runtime_Ids.Create_Task);
-- ** allocate new Tcb before acquiring lock, since could raise
-- ** Storage_Error:
New_Task : Task_Id := Storage_Manager.New_Task_Control_Block;
Current_Task : constant Task_Id := Get_Current_Task_And_Acquire_Lock;
Default_Task_Priority : Priority renames Main_Priority;
begin
-- if Debug_Mode then
-- Debugging.Put_Message ("Entered Create_Task");
-- end if;
--
-- if Safety_Check then
-- if Master = null then
-- Debugging.Put_Message ("*** ERROR - No master set up for task");
-- end if;
--
-- if Activation_Group = null then
-- Debugging.Put_Message
-- ("*** ERROR - No activation group set up for task");
-- end if;
--
-- Checking.Check_Layer (Master, "Create_Task",
-- Current_Task => Current_Task);
-- end if;
--New_Task.all :=
-- Task_Control_Block'
-- (Checksum => Checksum (New_Task),
New_Task.Checksum := Checksum (New_Task);
-- Exception_Id => Exceptions.No_Error,
New_Task.Exception_Id := null; -- := Exceptions.No_Error;
-- Stack_Bounds => (Null_Address, max (Stack_Space, Default));
New_Task.Stack_Bounds.First := To_Address (0);
if Stack_Space = 0 then
New_Task.Stack_Bounds.Size := Default_Task_Stack_Size;
else
New_Task.Stack_Bounds.Size := Stack_Space;
end if;
-- Action_State => Empty_Actions,
New_Task.Action_State := (others => False);
-- Suspension_State => Not_Activated,
New_Task.Suspension_State := Not_Activated;
-- Current_Priority => Set_Priority,
if At_Priority in Priority then
New_Task.Current_Priority := At_Priority;
else
New_Task.Current_Priority := Default_Task_Priority;
end if;
-- Partner_Priority => Priority'First,
New_Task.Partner_Priority := Priority'First;
-- Code_Start_Ref => Start_Addr_Ref,
New_Task.Code_Start_Ref := Start_Addr_Ref;
-- Current_Layer => null,
New_Task.Current_Layer := null;
-- Queues => Storage_Manager.New_Queues
-- (Entry_Count, Current_Task => Current_Task),
--*** New_Task.Queues created below
-- Master_Block => Master,
New_Task.Master_Block := Master;
-- Layer_Link => List'(Next => Master.Dependent_Task_List.Next),
New_Task.Layer_Link.Next := Master.Dependent_Task_List.Next;
-- Callers_Head => Empty_List,
New_Task.Callers_Head.Next := null;
-- Callers_Link =>
-- List'(Next => Activation_Group.all), -- temporary use
New_Task.Callers_Link.Next := Activation_Group.all; -- temporary use
-- Activations_In_Progress => Convert (Closure), -- temporary use
New_Task.Activations_In_Progress := Convert (Closure); -- temporary use
-- Spare
New_Task.Spare_Word0 := 0;
-- Process_Id => 0,
New_Task.Process_Id := 0;
-- Ipc_Buffer_List => null);
New_Task.Ipc_Buffer_List := null;
New_Task.Parent_Tcb := Current_Task;
New_Task.Parent_Frame_Link := Process_Ops.Get_Fp;
New_Task.Instance_Variable := Instance_Variable;
Master.Non_Terminated := Master.Non_Terminated + 1;
Master.Non_Terminable := Master.Non_Terminable + 1;
Master.Dependent_Task_List.Next := New_Task;
Activation_Group.all := New_Task;
-- *** New_Task.Queues := ...
-- creating queues can raise Storage_Error, so cannot hold lock
Release_Lock;
New_Task.Queues := Storage_Manager.New_Queues
(Entry_Count, Current_Task => Current_Task);
-- if Debug_Mode then
-- Debugging.Put_Message ("");
-- Debugging.Put_Message ("Task_Management.Create_Task result = ");
-- Debugging.Put_Tcb (New_Task);
-- Debugging.Put_Message ("");
-- end if;
return New_Task;
end Create_Task;
procedure Activate_Offspring (Activation_Group : Group_Ref;
Perform_Elaboration_Check : Boolean) is
pragma Routine_Number (Runtime_Ids.Activate_Offspring);
Current_Task : constant Task_Id := Get_Current_Task_And_Acquire_Lock;
Next_Task : Task_Id := Activation_Group.all;
Next_Next_Task : Task_Id;
Params : Fork_Parameters;
Reply : Reply_Kind;
begin
-- if Debug_Mode then
-- Debugging.Put_Message ("Entered Activate_Offspring");
-- end if;
Runtime_Exceptions.Check_For_Abnormality (Current_Task => Current_Task);
if Perform_Elaboration_Check then
while Next_Task /= null loop
if Next_Task.Code_Start_Ref.all = To_Address (0) then
-- Terminate all unstarted tasks in the activation group
-- before raising Program_Error. C93007A tests this.
Next_Task := Activation_Group.all;
while Next_Task /= null loop
if Next_Task.Suspension_State = Not_Activated then
Termination_And_Abortion.Forced_Termination
(Next_Task,
Term_Via_Abort => False,
Current_Task => Current_Task);
end if;
Next_Task := Next_Task.Callers_Link.Next;
end loop;
Runtime_Exceptions.Raise_Program_Error;
end if;
-- Until a task is activated, the Callers_Link field is
-- used to store the link to the next member of the
-- activation group.
Next_Task := Next_Task.Callers_Link.Next;
end loop;
Next_Task := Activation_Group.all;
end if;
Current_Task.Activations_In_Progress := 0;
Params.Global_Base_Address := Process_Ops.Global_Base_Address;
Params.Code_Start := Task_Code_Start;
while Next_Task /= null loop
-- if Safety_Check then
-- if (Next_Task.Suspension_State /= Not_Activated) and then
-- ((Next_Task.Suspension_State /= Terminated) or else
-- (not Next_Task.Action_State (Abnormal))) then
-- --
-- -- A task that is aborted before it is activated has its
-- -- Suspension_State set to Terminated.
--
-- Runtime_Exceptions.Raise_Runtime_Error
-- ("Activate_Offspring",
-- "Activating an already-activated task",
-- Err.Task_Activated_Twice,
-- Current_Task => Current_Task);
-- end if;
-- end if;
-- Until a task is activated, the Callers_Link field is
-- used to store the link to the next member of the
-- activation group. The Callers_Head field is set here
-- to reference the activator.
Next_Next_Task := Next_Task.Callers_Link.Next;
if not Next_Task.Action_State (Abnormal) then
Next_Task.Suspension_State := Not_Suspended;
Next_Task.Callers_Head := List'(Next => Current_Task);
Params.New_Task_Id := Next_Task;
Params.Instance_Variable := Next_Task.Instance_Variable;
-- if Debug_Mode then
-- Debugging.Put_Message
-- ("In Activate_Offspring, about to call Os9_Ops.Fork");
-- end if;
declare
Next_Priority : Integer := Integer
(Next_Task.Current_Priority);
Stack_Size : Integer := Next_Task.Stack_Bounds.Size;
Status : Process_Ops.Status;
Minimum_Stack_Size : constant := 64;
begin
if Next_Priority < Minimum_Os_Priority then
Next_Priority := Minimum_Os_Priority;
end if;
if Stack_Size < Minimum_Stack_Size then
Stack_Size := Minimum_Stack_Size;
end if;
Process_Ops.Fork (Params'Address, Fork_Parameters_Size,
Next_Priority, Stack_Size, Status);
if Status = Process_Ops.E_Noram then
if Debug_Mode then
Debugging.Put_Message
("In Activate_Offspring, Os9_Ops.Fork failed due to insufficient available memory");
end if;
-- Update TCB and layer state since task not activated
Next_Task.Suspension_State := Not_Activated;
Termination_And_Abortion.Forced_Termination
(The_Task => Next_Task,
Term_Via_Abort => False,
Current_Task => Current_Task);
-- Simulate effect of raising storage_error (sic)
-- during child's activation.
--
Current_Task.Action_State (Exception_Pending) := True;
Current_Task.Exception_Id := Exceptions.Tasking_Error;
else
-- if Debug_Mode then
-- Debugging.Put_Message
-- ("In Activate_Offspring, after call to Os9_Ops.Fork");
-- end if;
--
-- if Safety_Check then
-- Checking.Check_Os9_Ops_Status
-- (Status, Err.Bad_Status_From_Fork,
-- Current_Task => Current_Task);
-- end if;
if Status /= Process_Ops.Success then
Debugging.Put_Message
("Got bad status from fork " &
Process_Ops.Status'Image (Status));
end if;
Current_Task.Activations_In_Progress :=
Current_Task.Activations_In_Progress + 1;
end if;
end;
end if;
Next_Task := Next_Next_Task;
end loop;
Activation_Group.all := null;
-- It is desirable that all elements of the activation group
-- be forked before any of them begin to execute user code.
-- Otherwise there may be problems with a low priority parent
-- forking a medium priority child before a high priority child;
-- it would be possible for the medium priority child to starve the
-- parent and thereby prevent its sibling from ever being forked.
-- This is currently not a problem, because a task registers itself
-- (which involves acquiring the task management serialization
-- lock) before it begins to execute user code.
if Current_Task.Activations_In_Progress > 0 then
Message_Queue_Utilities.Await_Reply
(Child_Activating, Reply, Current_Task => Current_Task);
-- if Safety_Check then
-- Checking.Check_Reply (Reply, Activation_Group_Activated,
-- Current_Task => Current_Task);
-- end if;
end if;
Runtime_Exceptions.Check_For_Pending_Exception
(Current_Task => Current_Task);
Release_Lock;
end Activate_Offspring;
procedure Notify_Parent_Internal
(Tasking_Error_Found : Boolean; Current_Task : Task_Id) is
pragma Routine_Number (Runtime_Ids.Internal);
-- While a task is activating, the Callers_Head field is
-- used to store the task_id of the parent (i.e. activator,
-- as opposed to master) task.
--
Parent : Task_Id renames Current_Task.Callers_Head.Next;
Parent_Tcb : Task_Control_Block renames Parent.all;
Parent_Offspring_Count : Integer
renames Parent_Tcb.Activations_In_Progress;
begin
-- if Debug_Mode then
-- Debugging.Put_Message ("Entered Notify_Parent");
-- end if;
if Tasking_Error_Found then
Parent_Tcb.Action_State (Exception_Pending) := True;
Parent_Tcb.Exception_Id := Exceptions.Tasking_Error;
end if;
Parent_Offspring_Count := Parent_Offspring_Count - 1;
if Parent_Offspring_Count = 0 then
Message_Queue_Utilities.Send_Reply
(Parent, Activation_Group_Activated,
Current_Task => Current_Task);
end if;
-- if Safety_Check and then
-- Current_Task.Action_State (Activation_Done) then
-- Runtime_Exceptions.Raise_Runtime_Error
-- ("Notify_Parent", "child has already notified parent",
-- Err.Parent_Notified_Twice,
-- Current_Task => Current_Task);
-- end if;
Current_Task.Action_State (Activation_Done) := True;
Runtime_Exceptions.Check_For_Abnormality (Current_Task => Current_Task);
end Notify_Parent_Internal;
procedure Notify_Parent (Tasking_Error_Found : Boolean) is
pragma Routine_Number (Runtime_Ids.Notify_Parent);
Current_Task : constant Task_Id := Get_Current_Task_And_Acquire_Lock;
begin
Notify_Parent_Internal (Tasking_Error_Found,
Current_Task => Current_Task);
Release_Lock;
end Notify_Parent;
end Creation_And_Activation;
pragma Runtime_Unit (Unit_Number => Runtime_Ids.Runtime_Compunit,
Elab_Routine_Number => Runtime_Ids.Internal);