------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Cheddar is a GNU GPL real-time scheduling analysis tool. -- This program provides services to automatically check schedulability and -- other performance criteria of real-time architecture models. -- -- Copyright (C) 2002-2020, Frank Singhoff, Alain Plantec, Jerome Legrand, -- Hai Nam Tran, Stephane Rubini -- -- The Cheddar project was started in 2002 by -- Frank Singhoff, Lab-STICC UMR CNRS 6285, Universite de Bretagne Occidentale -- -- Cheddar has been published in the "Agence de Protection des Programmes/France" in 2008. -- Since 2008, Ellidiss technologies also contributes to the development of -- Cheddar and provides industrial support. -- -- The full list of contributors and sponsors can be found in AUTHORS.txt and SPONSORS.txt -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- -- -- Contact : cheddar@listes.univ-brest.fr -- ------------------------------------------------------------------------------ -- Last update : -- $Rev$ -- $Date$ -- $Author: singhoff $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with AADL_Config; use AADL_Config; with unbounded_strings; use unbounded_strings; with Text_IO; use Text_IO; with Ada.Exceptions; use Ada.Exceptions; with Resources; use Resources; use Resources.Resource_Accesses; with translate; use translate; with processor_set; use processor_set; with resource_set; use resource_set; package body Task_Dependencies is -- Add a task in the Dependent task list -- only if it now already added -- procedure Add_Dependent_Tasks (My_Dependencies : in out Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) is Ite1 : Tasks_Iterator; A_Task : Generic_Task_Ptr; begin if not is_empty (My_Dependencies.Dependent_Tasks) then reset_iterator (My_Dependencies.Dependent_Tasks, Ite1); loop current_element (My_Dependencies.Dependent_Tasks, A_Task, Ite1); if A_Task.name = My_Task.name then return; end if; exit when is_last_element (My_Dependencies.Dependent_Tasks, Ite1); next_element (My_Dependencies.Dependent_Tasks, Ite1); end loop; end if; add (My_Dependencies.Dependent_Tasks, My_Task); end Add_Dependent_Tasks; -- Delete a dependent task if it exists -- procedure Delete_Dependent_Tasks (My_Dependencies : in out Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) is Ite1 : Tasks_Iterator; A_Task : Generic_Task_Ptr; My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; ToDelete : Boolean := True; begin -- First search in dependencies if the task is not part of another dependency. if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); case A_Half_Dep.type_of_dependency is when remote_procedure_call_dependency => if (A_Half_Dep.remote_procedure_call_client.name = My_Task.name) or (A_Half_Dep.remote_procedure_call_server.name = My_Task.name) then ToDelete := False; end if; when precedence_dependency => if (A_Half_Dep.precedence_source.name = My_Task.name) or (A_Half_Dep.precedence_sink.name = My_Task.name) then ToDelete := False; end if; when queueing_buffer_dependency => if (A_Half_Dep.buffer_dependent_task.name = My_Task.name) then ToDelete := False; end if; when asynchronous_communication_dependency => if (A_Half_Dep.asynchronous_communication_dependent_task.name = My_Task.name) then ToDelete := False; end if; when time_triggered_communication_dependency => if (A_Half_Dep.time_triggered_communication_sink.name = My_Task.name) then ToDelete := False; end if; when resource_dependency => if (A_Half_Dep.resource_dependency_task.name = My_Task.name) then ToDelete := False; end if; when black_board_Buffer_dependency => if (A_Half_Dep.black_board_dependent_task.name = My_Task.name) then ToDelete := False; end if; end case; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; if ToDelete then if not is_empty (My_Dependencies.Dependent_Tasks) then reset_iterator (My_Dependencies.Dependent_Tasks, Ite1); loop current_element (My_Dependencies.Dependent_Tasks, A_Task, Ite1); if A_Task.name = My_Task.name then delete (My_Dependencies.Dependent_Tasks, A_Task); return; end if; exit when is_last_element (My_Dependencies.Dependent_Tasks, Ite1); next_element (My_Dependencies.Dependent_Tasks, Ite1); end loop; end if; end if; end Delete_Dependent_Tasks; ------------------------------------------------------------------------- procedure Free (My_Dependencies : in out Tasks_Dependencies_Ptr) is begin free (My_Dependencies.Dependent_Tasks); free (My_Dependencies.Depends); end Free; function XML_root_String (obj : in Tasks_Dependencies_Ptr; level : in Natural := 0) return Unbounded_String is begin if (obj /= null) then return xml_root_string (obj.Depends); else return empty_string; end if; end XML_root_String; function XML_String (obj : in Tasks_Dependencies_Ptr; level : in Natural := 0) return Unbounded_String is begin if (obj /= null) then return xml_string (obj.Depends); else return empty_string; end if; end XML_String; function Export_Aadl_Properties (My_Dependencies : in Tasks_Dependencies_Ptr; Number_Of_Ht : in Natural) return Unbounded_String is My_Iterator : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; Head_Is_Written : Boolean := False; Result : Unbounded_String := empty_string; begin if Aadl_Export_Precedencies_To_Properties then if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if not Head_Is_Written then for I in 1 .. Number_Of_Ht loop Result := Result & ASCII.HT; end loop; Result := Result & To_Unbounded_String( "Cheddar_Properties::Task_Precedencies => (") & unbounded_lf; Head_Is_Written := True; else Result := Result & "," & unbounded_lf; end if; for I in 1 .. Number_Of_Ht + 1 loop Result := Result & ASCII.HT; end loop; Result := Result & """" & "instancied_" & A_Half_Dep.precedence_source.address_space_name & ".instancied_" & A_Half_Dep.precedence_source.name & """" & ", " & """" & "instancied_" & A_Half_Dep.precedence_source.address_space_name & ".instancied_" & A_Half_Dep.precedence_sink.name & """"; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator); next_element (My_Dependencies.Depends, My_Iterator); end loop; if Head_Is_Written then Result := Result & To_Unbounded_String (");") & unbounded_lf; end if; end if; end if; return Result; end Export_Aadl_Properties; procedure Duplicate (Src : in Tasks_Dependencies_Ptr; Dest : in out Tasks_Dependencies_Ptr) is begin duplicate (Src.Depends, Dest.Depends); duplicate (Src.Dependent_Tasks, Dest.Dependent_Tasks); end Duplicate; procedure Reset (My_Dependencies : in out Tasks_Dependencies_Ptr; Free_Object : in Boolean := False) is begin reset (My_Dependencies.Depends, Free_Object); reset (My_Dependencies.Dependent_Tasks, Free_Object); end Reset; procedure Put (My_Dependencies : in Tasks_Dependencies_Ptr) is begin Put ("Task list/index : "); New_Line; put (My_Dependencies.Dependent_Tasks); Put ("Dependencies : "); New_Line; put (My_Dependencies.Depends); end Put; ------------------------------------------------------------------------ --------------------------------------- -- Services below allow to add -- dependencies. --------------------------------------- -- Add ALL dependencies taken from the definition -- of a given buffer -- procedure Add_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; My_Tasks : in Tasks_Set; A_Buffer : in Buffer_Ptr) is Task1 : Generic_Task_Ptr; begin Delete_All_Task_Dependencies (My_Dependencies, A_Buffer); for I in 0 .. A_Buffer.roles.nb_entries - 1 loop Task1 := Search_Task (My_Tasks, A_Buffer.roles.entries (I).item); if A_Buffer.roles.entries (I).data.the_role = Queuing_Producer then Add_One_Task_Dependency_queueing_buffer (My_Dependencies, Task1, A_Buffer, From_Task_To_Object); else Add_One_Task_Dependency_queueing_buffer (My_Dependencies, Task1, A_Buffer, From_Object_To_Task); end if; end loop; end Add_All_Task_Dependencies; procedure Add_One_Task_Dependency_asynchronous_communication (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Task : in Generic_Task_Ptr; A_Dep : in Generic_Message_Ptr; A_Type : in Orientation_Dependency_Type; protocol_property : in Asynchronous_Communication_Protocol_Property_Type := First_Message) is A_Dep_Ptr : Dependency_Ptr; begin A_Dep_Ptr := new Dependency (asynchronous_Communication_Dependency); A_Dep_Ptr.asynchronous_communication_dependent_task := A_Task; A_Dep_Ptr.asynchronous_communication_orientation := A_Type; A_Dep_Ptr.asynchronous_communication_dependency_object := A_Dep; A_Dep_Ptr.asynchronous_communication_protocol_property := protocol_property ; add (My_Dependencies.Depends, A_Dep_Ptr); Add_Dependent_Tasks (My_Dependencies, A_Task); end Add_One_Task_Dependency_asynchronous_communication; procedure Add_One_Task_Dependency_queueing_buffer (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Task : in Generic_Task_Ptr; A_Dep : in Buffer_Ptr; A_Type : in Orientation_Dependency_Type) is A_Dep_Ptr : Dependency_Ptr; begin A_Dep_Ptr := new Dependency (Queueing_Buffer_Dependency); A_Dep_Ptr.buffer_dependent_task := A_Task; A_Dep_Ptr.buffer_orientation := A_Type; A_Dep_Ptr.buffer_dependency_object := A_Dep; add (My_Dependencies.Depends, A_Dep_Ptr); Add_Dependent_Tasks (My_Dependencies, A_Task); end Add_One_Task_Dependency_queueing_buffer; procedure Add_One_Task_Dependency_black_board_buffer (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Task : in Generic_Task_Ptr; A_Dep : in Buffer_Ptr; A_Type : in Orientation_Dependency_Type) is A_Dep_Ptr : Dependency_Ptr; begin A_Dep_Ptr := new Dependency (Black_Board_Buffer_Dependency); A_Dep_Ptr.black_board_dependent_task := A_Task; A_Dep_Ptr.black_board_orientation := A_Type; A_Dep_Ptr.black_board_dependency_object := A_Dep; add (My_Dependencies.Depends, A_Dep_Ptr); Add_Dependent_Tasks (My_Dependencies, A_Task); end Add_One_Task_Dependency_black_board_buffer; procedure Add_One_Task_Dependency_precedence (My_Dependencies : in out Tasks_Dependencies_Ptr; Source : in Generic_Task_Ptr; Sink : in Generic_Task_Ptr) is A_Dep_Ptr : Dependency_Ptr; begin A_Dep_Ptr := new Dependency (Precedence_Dependency); A_Dep_Ptr.precedence_source := Source; A_Dep_Ptr.precedence_sink := Sink; add (My_Dependencies.Depends, A_Dep_Ptr); Add_Dependent_Tasks (My_Dependencies, Source); Add_Dependent_Tasks (My_Dependencies, Sink); end Add_One_Task_Dependency_precedence; procedure Add_One_Task_Dependency_remote_procedure_call (My_Dependencies : in out Tasks_Dependencies_Ptr; client : in Generic_Task_Ptr; server : in Generic_Task_Ptr) is A_Dep_Ptr : Dependency_Ptr; begin A_Dep_Ptr := new Dependency (remote_procedure_call_Dependency); A_Dep_Ptr.remote_procedure_call_client := client; A_Dep_Ptr.remote_procedure_call_server := server; add (My_Dependencies.Depends, A_Dep_Ptr); Add_Dependent_Tasks (My_Dependencies, client); Add_Dependent_Tasks (My_Dependencies, server); end Add_One_Task_Dependency_remote_procedure_call; ------------------------------------------------------------------ function Has_Buffer_To_Read (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Boolean is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_dependent_task.name = My_Task.name) and (A_Half_Dep.buffer_orientation = From_Object_To_Task) then return True; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; return False; end Has_Buffer_To_Read; function Has_Buffer_To_Write (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Boolean is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_dependent_task.name = My_Task.name) and (A_Half_Dep.buffer_orientation = From_Task_To_Object) then return True; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; return False; end Has_Buffer_To_Write; function Get_A_Successor (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Generic_Task_Ptr is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_source.name = My_Task.name) then return Copy (A_Half_Dep.precedence_sink); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; raise Dependency_Not_Found; return null; end Get_A_Successor; function Get_A_Predecessor (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Generic_Task_Ptr is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_sink.name = My_Task.name) then return Copy (A_Half_Dep.precedence_source); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; raise Dependency_Not_Found; return null; end Get_A_Predecessor; function Has_Predecessor (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Boolean is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_sink.name = My_Task.name) then return True; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; return False; end Has_Predecessor; --------------------------------------------------------------- function Has_Predecessor_Asynchronous (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Boolean is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_orientation = From_Object_To_Task) then if (A_Half_Dep.asynchronous_communication_dependent_task.name = My_Task.name) then return True; end if ; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; return False; end Has_Predecessor_Asynchronous; ------------------------------------------------------ function Has_Successor (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Boolean is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_source.name = My_Task.name) then return True; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; return False; end Has_Successor; function Get_Successors_List (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Tasks_Set is Result : Tasks_Set; New_Task : Generic_Task_Ptr; My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_source.name = My_Task.name) then New_Task := Copy (A_Half_Dep.precedence_sink); add (Result, New_Task); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; return Result; end Get_Successors_List; ----------------------------------------------------------------------- function Get_Successors_List_Asynchronous (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Tasks_Set is Result : Tasks_Set; New_Task : Generic_Task_Ptr; My_Iterator1, My_Iterator2 : Tasks_Dependencies_Iterator; A_Half_Dep, A_Half_Dep2 : Dependency_Ptr; A_Message : Generic_Message_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if (A_Half_Dep.asynchronous_communication_dependent_task.name = My_Task.name) then if (A_Half_Dep.asynchronous_communication_orientation = From_Task_To_Object) then A_Message := A_Half_Dep.asynchronous_communication_dependency_object ; reset_iterator (My_Dependencies.Depends, My_Iterator2); loop current_element (My_Dependencies.Depends, A_Half_Dep2, My_Iterator2); if (A_Half_Dep2.asynchronous_communication_dependency_object.name = A_Message.name) then if (A_Half_Dep2.asynchronous_communication_orientation = From_Object_To_Task) then New_Task := Copy (A_Half_Dep2.asynchronous_communication_dependent_task); add (Result, New_Task); end if ; end if ; exit when is_last_element (My_Dependencies.Depends, My_Iterator2); next_element (My_Dependencies.Depends, My_Iterator2); end loop; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; return Result; end Get_Successors_List_Asynchronous; ----------------------------------------------------------------------------- function Get_Predecessors_List (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Tasks_Set is Result : Tasks_Set; New_Task : Generic_Task_Ptr; My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_sink.name = My_Task.name) then New_Task := Copy (A_Half_Dep.precedence_source); add (Result, New_Task); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; return Result; end Get_Predecessors_List; ------------------------------------------------------------------------ function Get_Predecessors_List_Asynchronous (My_Dependencies : in Tasks_Dependencies_Ptr; My_Task : in Generic_Task_Ptr) return Tasks_Set is Result : Tasks_Set; New_Task : Generic_Task_Ptr; My_Iterator1, My_Iterator2 : Tasks_Dependencies_Iterator; A_Half_Dep, A_Half_Dep2 : Dependency_Ptr; A_Message : Generic_Message_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if (A_Half_Dep.asynchronous_communication_dependent_task.name = My_Task.name) then if (A_Half_Dep.asynchronous_communication_orientation = From_Object_To_Task) then A_Message := A_Half_Dep.asynchronous_communication_dependency_object ; reset_iterator (My_Dependencies.Depends, My_Iterator2); loop current_element (My_Dependencies.Depends, A_Half_Dep2, My_Iterator2); if (A_Half_Dep2.asynchronous_communication_dependency_object.name = A_Message.name) then if (A_Half_Dep2.asynchronous_communication_orientation = From_Task_To_Object) then New_Task := Copy (A_Half_Dep2.asynchronous_communication_dependent_task); add (Result, New_Task); end if ; end if ; exit when is_last_element (My_Dependencies.Depends, My_Iterator2); next_element (My_Dependencies.Depends, My_Iterator2); end loop; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; return Result; end Get_Predecessors_List_Asynchronous; ------------------------------------------------------------------------- function Get_A_Root_Task (My_Dependencies : in Tasks_Dependencies_Ptr) return Generic_Task_Ptr is Is_Root : Boolean; My_Iterator2 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; My_Iterator1 : Tasks_Iterator; A_Task : Generic_Task_Ptr; begin if not is_empty (My_Dependencies.Dependent_Tasks) then reset_iterator (My_Dependencies.Dependent_Tasks, My_Iterator1); loop current_element (My_Dependencies.Dependent_Tasks, A_Task, My_Iterator1); reset_iterator (My_Dependencies.Depends, My_Iterator2); Is_Root := True; loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator2); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_orientation = From_Object_To_Task) and (A_Task.name = A_Half_Dep.buffer_dependent_task.name) then Is_Root := False; end if; end if; if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_orientation = From_Object_To_Task) and (A_Task.name = A_Half_Dep.asynchronous_communication_dependent_task.name) then Is_Root := False; end if; end if; if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_sink.name = A_Task.name) then Is_Root := False; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator2); next_element (My_Dependencies.Depends, My_Iterator2); end loop; if Is_Root then return A_Task; end if; exit when is_last_element (My_Dependencies.Dependent_Tasks, My_Iterator1); next_element (My_Dependencies.Dependent_Tasks, My_Iterator1); end loop; end if; raise Dependency_Not_Found; return null; end Get_A_Root_Task; function Get_A_Leaf_Task (My_Dependencies : in Tasks_Dependencies_Ptr) return Generic_Task_Ptr is Is_Leaf : Boolean; My_Iterator2 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; My_Iterator1 : Tasks_Iterator; A_Task : Generic_Task_Ptr; begin if not is_empty (My_Dependencies.Dependent_Tasks) then reset_iterator (My_Dependencies.Dependent_Tasks, My_Iterator1); loop current_element (My_Dependencies.Dependent_Tasks, A_Task, My_Iterator1); reset_iterator (My_Dependencies.Depends, My_Iterator2); Is_Leaf := True; loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator2); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_orientation = From_Task_To_Object) and (A_Task.name = A_Half_Dep.buffer_dependent_task.name) then Is_Leaf := False; end if; end if; if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_orientation = From_Task_To_Object) and (A_Task.name = A_Half_Dep.asynchronous_communication_dependent_task.name) then Is_Leaf := False; end if; end if; if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_source.name = A_Task.name) then Is_Leaf := False; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator2); next_element (My_Dependencies.Depends, My_Iterator2); end loop; if Is_Leaf then return A_Task; end if; exit when is_last_element (My_Dependencies.Dependent_Tasks, My_Iterator1); next_element (My_Dependencies.Dependent_Tasks, My_Iterator1); end loop; end if; raise Dependency_Not_Found; return null; end Get_A_Leaf_Task; function Get_Leaf_Tasks (My_Dependencies : in Tasks_Dependencies_Ptr) return Tasks_Set is Result : Tasks_Set; Is_Leaf : Boolean; New_Task : Generic_Task_Ptr; My_Iterator2 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; My_Iterator1 : Tasks_Iterator; A_Task : Generic_Task_Ptr; begin if not is_empty (My_Dependencies.Dependent_Tasks) then reset_iterator (My_Dependencies.Dependent_Tasks, My_Iterator1); loop current_element (My_Dependencies.Dependent_Tasks, A_Task, My_Iterator1); reset_iterator (My_Dependencies.Depends, My_Iterator2); Is_Leaf := True; loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator2); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_orientation = From_Task_To_Object) and (A_Task.name = A_Half_Dep.buffer_dependent_task.name) then Is_Leaf := False; end if; end if; if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_orientation = From_Task_To_Object) and (A_Task.name = A_Half_Dep.asynchronous_communication_dependent_task.name) then Is_Leaf := False; end if; end if; if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_source.name = A_Task.name) then Is_Leaf := False; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator2); next_element (My_Dependencies.Depends, My_Iterator2); end loop; if Is_Leaf then New_Task := Copy (A_Task); add (Result, New_Task); end if; exit when is_last_element (My_Dependencies.Dependent_Tasks, My_Iterator1); next_element (My_Dependencies.Dependent_Tasks, My_Iterator1); end loop; end if; return Result; end Get_Leaf_Tasks; function Get_Root_Tasks (My_Dependencies : in Tasks_Dependencies_Ptr) return Tasks_Set is Result : Tasks_Set; Is_Root : Boolean; New_Task : Generic_Task_Ptr; My_Iterator2 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; My_Iterator1 : Tasks_Iterator; A_Task : Generic_Task_Ptr; begin if not is_empty (My_Dependencies.Dependent_Tasks) then reset_iterator (My_Dependencies.Dependent_Tasks, My_Iterator1); loop current_element (My_Dependencies.Dependent_Tasks, A_Task, My_Iterator1); reset_iterator (My_Dependencies.Depends, My_Iterator2); Is_Root := True; loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator2); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_orientation = From_Object_To_Task) and (A_Task.name = A_Half_Dep.buffer_dependent_task.name) then Is_Root := False; end if; end if; if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_orientation = From_Object_To_Task) and (A_Task.name = A_Half_Dep.asynchronous_communication_dependent_task.name) then Is_Root := False; end if; end if; if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_sink.name = A_Task.name) then Is_Root := False; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator2); next_element (My_Dependencies.Depends, My_Iterator2); end loop; if Is_Root then New_Task := Copy (A_Task); add (Result, New_Task); end if; exit when is_last_element (My_Dependencies.Dependent_Tasks, My_Iterator1); next_element (My_Dependencies.Dependent_Tasks, My_Iterator1); end loop; end if; return Result; end Get_Root_Tasks; ------------------------------------------------------------------- -- Delete ALL dependencies of an -- address space (parameter "An_Address_Space") -- procedure Delete_Address_Space_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; An_Address_Space : in Unbounded_String) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; To_Be_Deleted : Half_Dep_Set.set; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_source.address_space_name = An_Address_Space) or (A_Half_Dep.precedence_sink.address_space_name = An_Address_Space) then add (To_Be_Deleted, A_Half_Dep); end if; end if; if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_orientation = From_Object_To_Task) and (An_Address_Space = A_Half_Dep.buffer_dependent_task.address_space_name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_orientation = From_Object_To_Task) and (An_Address_Space = A_Half_Dep.asynchronous_communication_dependent_task.address_space_name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; if not is_empty (To_Be_Deleted) then delete (My_Dependencies.Depends, To_Be_Deleted); end if; end Delete_Address_Space_All_Task_Dependencies; -- Delete ALL dependencies of a -- processor (parameter "A_Processor") -- procedure Delete_Processor_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Processor : in Unbounded_String) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; To_Be_Deleted : Half_Dep_Set.set; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_source.cpu_name = A_Processor) or (A_Half_Dep.precedence_sink.cpu_name = A_Processor) then add (To_Be_Deleted, A_Half_Dep); end if; end if; if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_orientation = From_Object_To_Task) and (A_Processor = A_Half_Dep.buffer_dependent_task.cpu_name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_orientation = From_Object_To_Task) and (A_Processor = A_Half_Dep.asynchronous_communication_dependent_task.cpu_name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; if not is_empty (To_Be_Deleted) then delete (My_Dependencies.Depends, To_Be_Deleted); end if; end Delete_Processor_All_Task_Dependencies; -- Delete ALL dependencies : -- 1) of a task (if My_Dep_Name is a Task_ptr) -- 2) of a message (if My_Dep_Name is a Message_ptr) -- 3) of a buffer (if My_Dep_Name is a Buffer_ptr) -- procedure Delete_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Task : in Generic_Task_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; To_Be_Deleted : Half_Dep_Set.set; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_dependent_task.name = A_Task.name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_dependent_task.name = A_Task.name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_source.name = A_Task.name) or (A_Half_Dep.precedence_sink.name = A_Task.name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; if not is_empty (To_Be_Deleted) then delete (My_Dependencies.Depends, To_Be_Deleted); end if; end Delete_All_Task_Dependencies; procedure Delete_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Buffer : in Buffer_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; To_Be_Deleted : Half_Dep_Set.set; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_dependency_object.name = A_Buffer.name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; if not is_empty (To_Be_Deleted) then delete (My_Dependencies.Depends, To_Be_Deleted); end if; end Delete_All_Task_Dependencies; procedure Delete_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Message : in Generic_Message_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; To_Be_Deleted : Half_Dep_Set.set; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_dependency_object.name = A_Message.name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; if not is_empty (To_Be_Deleted) then delete (My_Dependencies.Depends, To_Be_Deleted); end if; end Delete_All_Task_Dependencies; -- Remove ONE precedency between two tasks -- procedure Delete_One_Task_Dependency_precedence (My_Dependencies : in out Tasks_Dependencies_Ptr; Source : in Generic_Task_Ptr; Sink : in Generic_Task_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_source.name = Source.name) and (A_Half_Dep.precedence_sink.name = Sink.name) then delete (My_Dependencies.Depends, A_Half_Dep); Delete_Dependent_Tasks(My_Dependencies, Source); Delete_Dependent_Tasks(My_Dependencies, Sink); return; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; raise Dependency_Not_Found; end Delete_One_Task_Dependency_precedence; -- Remove ONE remote procedure call dependency between two tasks -- procedure Delete_One_Task_Dependency_remote_procedure_call (My_Dependencies : in out Tasks_Dependencies_Ptr; client : in Generic_Task_Ptr; server : in Generic_Task_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = remote_procedure_call_Dependency then if (A_Half_Dep.remote_procedure_call_client.name = client.name) and (A_Half_Dep.remote_procedure_call_server.name = server.name) then delete (My_Dependencies.Depends, A_Half_Dep); Delete_Dependent_Tasks(My_Dependencies, client); Delete_Dependent_Tasks(My_Dependencies, server); return; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; raise Dependency_Not_Found; end Delete_One_Task_Dependency_remote_procedure_call; -- Remove ONE time triggered dependency between two tasks -- procedure Delete_One_Task_Dependency_time_triggered (My_Dependencies : in out Tasks_Dependencies_Ptr; Source : in Generic_Task_Ptr; Sink : in Generic_Task_Ptr; Timing_Type : in Time_Triggered_Communication_Timing_Property_Type) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Time_Triggered_Communication_Dependency then if (A_Half_Dep.time_triggered_communication_source.name = Source.name) and (A_Half_Dep.time_triggered_communication_sink.name = Sink.name) and (A_Half_Dep.time_triggered_timing_property = Timing_Type) then delete (My_Dependencies.Depends, A_Half_Dep); Delete_Dependent_Tasks(My_Dependencies, Source); Delete_Dependent_Tasks(My_Dependencies, Sink); return; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; raise Dependency_Not_Found; end Delete_One_Task_Dependency_time_triggered; procedure Delete_One_Task_Dependency_black_board_buffer (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Task : in Generic_Task_Ptr; A_Dep : in Buffer_Ptr; A_Type : in Orientation_Dependency_Type) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = black_board_Buffer_Dependency then if (A_Half_Dep.buffer_dependent_task.name = A_Task.name) and (A_Half_Dep.buffer_dependency_object.name = A_dep.name) and (A_Half_Dep.buffer_orientation = A_Type) then delete (My_Dependencies.Depends, A_Half_Dep); return; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; raise Dependency_Not_Found; end Delete_One_Task_Dependency_black_board_buffer; -- Remove ONE dependency between a task and -- a buffer -- procedure Delete_One_Task_Dependency_queueing_buffer (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Task : in Generic_Task_Ptr; A_Buffer : in Buffer_Ptr; A_Type : in Orientation_Dependency_Type) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_dependent_task.name = A_Task.name) and (A_Half_Dep.buffer_dependency_object.name = A_Buffer.name) and (A_Half_Dep.buffer_orientation = A_Type) then delete (My_Dependencies.Depends, A_Half_Dep); return; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; raise Dependency_Not_Found; end Delete_One_Task_Dependency_queueing_buffer; -- Remove ONE dependency between a task and -- a message -- procedure Delete_One_Task_Dependency_asynchronous_communication (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Task : in Generic_Task_Ptr; A_Message : in Generic_Message_Ptr; A_Type : in Orientation_Dependency_Type ) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_dependent_task.name = A_Task.name) and (A_Half_Dep.asynchronous_communication_dependency_object.name = A_Message.name) and (A_Half_Dep.asynchronous_communication_orientation = A_Type) then delete (My_Dependencies.Depends, A_Half_Dep); return; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; raise Dependency_Not_Found; end Delete_One_Task_Dependency_asynchronous_communication; procedure Delete_One_Task_Dependency_resource (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Task : in Generic_Task_Ptr; A_Resource : in Generic_Resource_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = resource_Dependency then if (A_Half_Dep.resource_dependency_task.name = A_Task.name) and (A_Half_Dep.resource_dependency_resource.name = A_resource.name) then delete (My_Dependencies.Depends, A_Half_Dep); return; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; raise Dependency_Not_Found; end Delete_One_Task_Dependency_resource; ------------------------------------------------------------------- procedure Update_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Task : in Generic_Task_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); case A_Half_Dep.type_of_dependency is when time_triggered_communication_dependency => if (A_Half_Dep.time_triggered_communication_source.name = A_Task.name) then A_Half_Dep.time_triggered_communication_source := A_Task; end if; if (A_Half_Dep.time_triggered_communication_sink.name = A_Task.name) then A_Half_Dep.time_triggered_communication_sink := A_Task; end if; when Remote_Procedure_Call_Dependency => if (A_Half_Dep.remote_procedure_call_client.name = A_Task.name) then A_Half_Dep.precedence_source := A_Task; end if; if (A_Half_Dep.remote_procedure_call_server.name = A_Task.name) then A_Half_Dep.precedence_sink := A_Task; end if; when Precedence_Dependency => if (A_Half_Dep.precedence_source.name = A_Task.name) then A_Half_Dep.precedence_source := A_Task; end if; if (A_Half_Dep.precedence_sink.name = A_Task.name) then A_Half_Dep.precedence_sink := A_Task; end if; when black_board_Buffer_dependency => if (A_Half_Dep.black_board_dependent_task.name = A_Task.name) then A_Half_Dep.black_board_dependent_task := A_Task; end if; when Queueing_Buffer_Dependency => if (A_Half_Dep.buffer_dependent_task.name = A_Task.name) then A_Half_Dep.buffer_dependent_task := A_Task; end if; when resource_Dependency => if (A_Half_Dep.resource_dependency_task.name = A_Task.name) then A_Half_Dep.resource_dependency_task := A_Task; end if; when asynchronous_Communication_Dependency => if (A_Half_Dep.asynchronous_communication_dependent_task.name = A_Task.name) then A_Half_Dep.asynchronous_communication_dependent_task := A_Task; end if; end case; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; end Update_All_Task_Dependencies; procedure Update_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Buffer : in Buffer_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Queueing_Buffer_Dependency then if (A_Half_Dep.buffer_dependency_object.name = A_Buffer.name) then A_Half_Dep.buffer_dependency_object := A_Buffer; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; end Update_All_Task_Dependencies; procedure Update_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Message : in Generic_Message_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency then if (A_Half_Dep.asynchronous_communication_dependency_object.name = A_Message.name) then A_Half_Dep.asynchronous_communication_dependency_object := A_Message; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; end Update_All_Task_Dependencies; ------------------------------------------------------------------- -- Check is a task dependencies is acyclic or not -- function Is_Cyclic (My_Dependencies : in Tasks_Dependencies_Ptr) return Boolean is begin return not Is_Acyclic (My_Dependencies); end Is_Cyclic; function Is_Acyclic (My_Dependencies : in Tasks_Dependencies_Ptr) return Boolean is type Tasks_Table_Range is new Integer range 0 .. Framework_Config.Max_Tasks_Dependencies; type Tasks_Table is array (Tasks_Table_Range'Range) of Generic_Task_Ptr; My_Iterator1 : Tasks_Iterator; A_Task : Generic_Task_Ptr; -- Stay true until we find a cycle -- Result : Boolean := True; -- Check backward arrows (cycle detection) -- function Has_Backward_Arrow (Current, Next_Of_Current : Generic_Task_Ptr; Number_Of_Arrows : Tasks_Table_Range; From, To : Tasks_Table) return Boolean is begin for K in 0 .. Number_Of_Arrows - 1 loop if (Current.name = From (K).name) and (Next_Of_Current.name = To (K).name) then return True; end if; end loop; return False; end Has_Backward_Arrow; -- Each task of the set has to be inspected -- procedure Scan_A_Task (Current : Generic_Task_Ptr; Number_Of_Arrows : in Tasks_Table_Range; From, To : in Tasks_Table) is Next : Tasks_Set; Ite : Tasks_Iterator; Next_Of_Current : Generic_Task_Ptr; Tmp_To : Tasks_Table := To; Tmp_From : Tasks_Table := From; Tmp_Number : constant Tasks_Table_Range := Number_Of_Arrows + 1; begin if Has_Successor (My_Dependencies, Current) then reset (Next, False); Next := Get_Successors_List (My_Dependencies, Current); -- Run for each task a cyclicity test -- reset_iterator (Next, Ite); for J in 0 .. get_number_of_elements (Next) - 1 loop current_element (Next, Next_Of_Current, Ite); -- Memorize that we had check this arrow -- if Has_Backward_Arrow (Current, Next_Of_Current, Number_Of_Arrows, From, To) then Result := False; else Tmp_From (Tmp_Number - 1) := Current; Tmp_To (Tmp_Number - 1) := Next_Of_Current; Scan_A_Task (Next_Of_Current, Tmp_Number, Tmp_From, Tmp_To); end if; next_element (Next, Ite); end loop; end if; end Scan_A_Task; -- Used to store backward arrows -- From, To : Tasks_Table; M : Tasks_Table_Range := 0; begin -- Run for Each task A Cyclicity Test -- if not is_empty (My_Dependencies.Dependent_Tasks) then reset_iterator (My_Dependencies.Dependent_Tasks, My_Iterator1); loop current_element (My_Dependencies.Dependent_Tasks, A_Task, My_Iterator1); if Result then M := 0; Scan_A_Task (A_Task, M, From, To); end if; exit when is_last_element (My_Dependencies.Dependent_Tasks, My_Iterator1); next_element (My_Dependencies.Dependent_Tasks, My_Iterator1); end loop; end if; return Result; end Is_Acyclic; function Is_Unique_Precedence_Dependency (My_Dependencies : in Tasks_Dependencies_Ptr; Source_Task : Generic_Task_Ptr; Sink_Task : in Generic_Task_Ptr) return Boolean is My_Iterator : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if (A_Half_Dep.precedence_sink.name = Sink_Task.name and A_Half_Dep.precedence_source.name = Source_Task.name) then return False; end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator); next_element (My_Dependencies.Depends, My_Iterator); end loop; end if; return True; end Is_Unique_Precedence_Dependency; -- Checks if creating a precedence dependency will result in a cycle -- TODO: Merge with (a)cyclic check function No_Precedence_Dependency_Deadlock (My_Dependencies : in Tasks_Dependencies_Ptr; Source_Task : Generic_Task_Ptr; Sink_Task : in Generic_Task_Ptr) return Boolean is My_Iterator : Tasks_Iterator; Source_Predecessors : Tasks_Set; A_Task : Generic_Task_Ptr; Result : Boolean; begin -- Stop condition if (Source_Task.name = Sink_Task.name) then return False; end if; Result := True; Source_Predecessors := Get_Predecessors_List (My_Dependencies, Source_Task); if (not is_empty (Source_Predecessors)) then reset_iterator (Source_Predecessors, My_Iterator); loop current_element (Source_Predecessors, A_Task, My_Iterator); Result := No_Precedence_Dependency_Deadlock (My_Dependencies, A_Task, Sink_Task); exit when is_last_element (Source_Predecessors, My_Iterator) or Result = False; next_element (Source_Predecessors, My_Iterator); end loop; end if; return Result; end No_Precedence_Dependency_Deadlock; -- Add a Time_Triggered_Communication constraint between two tasks -- (a dependency with a Time_Triggered_Communication_Timing_Property_Type) -- procedure Add_One_Task_Dependency_time_triggered (My_Dependencies : in out Tasks_Dependencies_Ptr; From_Task : in Generic_Task_Ptr; To_Task : in Generic_Task_Ptr; Timing_Type : in Time_Triggered_Communication_Timing_Property_Type) is A_Dep_Ptr : Dependency_Ptr; begin A_Dep_Ptr := new Dependency (Time_Triggered_Communication_Dependency); A_Dep_Ptr.time_triggered_communication_source := From_Task; A_Dep_Ptr.time_triggered_communication_sink := To_Task; A_Dep_Ptr.time_triggered_timing_property := Timing_Type; add (My_Dependencies.Depends, A_Dep_Ptr); Add_Dependent_Tasks (My_Dependencies, To_Task); end Add_One_Task_Dependency_time_triggered; -- Add a Resource constraint between a task and a resource -- procedure Add_One_Task_Dependency_resource (My_Dependencies : in out Tasks_Dependencies_Ptr; Dependent_Task : in Generic_Task_Ptr; a_Resource : in Generic_Resource_Ptr) is A_Dep_Ptr : Dependency_Ptr; begin A_Dep_Ptr := new Dependency (Resource_Dependency); A_Dep_Ptr.resource_dependency_resource := a_Resource; A_Dep_Ptr.resource_dependency_task := Dependent_Task; add (My_Dependencies.Depends, A_Dep_Ptr); Add_Dependent_Tasks (My_Dependencies, Dependent_Task); end Add_One_Task_Dependency_resource; procedure Delete_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Resource : in Generic_Resource_Ptr) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; To_Be_Deleted : Half_Dep_Set.set; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if A_Half_Dep.type_of_dependency = Resource_Dependency then if (A_Half_Dep.resource_dependency_resource.name = A_Resource.name) then add (To_Be_Deleted, A_Half_Dep); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; if not is_empty (To_Be_Deleted) then delete (My_Dependencies.Depends, To_Be_Deleted); end if; end Delete_All_Task_Dependencies; procedure Update_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; A_Resource : in Generic_Resource_Ptr) is begin raise Constraint_Error; end Update_All_Task_Dependencies; procedure Add_All_Task_Dependencies (My_Dependencies : in out Tasks_Dependencies_Ptr; My_Tasks : in Tasks_Set; A_Resource : in Generic_Resource_Ptr) is Task1 : Generic_Task_Ptr; begin Delete_All_Task_Dependencies (My_Dependencies, A_Resource); for I in 0 .. A_Resource.critical_sections.nb_entries - 1 loop Task1 := Search_Task (My_Tasks, A_Resource.critical_sections.entries (I).item); Add_One_Task_Dependency_resource(My_Dependencies, Task1, A_Resource); end loop; end Add_All_Task_Dependencies; -- Search ALL dependencies related to the -- processor "A_Processor" -- procedure Check_entity_referencing_Processor (My_Dependencies : in Tasks_Dependencies_Ptr; A_Processor : in Unbounded_String) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); case A_Half_Dep.type_of_dependency is when time_triggered_communication_dependency => if (A_Half_Dep.time_triggered_communication_sink.cpu_name = A_Processor) or (A_Half_Dep.time_triggered_communication_source.cpu_name = A_Processor) then Raise_Exception (processor_set.Invalid_Parameter'Identity, To_String ( lb_processor (Current_Language) & " " & a_processor & " : time triggered dependencies " & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when Precedence_Dependency => if (A_Half_Dep.precedence_source.cpu_name = A_Processor) or (A_Half_Dep.precedence_sink.cpu_name = A_Processor) then Raise_Exception (processor_set.Invalid_Parameter'Identity, To_String ( lb_processor (Current_Language) & " " & a_processor & " : " & lb_precedencies (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when remote_procedure_call_Dependency => if (A_Half_Dep.remote_procedure_call_client.cpu_name = A_Processor) or (A_Half_Dep.remote_procedure_call_server.cpu_name = A_Processor) then Raise_Exception (processor_set.Invalid_Parameter'Identity, To_String ( lb_processor (Current_Language) & " " & a_processor & " : remote procedure call : " & lb_entity_referenced_elsewhere(current_language) )); end if; when black_board_Buffer_dependency => if (A_Processor = A_Half_Dep.black_board_dependent_task.cpu_name) or (A_Processor = A_Half_Dep.black_board_dependency_object.cpu_name) then Raise_Exception (processor_set.Invalid_Parameter'Identity, To_String ( lb_processor (Current_Language) & " " & a_processor & " : " & lb_buffer (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when Queueing_Buffer_Dependency => if (A_Processor = A_Half_Dep.buffer_dependent_task.cpu_name) or (A_Processor = A_Half_Dep.buffer_dependency_object.cpu_name) then Raise_Exception (processor_set.Invalid_Parameter'Identity, To_String ( lb_processor (Current_Language) & " " & a_processor & " : " & lb_buffer (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when resource_Dependency => if (A_Processor = A_Half_Dep.resource_dependency_task.cpu_name) or (A_Processor = A_Half_Dep.resource_dependency_resource.cpu_name) then Raise_Exception (processor_set.Invalid_Parameter'Identity, To_String ( lb_processor (Current_Language) & " " & a_processor & " : " & lb_resource (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when asynchronous_Communication_Dependency => if (A_Processor = A_Half_Dep.asynchronous_communication_dependent_task.cpu_name) then Raise_Exception (processor_set.Invalid_Parameter'Identity, To_String ( lb_processor (Current_Language) & " " & a_processor & " : " & lb_message (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; end case; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; end Check_entity_referencing_Processor; -- Search ALL dependencies related to the -- resource "A_buffer" -- procedure Check_entity_referencing_buffer (My_Dependencies : in Tasks_Dependencies_Ptr; A_buffer : in Unbounded_String) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if (A_Half_Dep.type_of_dependency = queueing_buffer_Dependency) then if (A_buffer = A_Half_Dep.buffer_dependency_object.name) then Raise_Exception (buffer_set.Invalid_Parameter'Identity, To_String ( lb_buffer (Current_Language) & " " & a_buffer & " : " & lb_dependencies (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; end Check_entity_referencing_buffer; -- Search ALL dependencies related to the -- resource "A_resource" -- procedure Check_entity_referencing_resource (My_Dependencies : in Tasks_Dependencies_Ptr; A_resource : in Unbounded_String) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if (A_Half_Dep.type_of_dependency = resource_Dependency) then if (A_resource = A_Half_Dep.resource_dependency_resource.name) then Raise_Exception (resource_set.Invalid_Parameter'Identity, To_String ( lb_resource (Current_Language) & " " & a_resource & " : " & lb_dependencies (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; end Check_entity_referencing_resource; -- Search ALL dependencies related to the -- message 'a_message' -- procedure Check_entity_referencing_message (My_Dependencies : in Tasks_Dependencies_Ptr; A_message : in Unbounded_String) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); if (A_Half_Dep.type_of_dependency = asynchronous_Communication_Dependency) then if (A_message = A_Half_Dep.asynchronous_communication_dependent_task.name) then Raise_Exception (resource_set.Invalid_Parameter'Identity, To_String ( lb_message (Current_Language) & " " & a_message & " : " & lb_dependencies (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; end if; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; end Check_entity_referencing_message; -- Search ALL dependencies related to the -- task "A_task" -- procedure Check_entity_referencing_task (My_Dependencies : in Tasks_Dependencies_Ptr; A_task : in Unbounded_String) is My_Iterator1 : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty (My_Dependencies.Depends) then reset_iterator (My_Dependencies.Depends, My_Iterator1); loop current_element (My_Dependencies.Depends, A_Half_Dep, My_Iterator1); case A_Half_Dep.type_of_dependency is when time_triggered_communication_dependency => if (A_Half_Dep.time_triggered_communication_sink.name = A_task) or (A_Half_Dep.time_triggered_communication_source.name = A_task) then Raise_Exception (task_set.Invalid_Parameter'Identity, To_String ( lb_task (Current_Language) & " " & a_task & " : time triggered dependencies " & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when remote_procedure_call_dependency => if (A_Half_Dep.remote_procedure_call_client.name = A_task) or (A_Half_Dep.remote_procedure_call_server.name = A_task) then Raise_Exception (task_set.Invalid_Parameter'Identity, To_String ( lb_task (Current_Language) & " " & a_task & " : time triggered dependencies " & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when Precedence_Dependency => if (A_Half_Dep.precedence_source.name = A_task) or (A_Half_Dep.precedence_sink.name = A_task) then Raise_Exception (task_set.Invalid_Parameter'Identity, To_String ( lb_task (Current_Language) & " " & a_task & " : " & lb_precedencies (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when black_board_Buffer_dependency => if (A_task = A_Half_Dep.black_board_dependent_task.name) then Raise_Exception (task_set.Invalid_Parameter'Identity, To_String ( lb_task (Current_Language) & " " & a_task & " : " & lb_buffer (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when Queueing_Buffer_Dependency => if (A_task = A_Half_Dep.buffer_dependent_task.name) then Raise_Exception (task_set.Invalid_Parameter'Identity, To_String ( lb_task(Current_Language) & " " & a_task& " : " & lb_buffer (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when resource_Dependency => if (A_task = A_Half_Dep.resource_dependency_task.name) then Raise_Exception (task_set.Invalid_Parameter'Identity, To_String ( lb_task (Current_Language) & " " & a_task & " : " & lb_resource (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; when asynchronous_Communication_Dependency => if (A_task = A_Half_Dep.asynchronous_communication_dependent_task.cpu_name) then Raise_Exception (task_set.Invalid_Parameter'Identity, To_String ( lb_task (Current_Language) & " " & a_task & " : " & lb_message (Current_Language) & " : " & lb_entity_referenced_elsewhere(current_language) )); end if; end case; exit when is_last_element (My_Dependencies.Depends, My_Iterator1); next_element (My_Dependencies.Depends, My_Iterator1); end loop; end if; end Check_entity_referencing_task; end Task_Dependencies;