------------------------------------------------------------ -------------------- ------------------------------------------------------------------------------ -- Cheddar is a GNU GPL real time scheduling analysis tool. -- This program provides services to automatically check performances -- of real time architectures. -- -- Copyright (C) 2002-2010, by Frank Singhoff, Alain Plantec, Jerome Legrand -- -- The Cheddar project was started in 2002 by -- the LISyC Team, University of Western Britanny. -- -- Since 2008, Ellidiss technologies also contributes to the development of -- Cheddar and provides industrial support. -- -- 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: 97 $ -- $Date: 2007-07-20 15:17:15 +0200 (Fri, 20 Jul 2007) $ -- $Author: singhoff $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with Translate; use Translate; with Parameters; use Parameters; use Parameters.User_Defined_Parameters_Table_Package; with Ada.Exceptions; use Ada.Exceptions; with Debug; use Debug; with section_Set; use section_Set; use section_Set.package_Generic_section_Set; with Simulations; use Simulations; with Simulations.extended; use Simulations.extended; with Interpreter.extended; use Interpreter.extended; package body Scheduler.user_defined.interpreted is procedure Load_Read_Write_Interpreter_Variables (My_Scheduler : in out interpreted_user_defined_Scheduler; Si : in Scheduling_Information; Processor_Name : in Unbounded_String) is Var : Variables_Range; Var_Task_Name : Variables_Range; begin Var_Task_Name := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.name")); for J in 0 .. Si.Number_Of_Tasks - 1 loop if Processor_Name = Si.Tcbs (J).Tsk.cpu_name then for Z in 0 .. Si.Number_Of_Tasks - 1 loop if My_Scheduler.Variables_Table.entries (Var_Task_Name). Simulation.String_Table_Value (Simulations_Range (Z)) = Si.Tcbs (J).Tsk.name then -- "tasks.priority" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.priority")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Si.Tcbs (J).Tsk.priority); -- "tasks.deadline" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.deadline")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Si.Tcbs (J).Tsk.deadline); -- "tasks.start_time" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.start_time")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Si.Tcbs (J).Tsk.start_time); -- "tasks.processor_name" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.processor_name")); My_Scheduler.Variables_Table.entries (Var).Simulation. String_Table_Value (Simulations_Range (Z)) := Si.Tcbs (J).Tsk.cpu_name; -- "tasks.name" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.name")); My_Scheduler.Variables_Table.entries (Var).Simulation. String_Table_Value (Simulations_Range (Z)) := Si.Tcbs (J).Tsk.name; -- "tasks.capacity" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.capacity")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Si.Tcbs (J).Tsk.capacity); -- "tasks.suspended" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.suspended")); My_Scheduler.Variables_Table.entries (Var).Simulation. Boolean_Table_Value (Simulations_Range (Z)) := Si.Tcbs (J).Suspended; -- "tasks.used_capacity" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.used_capacity")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Si.Tcbs (J).Used_Capacity); -- "tasks.wakeup_time" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.wakeup_time")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Si.Tcbs (J).Wake_Up_Time); -- "tasks.rest_of_capacity" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.rest_of_capacity")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Si.Tcbs (J).Rest_Of_Capacity); -- "tasks.blocking_time" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.blocking_time")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Si.Tcbs (J).Tsk.blocking_time); -- "tasks.period" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.period")); case Si.Tcbs (J).Tsk.task_type is when Aperiodic_Type => My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := 0; when others => My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Periodic_Task_Ptr (Si.Tcbs (J).Tsk).period); end case; -- "tasks.jitter" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.jitter")); case Si.Tcbs (J).Tsk.task_type is when Aperiodic_Type => My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := 0; when others => My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)) := Integer (Periodic_Task_Ptr (Si.Tcbs (J).Tsk).jitter); end case; -- user defined task's parameter : -- for I in 0 .. Si.Tcbs (J).Tsk.parameters.nb_entries - 1 loop -- Find the user defined variable -- and set its value -- for K in 0 .. My_Scheduler.Variables_Table.nb_entries - 1 loop if My_Scheduler.Variables_Table.entries (K).Variable. Name = To_Unbounded_String ("tasks.") & Si.Tcbs (J).Tsk.parameters.entries (I).name then -- Now, set the value -- if Si.Tcbs (J).Tsk.parameters.entries (I).discriminant = Boolean_Parameter then My_Scheduler.Variables_Table.entries (K). Simulation.Boolean_Table_Value ( Simulations_Range (Z)) := Boolean ( Si.Tcbs (J).Tsk.parameters.entries (I). boolean_value); end if; if Si.Tcbs (J).Tsk.parameters.entries (I).discriminant = Integer_Parameter then My_Scheduler.Variables_Table.entries (K). Simulation.Integer_Table_Value ( Simulations_Range (Z)) := Integer ( Si.Tcbs (J).Tsk.parameters.entries (I). integer_value); end if; if Si.Tcbs (J).Tsk.parameters.entries (I).discriminant = Double_Parameter then My_Scheduler.Variables_Table.entries (K). Simulation.Double_Table_Value ( Simulations_Range (Z)) := Double ( Si.Tcbs (J).Tsk.parameters.entries (I).double_value) ; end if; if Si.Tcbs (J).Tsk.parameters.entries (I).discriminant = String_Parameter then My_Scheduler.Variables_Table.entries (K). Simulation.String_Table_Value ( Simulations_Range (Z)) := Si.Tcbs (J).Tsk.parameters.entries (I).string_value; end if; end if; end loop; end loop; end if; end loop; end if; end loop; end Load_Read_Write_Interpreter_Variables; procedure Save_Read_Write_Interpreter_Variables (My_Scheduler : in interpreted_user_defined_Scheduler; Si : in out Scheduling_Information; Processor_Name : in Unbounded_String) is Var : Variables_Range; Var_Task_Name : Variables_Range; begin Var_Task_Name := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.name")); for J in 0 .. Si.Number_Of_Tasks - 1 loop if Processor_Name = Si.Tcbs (J).Tsk.cpu_name then for Z in 0 .. Si.Number_Of_Tasks - 1 loop if My_Scheduler.Variables_Table.entries (Var_Task_Name). Simulation.String_Table_Value (Simulations_Range (Z)) = Si.Tcbs (J).Tsk.name then -- "tasks.priority" -- begin Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.priority")); Si.Tcbs (J).Tsk.priority := Priority_Range ( My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z))); exception when Constraint_Error => Raise_Exception (Type_Error'Identity, "Task priority range check error " & To_String (Parametric_Task_Ptr (Si.Tcbs (J).Tsk).name) & " " & Integer'Image ( My_Scheduler.Variables_Table.entries (Var). Simulation.Integer_Table_Value (Simulations_Range (Z) ))); end; -- "tasks.deadline" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.deadline")); Si.Tcbs (J).Tsk.deadline := My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)); -- "tasks.suspended" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.suspended")); Si.Tcbs (J).Suspended := My_Scheduler.Variables_Table.entries (Var).Simulation. Boolean_Table_Value (Simulations_Range (Z)); -- "tasks.start_time" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.start_time")); Si.Tcbs (J).Tsk.start_time := My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)); -- "tasks.capacity" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.capacity")); Si.Tcbs (J).Tsk.capacity := My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)); -- "tasks.wakeup_time" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.wakeup_time")); Si.Tcbs (J).Wake_Up_Time := My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)); -- "tasks.used_capacity" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.used_capacity")); Si.Tcbs (J).Used_Capacity := My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)); -- "tasks.rest_of_capacity" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.rest_of_capacity")); Si.Tcbs (J).Rest_Of_Capacity := My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)); -- "tasks.blocking_time" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.blocking_time")); Si.Tcbs (J).Tsk.blocking_time := My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (Z)); -- "tasks.period" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.period")); case Si.Tcbs (J).Tsk.task_type is when Aperiodic_Type => null; when others => Periodic_Task_Ptr (Si.Tcbs (J).Tsk).period := My_Scheduler.Variables_Table.entries (Var). Simulation.Integer_Table_Value (Simulations_Range (Z) ); end case; -- "tasks.jitter" -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.jitter")); case Si.Tcbs (J).Tsk.task_type is when Aperiodic_Type => null; when others => Periodic_Task_Ptr (Si.Tcbs (J).Tsk).jitter := My_Scheduler.Variables_Table.entries (Var). Simulation.Integer_Table_Value (Simulations_Range (Z) ); end case; -- user defined task's parameter : -- for I in 0 .. Si.Tcbs (J).Tsk.parameters.nb_entries - 1 loop -- Find the user defined variable -- and set its value -- for K in 0 .. My_Scheduler.Variables_Table.nb_entries - 1 loop if My_Scheduler.Variables_Table.entries (K).Variable. Name = To_Unbounded_String ("tasks.") & Si.Tcbs (J).Tsk.parameters.entries (I).name then -- Now, set the value -- if Si.Tcbs (J).Tsk.parameters.entries (I).discriminant = Boolean_Parameter then Si.Tcbs (J).Tsk.parameters.entries (I).boolean_value := My_Scheduler.Variables_Table.entries (K). Simulation.Boolean_Table_Value ( Simulations_Range (Z)); end if; if Si.Tcbs (J).Tsk.parameters.entries (I).discriminant = Integer_Parameter then Si.Tcbs (J).Tsk.parameters.entries (I).integer_value := My_Scheduler.Variables_Table.entries (K). Simulation.Integer_Table_Value ( Simulations_Range (Z)); end if; if Si.Tcbs (J).Tsk.parameters.entries (I).discriminant = Double_Parameter then Si.Tcbs (J).Tsk.parameters.entries (I).double_value := My_Scheduler.Variables_Table.entries (K). Simulation.Double_Table_Value ( Simulations_Range (Z)); end if; if Si.Tcbs (J).Tsk.parameters.entries (I).discriminant = String_Parameter then Si.Tcbs (J).Tsk.parameters.entries (I).string_value := My_Scheduler.Variables_Table.entries (K). Simulation.String_Table_Value ( Simulations_Range (Z)); end if; end if; end loop; end loop; end if; end loop; end if; end loop; end Save_Read_Write_Interpreter_Variables; procedure Compute_Activation_Time (My_Scheduler : in interpreted_user_defined_Scheduler; Si : in out Scheduling_Information; Elected : in Tasks_Range; Value : in out Natural) is Set_Id : Sets_Range; User_Defined_Delay : Simulation_Value_Ptr; begin Set_Id := Find_Set (My_Scheduler.Sets_Table, Parametric_Task_Ptr (Si.Tcbs (Elected).Tsk).activation_rule); User_Defined_Delay := Value_Of (My_Scheduler.Sets_Table.entries (Set_Id).set_value.all, My_Scheduler.Variables_Table); if (User_Defined_Delay.Ptype /= Simulation_Integer) and (User_Defined_Delay.Ptype /= Simulation_Array_Integer) then Raise_Exception (Type_Error'Identity, "Task activation rule, activation rule " & To_String (Parametric_Task_Ptr (Si.Tcbs (Elected).Tsk).activation_rule) & To_String (Lb_Comma & Lb_Uncompatible_Type_Error (Current_Language))); end if; -- If it's a vector, return the corresponding index -- else, just return the computed integer -- if User_Defined_Delay.Ptype = Simulation_Integer then Value := User_Defined_Delay.Integer_Value; else Value := User_Defined_Delay.Integer_Table_Value (Simulations_Range (Elected)) ; end if; Put_Debug ("Compute activation time for task " & To_String (Si.Tcbs (Elected).Tsk.name) & " : value is " & Natural'Image (Value)); end Compute_Activation_Time; -- A election is done in 3 steps : -- 1) we check and retrieve return information -- 2) tasks queues should be updated -- 3) we find the running task -- procedure dispatch_return_statement (My_Scheduler : in out interpreted_user_defined_Scheduler; Current : in Generic_Statement_Ptr; Si : in out Scheduling_Information; Current_Time : in Natural; Processor_Name : in Unbounded_String; address_space_Name : in Unbounded_String; My_Dependencies : in Tasks_Dependencies_Ptr; With_Offsets : in Boolean; With_Precedencies : in Boolean; With_Resources : in Boolean; Elected : in out Tasks_Range; No_Task : in out Boolean) is Return_Val : Generic_Expression_Ptr; Election_Value : Simulation_Value_Ptr; Current_Selected_Value : Simulation_Value_Ptr; I : Tasks_Range := 0; Var : Variables_Range; Var_Task_Name : Variables_Range; begin -- We should have, at least a election_section ! -- if Current = null then Raise_Exception (Statement_Error'Identity, "An election section is mandatory"); end if; -- Only one type of statement is allowed on "election" section : -- a return statement -- if Current.all not in Return_Statement'Class then Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", return statement expected"); end if; -- Look for the variable which stores task names -- Var_Task_Name := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.name")); -- Do return statement -- -- The return statement should be : -- 1) either a min/max_to_index expression composed of -- a array variable only. Boolean/double/string array variable --are forbidden -- 2) or an integer constant -- 3) or an integer variable -- -- Others expression must raise an error -- Return_Val := Return_Statement_Ptr (Current).return_value; ------------------------------------------------------------ -- 2) and 3) the return statement is a constant or a variable ------------------------------------------------------------ if (Return_Val.Expression_Type = Variable_Type) or (Return_Val.Expression_Type = Constant_Type) then if (Return_Val.Expression_Type = Constant_Type) then Put_Debug ("Do a constant election at time " & Current_Time'Img & " ; processor/addr space " & Processor_Name & "/" & address_space_Name); if Constant_Expression_Ptr (Return_Val).Value.Ptype /= Simulation_Integer then Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", invalid constant expression type referenced in a return statement"); end if; if (Constant_Expression_Ptr (Return_Val).Value.Integer_Value < Integer (Tasks_Range'First)) or (Constant_Expression_Ptr (Return_Val).Value.Integer_Value > Integer (Tasks_Range'Last)) then Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", invalid range constant type referenced in a return statement"); end if; I := Tasks_Range ( Constant_Expression_Ptr (Return_Val).Value.Integer_Value); end if; if (Return_Val.Expression_Type = Variable_Type) then Put_Debug ("Do a variable election at time " & Current_Time'Img & " ; processor/addr space " & Processor_Name & "/" & address_space_Name); Var := Find_Variable (My_Scheduler.Variables_Table, Variable_Expression_Ptr (Return_Val).Name); if My_Scheduler.Variables_Table.entries (Var).Simulation.Ptype /= Simulation_Integer then Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", invalid variable expression type referenced in a return statement"); end if; if (My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Value < Integer (Simulations_Range'First)) or (My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Value > Integer (Tasks_Range'Last)) then Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", invalid range variable type referenced in a return statement"); end if; I := Tasks_Range ( My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Value); end if; -- Convert user_defined variable index towards tcb index -- for J in 0 .. Si.Number_Of_Tasks - 1 loop if My_Scheduler.Variables_Table.entries (Var_Task_Name). Simulation.String_Table_Value (Simulations_Range (I)) = Si.Tcbs (J).Tsk.name then -- Check that the task is ready ... and elect it ! -- if ((Si.Tcbs (J).Tsk.cpu_name = Processor_Name) or (Si.Tcbs (J).Tsk.address_space_name = address_space_Name)) then if (Si.Tcbs (J).Wake_Up_Time <= Current_Time) then if (Si.Tcbs (J).Suspended = False) then if (Si.Tcbs (J).Rest_Of_Capacity /= 0) then if (With_Offsets = False) or Check_Offset (Si.Tcbs (J), Current_Time) then if (With_Precedencies = False) or Check_Precedencies (Si, My_Dependencies, Current_Time, Si.Tcbs (J)) then Elected := J; No_Task := False; end if; end if; end if; end if; end if; end if; end if; end loop; return; end if; ------------------------------------------------------------------------- --------- -- 1) the case when the return statement is a max/min_to_index expression ------------------------------------------------------------------------- --------- if (Return_Val.Expression_Type = Unary_Type) then if (Unary_Expression_Ptr (Return_Val).Ope = Min_To_Index_Type) or (Unary_Expression_Ptr (Return_Val).Ope = Max_To_Index_Type) then Put_Debug ("Do a min/max_to_index election at time " & Current_Time'Img & " ; processor/addr space " & Processor_Name & "/" & address_space_Name); ------------------------------------------------------------------- --------------------- -- Some checks on the type of the variable on which we will run --the min/max statement ------------------------------------------------------------------- --------------------- if (Unary_Expression_Ptr (Return_Val).Ope = Min_To_Index_Type) then if (Unary_Expression_Ptr (Return_Val).Value.Expression_Type /= Array_Variable_Type) then Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", invalid min_to_index expression in return statement"); end if; if (Array_Variable_Expression_Ptr ( Unary_Expression_Ptr (Return_Val).Value).Variable_Type /= Simulation_Array_Integer) and (Array_Variable_Expression_Ptr ( Unary_Expression_Ptr (Return_Val).Value).Variable_Type /= Simulation_Array_Double) then Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", min_to_index expression in return statement should be an integer array variable" ); end if; end if; if (Unary_Expression_Ptr (Return_Val).Ope = Max_To_Index_Type) then if (Unary_Expression_Ptr (Return_Val).Value.Expression_Type /= Array_Variable_Type) then Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", invalid max_to_index expression in return statement"); end if; if (Array_Variable_Expression_Ptr ( Unary_Expression_Ptr (Return_Val).Value).Variable_Type /= Simulation_Array_Integer) then Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", max_to_index expression in return statement should be an integer array variable" ); end if; end if; --------------------------------------------------------- -- The type of the expression is ok, run the return now --------------------------------------------------------- Election_Value := Value_Of (Array_Variable_Expression ( Unary_Expression_Ptr (Return_Val).Value.all), My_Scheduler.Variables_Table, Current.line_number, Current.file_name); if (Election_Value.Ptype = Simulation_Array_Double) then Current_Selected_Value := new Simulation_Value (Simulation_Double); if Unary_Expression_Ptr (Return_Val).Ope = Min_To_Index_Type then Current_Selected_Value.Double_Value := Double'Last; else Current_Selected_Value.Double_Value := Double'First; end if; else Current_Selected_Value := new Simulation_Value (Simulation_Integer); if Unary_Expression_Ptr (Return_Val).Ope = Min_To_Index_Type then Current_Selected_Value.Integer_Value := Integer'Last; else Current_Selected_Value.Integer_Value := Integer'First; end if; end if; -- Now, loop on the array variable to find the appropriate task to --be -- elected -- I := 0; loop if ((Si.Tcbs (I).Tsk.cpu_name = Processor_Name) or (Si.Tcbs (I).Tsk.address_space_name = address_space_Name)) then if (Si.Tcbs (I).Suspended = False) then if (Si.Tcbs (I).Wake_Up_Time <= Current_Time) and (Si.Tcbs (I).Rest_Of_Capacity /= 0) then if (With_Offsets = False) or Check_Offset (Si.Tcbs (I), Current_Time) then if (With_Precedencies = False) or Check_Precedencies (Si, My_Dependencies, Current_Time, Si.Tcbs (I)) then -- Integer case -- if (Election_Value.Ptype = Simulation_Array_Integer) then -- Min_To_Index case -- if (Unary_Expression_Ptr (Return_Val).Ope = Min_To_Index_Type) and (Election_Value.Integer_Table_Value ( Simulations_Range (I)) < Current_Selected_Value.Integer_Value) then Elected := I; Current_Selected_Value.Integer_Value := Election_Value.Integer_Table_Value ( Simulations_Range (I)); end if; -- Max_To_Index case -- if (Unary_Expression_Ptr (Return_Val).Ope = Max_To_Index_Type) and (Election_Value.Integer_Table_Value ( Simulations_Range (I)) > Current_Selected_Value.Integer_Value) then Elected := I; Current_Selected_Value.Integer_Value := Election_Value.Integer_Table_Value ( Simulations_Range (I)); end if; -- Double case -- else -- Min_To_Index case -- if (Unary_Expression_Ptr (Return_Val).Ope = Min_To_Index_Type) and (Election_Value.Double_Table_Value ( Simulations_Range (I)) < Current_Selected_Value.Double_Value) then Elected := I; Current_Selected_Value.Double_Value := Election_Value.Double_Table_Value ( Simulations_Range (I)); end if; -- Max_To_Index case -- if (Unary_Expression_Ptr (Return_Val).Ope = Max_To_Index_Type) and (Election_Value.Double_Table_Value ( Simulations_Range (I)) > Current_Selected_Value.Double_Value) then Elected := I; Current_Selected_Value.Double_Value := Election_Value.Double_Table_Value ( Simulations_Range (I)); end if; end if; end if; end if; end if; end if; end if; I := I + 1; exit when Si.Tcbs (I) = null; end loop; if (Election_Value.Ptype = Simulation_Array_Integer) then if ((Unary_Expression_Ptr (Return_Val).Ope = Min_To_Index_Type) and (Current_Selected_Value.Integer_Value /= Integer'Last)) or ((Unary_Expression_Ptr (Return_Val).Ope = Max_To_Index_Type) and (Current_Selected_Value.Integer_Value /= Integer'First)) then No_Task := False; end if; else if ((Unary_Expression_Ptr (Return_Val).Ope = Min_To_Index_Type) and (Current_Selected_Value.Double_Value /= Double'Last)) or ((Unary_Expression_Ptr (Return_Val).Ope = Max_To_Index_Type) and (Current_Selected_Value.Double_Value /= Double'First)) then No_Task := False; end if; end if; Free (Election_Value); return; end if; end if; ------------------------------------------------------------ -- Others expression in a return statement is a mistake ------------------------------------------------------------ Raise_Exception (Statement_Error'Identity, "Election section, line " & Current.line_number'Img & ", file " & To_String (Current.file_name) & ", invalid expression referenced in a return statement"); end dispatch_return_statement; procedure update_interpreter_variables_after_task_execution (My_Scheduler : in out interpreted_user_defined_Scheduler; Si : in out Scheduling_Information; Current_Time : in Natural; Processor_Name : in Unbounded_String; address_space_Name : in Unbounded_String; My_Dependencies : in Tasks_Dependencies_Ptr; With_Offsets : in Boolean; With_Precedencies : in Boolean; With_Resources : in Boolean) is Var : Variables_Range; Var_Task_Name : Variables_Range; begin -- Look for the variable which stores task names -- Var_Task_Name := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.name")); -- We set the variables changed by the simulation each unit of time -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.activation_number")); for I in 0 .. Si.Number_Of_Tasks - 1 loop if Processor_Name = Si.Tcbs (I).Tsk.cpu_name then for J in 0 .. Si.Number_Of_Tasks - 1 loop if My_Scheduler.Variables_Table.entries (Var_Task_Name). Simulation.String_Table_Value (Simulations_Range (J)) = Si.Tcbs (I).Tsk.name then My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (J)) := Integer (Si.Tcbs (I).Activation); end if; end loop; end if; end loop; for I in 0 .. Si.Number_Of_Tasks - 1 loop if My_Scheduler.Variables_Table.entries (Var_Task_Name).Simulation. String_Table_Value (Simulations_Range (I)) = Si.Tcbs (My_Scheduler.Previously_Elected).Tsk.name then Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.used_capacity")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (I)) := Integer (Si.Tcbs (My_Scheduler.Previously_Elected).Used_Capacity) ; Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.rest_of_capacity")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (I)) := Integer ( Si.Tcbs (My_Scheduler.Previously_Elected).Rest_Of_Capacity); Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.used_cpu")); My_Scheduler.Variables_Table.entries (Var).Simulation. Integer_Table_Value (Simulations_Range (I)) := Integer (Si.Tcbs (My_Scheduler.Previously_Elected).Used_Cpu); end if; end loop; Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("previously_elected")); My_Scheduler.Variables_Table.entries (Var).Simulation.Integer_Value := Integer (My_Scheduler.Previously_Elected); Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("simulation_time")); My_Scheduler.Variables_Table.entries (Var).Simulation.Integer_Value := Integer (Current_Time); -- Check if tasks are ready or not -- Var := Find_Variable (My_Scheduler.Variables_Table, To_Unbounded_String ("tasks.ready")); for I in 0 .. Si.Number_Of_Tasks - 1 loop if ((Si.Tcbs (I).Tsk.cpu_name = Processor_Name) or (Si.Tcbs (I).Tsk.address_space_name = address_space_Name)) then for J in 0 .. Si.Number_Of_Tasks - 1 loop if My_Scheduler.Variables_Table.entries (Var_Task_Name). Simulation.String_Table_Value (Simulations_Range (J)) = Si.Tcbs (I).Tsk.name then My_Scheduler.Variables_Table.entries (Var).Simulation. Boolean_Table_Value (Simulations_Range (J)) := False; end if; end loop; end if; end loop; for I in 0 .. Si.Number_Of_Tasks - 1 loop if ((Si.Tcbs (I).Tsk.cpu_name = Processor_Name) or (Si.Tcbs (I).Tsk.address_space_name = address_space_Name)) then if (Si.Tcbs (I).Wake_Up_Time <= Current_Time) and (Si.Tcbs (I).Rest_Of_Capacity /= 0) then if (With_Offsets = False) or Check_Offset (Si.Tcbs (I), Current_Time) then if (With_Precedencies = False) or Check_Precedencies (Si, My_Dependencies, Current_Time, Si.Tcbs (I)) then for J in 0 .. Si.Number_Of_Tasks - 1 loop if My_Scheduler.Variables_Table.entries ( Var_Task_Name).Simulation.String_Table_Value ( Simulations_Range (J)) = Si.Tcbs (I).Tsk.name then My_Scheduler.Variables_Table.entries (Var). Simulation.Boolean_Table_Value (Simulations_Range( J)) := True; end if; end loop; end if; end if; end if; end if; end loop; end update_interpreter_variables_after_task_execution; end Scheduler.user_defined.interpreted;