------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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 Text_IO; use Text_IO; with xml_tag; use xml_tag; with scheduler.fixed_priority; use scheduler.fixed_priority; with scheduler.fixed_priority.dm; use scheduler.fixed_priority.dm; with scheduler.fixed_priority.rm; use scheduler.fixed_priority.rm; with double_util; use double_util; with translate; use translate; with tasks; use tasks; with task_group_set; use task_group_set; with event_analyzers; use event_analyzers; with event_analyzer_set; use event_analyzer_set; with event_analyzer_set; use event_analyzer_set.generic_event_analyzer_set; with Ada.Numerics.Aux; use Ada.Numerics.Aux; with unbounded_strings; use unbounded_strings; with scheduling_analysis; use scheduling_analysis; with GNAT.Current_Exception; use GNAT.Current_Exception; with expressions; use expressions; with framework_config; use framework_config; with time_unit_events; use time_unit_events; with multiprocessor_services; use multiprocessor_services; with partitioning_services; use partitioning_services; with debug; use debug; with priority_assignment.dm; use priority_assignment.dm; with priority_assignment.rm; use priority_assignment.rm; with priority_assignment.audsley_opa; use priority_assignment.audsley_opa; with priority_assignment; use priority_assignment; with cache_set; use cache_set; with priority_assignment.audsley_opa_crpd; use priority_assignment.audsley_opa_crpd; with feasibility_test; use feasibility_test; with feasibility_test.processor_utilization; use feasibility_test.processor_utilization; with feasibility_test.feasibility_interval; use feasibility_test.feasibility_interval; with feasibility_test.periodic_task_worst_case_response_time; use feasibility_test.periodic_task_worst_case_response_time; with feasibility_test.transaction_worst_case_response_time; use feasibility_test.transaction_worst_case_response_time; with scheduling_analysis.extended.task_analysis; use scheduling_analysis.extended.task_analysis; with framework; use framework; with core_units; use core_units; use core_units.core_units_table_package; with caches; use caches; with cache_block_set; use cache_block_set; with cache_access_profile_set; use cache_access_profile_set; with processor_interface; use processor_interface; with feasibility_test.processor_demand; use feasibility_test.processor_demand; package body call_scheduling_framework is procedure compute_simulation_time_line (sys : in out system; result : in out Unbounded_String; period : in Natural; options : in scheduling_option; event_to_generate : in time_unit_event_type_boolean_table; output : in output_format := string_output) is begin put_debug ("Call Compute_Simulation_Time_Line"); sort (sys.tasks, increasing_name'access); scheduling_base_period := period; initialize (sched.all); build_multiprocessor_scheduling (sys, sched, event_to_generate, period, options); exception when exit_statement_exception => result := result & lb_minus & lb_simulation_warning (current_language) & Exception_Message & unbounded_lf; when parametric_file_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_parametric_file_error (current_language) & lb_comma & Exception_Message & unbounded_lf; when type_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_type_error (current_language) & lb_comma & Exception_Message & unbounded_lf; when statement_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_statement_error (current_language) & lb_comma & Exception_Message & unbounded_lf; when variable_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_variable_error (current_language) & lb_comma & Exception_Message & unbounded_lf; when syntax_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_syntax_error (current_language) & lb_comma & Exception_Message & unbounded_lf; when time_unit_package.indexed_table_full => result := result & lb_compute_scheduling_error_22 (current_language) & unbounded_lf; initialize (sched.all); when cache_access_profile_must_be_defined => result := result & unbounded_lf & lb_cache_access_profile_must_be_defined (current_language) & unbounded_lf; end compute_simulation_time_line; procedure compute_simulation_basics (sys : in system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; output : in output_format := string_output) is check : Unbounded_String; begin put_debug ("Call Compute_Simulation_Basics"); check := empty_string; compute_simulation_number_of_context_switch (sys, check, a_processor, output); result := result & check; check := empty_string; compute_simulation_number_of_preemption (sys, check, a_processor, output); result := result & check; check := empty_string; compute_simulation_response_time (sys, check, a_processor, True, False, False, output); result := result & unbounded_lf & check & unbounded_lf; end compute_simulation_basics; procedure compute_simulation_number_of_context_switch (sys : in system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; output : in output_format := string_output) is nb : Natural := 0; begin put_debug ("Call Compute_Simulation_Number_Of_Context_Switch"); if output = xml_output then set_tag; else set_empty; end if; for j in 0 .. sched.nb_entries - 1 loop if sched.entries (j).item.name = a_processor.name then if sched.entries (j).data.error_msg /= empty_string then result := result & sched.entries (j).data.error_msg & unbounded_lf; else nb := number_of_switch_context_from_simulation (sched.entries (j).data.result); result := result & start_line & lb_minus & lb_number_of_context_switch (current_language) & lb_colon & start_num_of_context_switch & nb'img & end_num_of_context_switch & end_line & unbounded_lf; end if; end if; end loop; end compute_simulation_number_of_context_switch; procedure compute_simulation_number_of_preemption (sys : in system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; output : in output_format := string_output) is nb : Natural := 0; begin put_debug ("Call Compute_Simulation_Number_Of_Preemption"); if output = xml_output then set_tag; else set_empty; end if; for j in 0 .. sched.nb_entries - 1 loop if sched.entries (j).item.name = a_processor.name then if sched.entries (j).data.error_msg /= empty_string then result := result & sched.entries (j).data.error_msg & unbounded_lf; else nb := number_of_preemption_from_simulation (sched.entries (j).data.result, sys.tasks); result := result & sched.entries (j).data.scheduling_msg; result := result & start_line & lb_minus & lb_number_of_preemption (current_language) & lb_colon & start_num_of_preemp & nb'img & end_num_of_preemp & end_line & unbounded_lf; end if; end if; end loop; end compute_simulation_number_of_preemption; procedure compute_simulation_response_time (sys : in system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; worst_case : Boolean; best_case : Boolean; average_case : Boolean; output : in output_format := string_output) is check : Unbounded_String := empty_string; a_task : generic_task_ptr; my_iterator : tasks_iterator; min : Natural := 0; max : Natural := 0; average : Double := 0.0; missed : Boolean := False; completed : Boolean := True; has_error : Boolean := False; begin put_debug ("Call Compute_Simulation_Response_Time"); for j in 0 .. sched.nb_entries - 1 loop if sched.entries (j).item.name = a_processor.name then if sched.entries (j).data.error_msg /= empty_string then has_error := True; end if; if get_number_of_task_from_processor (sys.tasks, a_processor.name) > 0 then result := lb_minus & lb_task_response_time_from_simulation (current_language) & lb_colon & unbounded_lf; reset_iterator (sys.tasks, my_iterator); loop current_element (sys.tasks, a_task, my_iterator); check := empty_string; if (a_processor.name = a_task.cpu_name) then response_time_by_simulation (a_task, sched.entries (j).data.result, check, max, min, average); result := result & start_task & To_Unbounded_String (" ") & a_task.name & To_Unbounded_String (" =>"); if worst_case then result := result & max'img & To_Unbounded_String ("/worst "); end if; if best_case then result := result & min'img & To_Unbounded_String ("/best "); end if; if average_case then result := result & format (average) & To_Unbounded_String ("/average "); end if; if (worst_case) and (max = 0) then result := result & lb_comma & lb_task_is_not_over_response_time_is_not_computed (current_language); completed := False; end if; result := result & check & unbounded_lf; if check /= empty_string then missed := True; end if; result := result & end_task; end if; exit when is_last_element (sys.tasks, my_iterator); next_element (sys.tasks, my_iterator); end loop; end if; end if; end loop; if not has_error then if completed = True then if missed = False then result := result & lb_no_deadline_missed_in_the_computed_scheduling (current_language) & unbounded_lf; else result := result & lb_deadline_will_be_missed_task_are_not_schedulable (current_language) & unbounded_lf; end if; else result := result & lb_cannot_say_if_deadline_will_be_missed_in_the_computed_scheduling (current_language); end if; end if; end compute_simulation_response_time; procedure compute_feasibility_interval (sys : in system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; output : in output_format := string_output) is period_string : Unbounded_String; free_ut_string : Unbounded_String; period : Double := 0.0; util : Double := 0.0; free_ut : Double := 0.0; validate : Boolean; msg : Unbounded_String; begin put_debug ("Call Compute_Feasibility_Interval"); if output = xml_output then set_tag; else set_empty; end if; begin calculate_feasibility_interval (sys, a_processor, validate, period, msg); exception when Constraint_Error => -- A large task set with many different period values can lead to -- a CONSTRAINT_ERROR exception due to type overflow -- result := result & start_line & To_Unbounded_String ("- ") & Exception_Name & " " & Exception_Message & end_line & unbounded_lf; result := result & start_line & To_Unbounded_String ("- ") & "Cheddar warning: Scheduling period overflow! " & end_line & unbounded_lf; end; period_string := " " & format (period, 0); result := result & start_line & lb_scheduling_period (current_language) & start_bas_per & period_string & end_bas_per & start_ref & msg & end_ref & end_line & unbounded_lf; util := processor_utilization_over_period (sys.tasks, a_processor.name); if (a_processor.processor_type = monocore_type) then free_ut := period * (1.0 - util); else free_ut := period * (Double (multi_cores_processor_ptr (a_processor).cores.nb_entries) - util); end if; free_ut := Double'max (0.0, free_ut); if free_ut > Double (Natural'last) then free_ut_string := To_Unbounded_String (Double'image (free_ut)); else free_ut_string := To_Unbounded_String (Natural'image (Natural (free_ut))); end if; result := result & start_line & To_Unbounded_String ("-") & start_unit & free_ut_string & end_unit & lb_free_unit_time (current_language) & end_line & unbounded_lf; exception when task_set.task_must_be_periodic => result := result & lb_compute_scheduling_error_2 (current_language) & unbounded_lf; when task_set.task_model_error => result := result & lb_compute_scheduling_error_3 (current_language) & unbounded_lf; end compute_feasibility_interval; procedure compute_feasibility_processor_utilization_factor (sys : in system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; output : in output_format := string_output) is util : Double; utildi : Double; a_scheduler : generic_scheduler_ptr; begin put_debug ("Call Compute_Feasibility_Processor_Utilization_Factor"); if output = xml_output then set_tag; else set_empty; end if; -- Compute feasibility interval -- result := result & lb_feasibility_number1 (current_language) & unbounded_lf & unbounded_lf; compute_feasibility_interval (sys, result, a_processor, output); -- Compute number of cores of the processor -- if (a_processor.processor_type = monocore_type) then result := result & lb_processor_has_number_of_cores (current_language) & To_Unbounded_String (" 1. ") & unbounded_lf; else result := result & lb_processor_has_number_of_cores (current_language) & To_Unbounded_String (" " & multi_cores_processor_ptr (a_processor).cores.nb_entries'img & ". ") & unbounded_lf; end if; -- Compute processor utilization faction over deadline -- begin utildi := processor_utilization_over_deadline (sys.tasks, a_processor.name); result := result & start_line & lb_utilization_with_deadline (current_language) & start_deadl_fact & format (utildi) & end_deadl_fact & start_ref & To_Unbounded_String (" (") & lb_see (current_language) & To_Unbounded_String ("[1], page 6). ") & end_ref & end_line & unbounded_lf; exception when task_set.task_must_be_periodic => result := result & lb_compute_scheduling_error_9 (current_language) & unbounded_lf; when task_set.task_model_error => result := result & lb_compute_scheduling_error_10 (current_language) & unbounded_lf; when deadline_error => result := result & lb_compute_scheduling_error_21 (current_language) & unbounded_lf; end; -- Compute processor utilization factor over period -- begin util := processor_utilization_over_period (sys.tasks, a_processor.name); result := result & start_line & lb_utilization_with_period (current_language) & start_per_fact & format (util) & end_per_fact & start_ref & To_Unbounded_String (" (") & lb_see (current_language) & To_Unbounded_String ("[1], page 6). ") & end_ref & unbounded_lf; exception when task_set.task_must_be_periodic => result := result & lb_compute_scheduling_error_9 (current_language) & unbounded_lf; when task_set.task_model_error => result := result & lb_compute_scheduling_error_10 (current_language) & unbounded_lf; end; if (a_processor.processor_type = monocore_type) then -- Compute feasibility test on the Processor utilization bound -- begin result := result & start_line; a_scheduler := build_a_scheduler (a_processor); utilization_factor_feasibility_test (a_scheduler, sys.tasks, a_processor.name, result); free (a_scheduler); exception when task_set.task_must_be_periodic => result := result & lb_compute_scheduling_error_9 (current_language) & unbounded_lf; when task_set.task_model_error => result := result & lb_compute_scheduling_error_10 (current_language) & unbounded_lf; when deadline_error => result := result & lb_compute_scheduling_error_21 (current_language) & unbounded_lf; when task_set.start_time_error => result := result & lb_compute_scheduling_error_23 (current_language) & unbounded_lf; when task_set.offset_error => result := result & lb_compute_scheduling_error_24 (current_language) & unbounded_lf; end; end if; end compute_feasibility_processor_utilization_factor; procedure compute_feasibility_test_by_name (sys : in system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; test_name : Unbounded_String; output : in output_format := string_output) is begin put_debug ("Call Compute_Feasibility_Test_By_Name"); if output = xml_output then set_tag; else set_empty; end if; result := result & unbounded_lf; end compute_feasibility_test_by_name; procedure compute_feasibility_response_time (sys : in out system; result : in out Unbounded_String; a_transaction : in transaction_wcrt_type; wcrt_with_memory_interferences : in memory_interference_computation_approach_type := no_memory_interference; with_crpd : in crpd_computation_approach_type := no_crpd; a_processor : in generic_processor_ptr; output : in output_format := string_output) is rt : response_time_table; msg : Unbounded_String := empty_string; missed : Boolean := False; a_scheduler : generic_scheduler_ptr; begin put_debug ("Call Compute_Feasibility_Response_Time"); if output = xml_output then set_tag; else set_empty; end if; result := result & unbounded_lf & lb_feasibility_number2 (current_language) & unbounded_lf & unbounded_lf; case a_transaction is when periodic => a_scheduler := build_a_scheduler (a_processor); compute_response_time (a_scheduler, sys, a_processor.name, msg, rt, wcrt_with_memory_interferences, with_crpd); free (a_scheduler); when tindell => tindell_compute_offset_response_time (sys.task_groups, a_processor.name, msg, rt); when audsley => audsley_compute_offset_response_time (sys.task_groups, a_processor.name, msg, rt); when palencia => palencia_compute_offset_response_time (sys.task_groups, a_processor.name, msg, rt); when wcdops_plus => wcdops_plus (sys, msg, rt, False); when wcdops_plus_nim => wcdops_plus_nimp (sys, msg, rt, False); end case; result := result & start_line & lb_minus & lb_worst_case_task_response_time (current_language) & lb_colon & start_ref & msg & end_ref & unbounded_lf; for i in 0 .. response_time_range (get_number_of_task_from_processor (sys.tasks, a_processor.name) - 1) loop if (rt.entries (i).item /= null) then result := result & start_task & To_Unbounded_String (" ") & rt.entries (i).item.name & To_Unbounded_String (" =>") & Integer'image (Integer (rt.entries (i).data)) & end_task; if (Natural (rt.entries (i).data) > rt.entries (i).item.deadline) then result := result & lb_comma & lb_check_deadline (current_language) & rt.entries (i).item.deadline'img & To_Unbounded_String (")"); missed := True; end if; result := result & unbounded_lf; end if; end loop; if missed = False then result := result & lb_no_deadline_will_be_missed_task_are_schedulable (current_language); else result := result & lb_deadline_will_be_missed_task_are_not_schedulable (current_language); end if; result := result & end_line & unbounded_lf & end_sched_feas & unbounded_lf; exception when task_set.task_must_have_period_equal_to_deadline => result := result & lb_compute_scheduling_error_4 (current_language) & unbounded_lf; when task_set.task_must_be_periodic => result := result & lb_compute_scheduling_error_5 (current_language) & unbounded_lf; when task_set.task_model_error => result := result & lb_compute_scheduling_error_6 (current_language) & unbounded_lf; when processor_utilization_exceeded => result := result & lb_compute_scheduling_error_7 (current_language) & unbounded_lf; when task_set.start_time_error => result := result & lb_compute_scheduling_error_12 (current_language) & unbounded_lf; when task_set.offset_error => result := result & lb_compute_scheduling_error_13 (current_language) & unbounded_lf; when invalid_scheduler => result := result & lb_compute_scheduling_error_18 (current_language) & unbounded_lf; when computation_time_exceeded => result := result & lb_computation_time_exceeded (current_language) & unbounded_lf; when transaction_error => result := result & lb_compute_scheduling_error_25 (current_language) & unbounded_lf; when task_set.generic_task_set.empty_set => result := result & lb_compute_scheduling_error_26 (current_language) & unbounded_lf; when cache_access_profile_must_be_defined => result := result & lb_cache_access_profile_must_be_defined (current_language) & unbounded_lf; when cache_access_profile_must_be_defined_for_all_tasks => result := result & lb_cache_access_profile_must_be_defined (current_language) & unbounded_lf; end compute_feasibility_response_time; procedure set_priorities (sys : in out system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; a_scheduler : in framework_statement_type; output : in output_format := string_output) is ok : Boolean := True; error_msg : Unbounded_String; a_task : generic_task_ptr; my_task_iterator : tasks_iterator; begin put_debug ("Call Set_Priorities"); if output = xml_output then set_tag; else set_empty; end if; begin if (a_scheduler = scheduling_set_priorities_according_to_rate_monotonic) then set_priority_according_to_rm (sys.tasks, a_processor.name); elsif (a_scheduler = scheduling_set_priorities_according_to_deadline_monotonic) then set_priority_according_to_dm (sys.tasks, a_processor.name); elsif (a_scheduler = scheduling_set_priorities_according_to_audsley_opa) then set_priority_according_to_audsley_opa (sys.tasks, a_processor.name); elsif (a_scheduler = scheduling_set_priorities_according_to_opa_crpd_pt_simplified) then set_priority_according_to_cpa (sys.tasks, sys.cache_access_profiles, pt_simplified, a_processor.name); elsif (a_scheduler = scheduling_set_priorities_according_to_opa_crpd_pt) then set_priority_according_to_cpa (sys.tasks, sys.cache_access_profiles, pt_binomial_coefficient, a_processor.name); elsif (a_scheduler = scheduling_set_priorities_according_to_opa_crpd_tree) then set_priority_according_to_cpa (sys.tasks, sys.cache_access_profiles, tree, a_processor.name); end if; exception when task_set.task_must_be_periodic => ok := False; error_msg := lb_priorities_error1 (current_language); when generic_task_set.empty_set => ok := False; error_msg := lb_priorities_error2 (current_language); when no_feasible_priority_assignment_exception => ok := False; error_msg := lb_priorities_error_opa (current_language); when no_feasible_priority_assignment_with_crpd_exception => ok := False; error_msg := lb_priorities_error_opa_crpd (current_language); when offset_must_be_defined => ok := False; error_msg := lb_offset_must_be_defined_for_opa (current_language); when cache_access_profile_not_found => ok := False; error_msg := lb_cache_access_profile_must_be_defined_for_opa (current_language); when cache_access_profile_must_be_defined => ok := False; error_msg := lb_cache_access_profile_must_be_defined_for_opa (current_language); end; if ok then if (a_scheduler = scheduling_set_priorities_according_to_rate_monotonic) then result := result & start_line & lb_set_priorities_rm (current_language) & end_line; end if; if (a_scheduler = scheduling_set_priorities_according_to_deadline_monotonic) then result := result & start_line & lb_set_priorities_dm (current_language) & end_line; end if; if (a_scheduler = scheduling_set_priorities_according_to_audsley_opa) then result := result & start_line & lb_set_priorities_audsley_opa (current_language) & end_line; end if; if (a_scheduler = scheduling_set_priorities_according_to_opa_crpd_pt) then result := result & start_line & lb_set_priorities_opa_crpd_pt (current_language) & end_line; end if; if (a_scheduler = scheduling_set_priorities_according_to_opa_crpd_pt_simplified) then result := result & start_line & lb_set_priorities_opa_crpd_pt_simplified (current_language) & end_line; end if; if (a_scheduler = scheduling_set_priorities_according_to_opa_crpd_tree) then result := result & start_line & lb_set_priorities_opa_crpd_tree (current_language) & end_line; end if; result := result & unbounded_lf & start_line & lb_priorities (current_language); reset_iterator (sys.tasks, my_task_iterator); loop current_element (sys.tasks, a_task, my_task_iterator); if (a_task.cpu_name = a_processor.name) then result := result & unbounded_lf & start_task & To_Unbounded_String (" ") & a_task.name & To_Unbounded_String (" =>") & To_Unbounded_String (a_task.priority'img) & end_task; end if; exit when is_last_element (sys.tasks, my_task_iterator); next_element (sys.tasks, my_task_iterator); end loop; result := result & unbounded_lf & end_line & unbounded_lf & end_set_prio; else result := result & error_msg; end if; end set_priorities; procedure run_user_defined_event_handlers (sys : in system; result : in out Unbounded_String; output : in output_format := string_output) is msg : Unbounded_String; my_iterator : event_analyzers_iterator; an_event_analyzer : event_analyzer_ptr; begin put_debug ("Call Run_User_Defined_Event_Handlers"); if output = xml_output then set_tag; else set_empty; end if; if (get_number_of_elements (sys.event_analyzers) > 0) then reset_iterator (sys.event_analyzers, my_iterator); loop current_element (sys.event_analyzers, an_event_analyzer, my_iterator); -- Run an event analyzer --- begin msg := empty_string; result := result & unbounded_lf & unbounded_lf; result := result & lb_minus & lb_event_analyzer_name (current_language) & lb_colon & an_event_analyzer.event_analyzer_source_file_name & unbounded_lf & unbounded_lf; run_an_event_analyzer (sys, sched, an_event_analyzer, msg); result := result & msg; result := result & unbounded_lf & unbounded_lf; exception when parametric_file_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_parametric_file_error (current_language) & lb_comma & Exception_Message & unbounded_lf; when type_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_type_error (current_language) & lb_comma & Exception_Message & unbounded_lf; when statement_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_statement_error (current_language) & lb_comma & Exception_Message & unbounded_lf; when variable_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_variable_error (current_language) & lb_comma & Exception_Message & unbounded_lf; when syntax_error => result := result & lb_minus & lb_simulation_error (current_language) & lb_syntax_error (current_language) & lb_comma & Exception_Message & unbounded_lf; end; exit when is_last_element (sys.event_analyzers, my_iterator); next_element (sys.event_analyzers, my_iterator); end loop; end if; end run_user_defined_event_handlers; procedure partionning_tasks (sys : in out system; result : in out Unbounded_String; a_parition_rule : in partioning_type; output : in output_format := string_output) is partitionned_task_set : tasks_set; a_task : generic_task_ptr; my_task_iterator : tasks_iterator; msg : Unbounded_String := empty_string; begin put_debug ("Call Partionning_Tasks"); if output = xml_output then set_tag; else set_empty; end if; case a_parition_rule is when general_task => partition_general_task (sys.processors, sys.tasks, msg, partitionned_task_set); when best_fit => partition_best_fit (sys.processors, sys.tasks, msg, partitionned_task_set); when next_fit => partition_next_fit (sys.processors, sys.tasks, msg, partitionned_task_set); when first_fit => partition_first_fit (sys.processors, sys.tasks, msg, partitionned_task_set); when small_task => partition_small_task (sys.processors, sys.tasks, msg, partitionned_task_set); end case; result := result & start_line & lb_minus & lb_partitioning_result (current_language) & start_ref & msg & end_ref & lb_colon & unbounded_lf; sys.tasks := partitionned_task_set; reset_iterator (sys.tasks, my_task_iterator); loop current_element (sys.tasks, a_task, my_task_iterator); result := result & unbounded_lf & To_Unbounded_String (" ") & a_task.name & To_Unbounded_String (" =>") & a_task.cpu_name; exit when is_last_element (sys.tasks, my_task_iterator); next_element (sys.tasks, my_task_iterator); end loop; result := result & unbounded_lf & unbounded_lf; exception when processors_should_have_the_same_scheduler => result := result & lb_partition_error1 (current_language); when no_such_processors => result := result & lb_partition_error2 (current_language); when invalid_scheduler_multiprocessors => result := result & lb_partition_error3 (current_language); when task_set.task_must_be_periodic => result := result & lb_partition_error4 (current_language); end partionning_tasks; procedure compute_feasibility_basics (sys : in out system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; output : in output_format := string_output) is begin put_debug ("Call Compute_Feasibility_Basics"); compute_feasibility_processor_utilization_factor (sys, result, a_processor, output); compute_feasibility_response_time (sys, result, periodic, no_memory_interference, no_crpd, a_processor, output); end compute_feasibility_basics; ------------------------------------------------------------------------ -- Compute_Feasibility_By_Demand_Bound_Function -- "Preemptively Scheduling Hard-Real-Time Sporadic Tasks on One processor", -- Baruah, Mok and Rosier, 1990 -- Implementation Notes: -- S. Rubini, 11/2018 ------------------------------------------------------------------------ procedure compute_feasibility_by_demand_bound_function (sys : in system; result : in out Unbounded_String; a_processor : in generic_processor_ptr; output : in output_format := string_output) is compute_report : feasibility_test.processor_demand .feasibility_test_report; a_scheduler : generic_scheduler_ptr; begin put_debug ("Call Compute_Feasibility_By_Demand_Bound_Function"); if output = xml_output then set_tag; else set_empty; end if; result := result & lb_feasibility_dbf (current_language) & unbounded_lf & unbounded_lf; a_scheduler := build_a_scheduler (a_processor); begin sporadic_periodic_task_set_feasibility_test (a_scheduler, sys.tasks, a_processor.name, compute_report); -- report results if compute_report.feasible then if compute_report.motivation = by_processor_utilization_factor then result := result & start_line & lb_sched_explanation1 (current_language) & lb_sched_explanation12 (current_language) & start_fact_bound & format (compute_report.processor_utilization_bound) & end_fact_bound & start_ref & To_Unbounded_String (" (") & lb_see (current_language) & To_Unbounded_String ("[1], page 6). ") & end_ref & end_line & unbounded_lf & start_line & lb_utilization_with_period (current_language) & start_deadl_fact & format (compute_report.processor_utilization) & end_deadl_fact & end_line & unbounded_lf & unbounded_lf; elsif compute_report.motivation = by_dbf then result := result & start_line & lb_sched_explanation_dbf1 (current_language) & start_fact_bound & compute_report.check_interval'img & start_ref & To_Unbounded_String (" (") & lb_see (current_language) & To_Unbounded_String ("[22], page 6). ") & end_ref & end_line & unbounded_lf; else null; -- TODO raise an exception end if; else -- unfeasible if compute_report.motivation = by_processor_utilization_factor then result := result & lb_sched_explanation2 (current_language) & lb_sched_explanation22 (current_language) & start_fact_bound & format (compute_report.processor_utilization_bound) & end_fact_bound & start_ref & To_Unbounded_String (" (") & lb_see (current_language) & To_Unbounded_String ("[1], page 6). ") & end_ref & end_line & unbounded_lf & start_line & lb_utilization_with_period (current_language) & start_fact_bound & format (compute_report.processor_utilization) & end_fact_bound & end_line & unbounded_lf; elsif compute_report.motivation = by_dbf then -- Compute_Report.Overrun_Time /= 0 result := result & lb_sched_explanation_dbf2 (current_language) & start_fact_bound & compute_report.check_interval'img & end_fact_bound & start_ref & To_Unbounded_String (" (") & lb_see (current_language) & To_Unbounded_String ("[22], page ?). ") & end_ref & end_line & unbounded_lf & start_line & lb_minus & lb_feasibility_dbf_check_interval (current_language) & start_fact_bound & compute_report.check_interval'img & end_fact_bound & unbounded_lf & end_line & start_line & lb_minus & lb_feasibility_dbf_overrun_instant (current_language) & start_deadl_fact & compute_report.overrun_time'img & end_deadl_fact & end_line & start_line & unbounded_lf; else null; end if; end if; exception when task_set.task_must_be_sporadic_or_periodic => result := result & lb_compute_scheduling_error_27 (current_language) & unbounded_lf; when invalid_scheduler => result := result & lb_compute_scheduling_error_18 (current_language) & unbounded_lf; end; end compute_feasibility_by_demand_bound_function; end call_scheduling_framework;