------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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: 523 $ -- $Date: 2012-09-26 15:09:39 +0200 (Wed, 26 Sep 2012) $ -- $Author: fotsing $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with Xml_Tag; use Xml_Tag; with double_util; use double_util; with Feasibility_Test.processor_utilization; use Feasibility_Test.processor_utilization; with Text_IO; use Text_IO; with Translate; use Translate; with unbounded_strings; use unbounded_strings; with Scheduler; use Scheduler; with Scheduling_Analysis; use Scheduling_Analysis; with Call_Framework_Interface; use Call_Framework_Interface; with Scheduling_Analysis; use Scheduling_Analysis.Double_Tasks_Parameters_Package; with priority_assignment.rm; use priority_assignment.rm; with priority_assignment.dm; use priority_assignment.dm; with systems; use systems; with Cache_Set; use Cache_Set; with Caches; use Caches; with Integer_Arrays; use Integer_Arrays; with Caches; use Caches.Cache_Blocks_Table_Package; package body feasibility_test.periodic_task_worst_case_response_time_fixed_priority is procedure Compute_Response_Time (My_Scheduler : in Rm_Scheduler; My_Tasks : in out Tasks_Set; Processor_Name : in Unbounded_String; Msg : in out Unbounded_String; Response_Time : out Response_Time_Table; With_CRPD : in Boolean := false; CRPD_Computation_Approach : in CRPD_Computation_Approach_Type := ECB_Only; Block_Reload_Time : in Natural := 0; My_Cache_Access_Profiles : in Cache_Access_Profiles_Set := no_cache_access_profile) is begin -- check if tasks are periodic -- Periodic_Control (My_Tasks, Processor_Name); -- check start time -- Start_Time_Control (My_Tasks, Processor_Name); -- check offset -- Offset_Control (My_Tasks, Processor_Name); -- check if deadlines are equal than period -- Have_Deadlines_Equal_Than_Periods_Control (My_Tasks, Processor_Name); -- Check processor utilization first -- if (Processor_Utilization_Over_Period (My_Tasks, Processor_Name) > 1.0) then raise Processor_Utilization_Exceeded; end if; -- Compute response time -- Compute_Response_Time (Fixed_Priority_Scheduler (My_Scheduler), My_Tasks, Processor_Name, Msg, Response_Time); end Compute_Response_Time; procedure Compute_Response_Time (My_Scheduler : in Dm_Scheduler; My_Tasks : in out Tasks_Set; Processor_Name : in Unbounded_String; Msg : in out Unbounded_String; Response_Time : out Response_Time_Table; With_CRPD : in Boolean := false; CRPD_Computation_Approach : in CRPD_Computation_Approach_Type := ECB_Only; Block_Reload_Time : in Natural := 0; My_Cache_Access_Profiles : in Cache_Access_Profiles_Set := no_cache_access_profile) is begin -- check if tasks are periodics -- Periodic_Control (My_Tasks, Processor_Name); -- Check processor utilization first -- if (Processor_Utilization_Over_Period (My_Tasks, Processor_Name) > 1.0) then raise Processor_Utilization_Exceeded; end if; -- check start time -- Start_Time_Control (My_Tasks, Processor_Name); -- check offset -- Offset_Control (My_Tasks, Processor_Name); -- Compute response time -- Compute_Response_Time (Fixed_Priority_Scheduler (My_Scheduler), My_Tasks, Processor_Name, Msg, Response_Time); end Compute_Response_Time; procedure Compute_Response_Time (My_Scheduler : in Hpf_Scheduler; My_Tasks : in out Tasks_Set; Processor_Name : in Unbounded_String; Msg : in out Unbounded_String; Response_Time : out Response_Time_Table; With_CRPD : in Boolean := false; CRPD_Computation_Approach : in CRPD_Computation_Approach_Type := ECB_Only; Block_Reload_Time : in Natural := 0; My_Cache_Access_Profiles : in Cache_Access_Profiles_Set := no_cache_access_profile) is begin -- Check if tasks are periodics -- Periodic_Control(My_Tasks, Processor_Name); -- Check processor utilization first -- if (Processor_Utilization_Over_Period (My_Tasks, Processor_Name) > 1.0) then raise Processor_Utilization_Exceeded; end if; -- Check start time -- Start_Time_Control (My_Tasks, Processor_Name); -- Check offset -- Offset_Control (My_Tasks, Processor_Name); -- Compute response time -- Compute_Response_Time (Fixed_Priority_Scheduler (My_Scheduler), My_Tasks, Processor_Name, Msg, Response_Time, With_CRPD, CRPD_Computation_Approach, Block_Reload_Time, My_Cache_Access_Profiles); end Compute_Response_Time; -- compute the value of level-i busy period -- function compute_L (My_Tasks : in Tasks_Set; Current_Task : in Generic_Task_Ptr) return Double is Iterator2 : Tasks_Iterator; Taskj2 : Generic_Task_Ptr; Ln, Ln1 : Double; begin Ln := -0.1; Ln1 := 1.0; while Ln1 /= Ln loop reset_iterator (My_Tasks, Iterator2); Ln := Ln1; Ln1 := 0.0; loop current_element (My_Tasks, Taskj2, Iterator2); if (Taskj2.priority >= Current_Task.priority) then Ln1 := Ln1 + Double'Ceiling (Ln / Double (Periodic_Task_Ptr (Taskj2).period)) * Double (Taskj2.capacity); end if; exit when is_last_element (My_Tasks, Iterator2); next_element (My_Tasks, Iterator2); end loop; end loop; return Ln1; end compute_L; function Compute_Wiq_non_preemptive (My_Tasks : in Tasks_Set; --all the task Current_Task : in Generic_Task_Ptr; --the task examine q : in Integer) return Double is Iterator2 : Tasks_Iterator; Iterator3 : Tasks_Iterator; Taskk, Taskj : Generic_Task_Ptr; Ck, Ck_tmp, Wiq_k, Wiq_k1 : Double; begin --initialization -- Wiq_k := -0.1; Wiq_k1 := 1.0; Ck := 0.0; Ck_tmp := 0.0; -- approximations for Wiq -- exit loop when approximations converge -- while Wiq_k1 /= Wiq_k loop reset_iterator (My_Tasks, Iterator2); Wiq_k := Wiq_k1; Wiq_k1 := Double (q * Current_Task.capacity); -- Iterate on all tasks -- loop current_element (My_Tasks, Taskj, Iterator2); -- If Taskj is in hp(Taski) -- if (Taskj.priority > Current_Task.priority) then Wiq_k1 := Wiq_k1 + (Double'Floor (Wiq_k / Double (Periodic_Task_Ptr (Taskj).period)) + 1.0) * Double (Taskj.capacity); end if; -- exit loop when there is no more task -- exit when is_last_element (My_Tasks, Iterator2); next_element (My_Tasks, Iterator2); end loop; -- Compute the max{Ck-1} -- loop current_element (My_Tasks, Taskk, Iterator3); if (Taskk.priority < Current_Task.priority) then Ck_tmp := Double (Taskk.capacity) - 1.0; if (Ck_tmp > Ck) then Ck := Ck_tmp; end if; end if; exit when is_last_element (My_Tasks, Iterator3); next_element (My_Tasks, Iterator3); end loop; Wiq_k1 := Wiq_k1 + Ck; end loop; return Wiq_k1; end Compute_Wiq_non_preemptive; function Compute_Gamma_UCB_Union_Multiset (My_Tasks : in Tasks_Set; task_i : in Generic_Task_Ptr; task_j : in Generic_Task_Ptr; Response_Time : in Response_Time_Table; Wiq : in Double; q : in Natural; CRPD_Computation_Approach : in CRPD_Computation_Approach_Type := ECB_Only; Block_Reload_Time : in Natural := 0; My_Cache_Access_Profiles : in Cache_Access_Profiles_Set := no_cache_access_profile) return Natural is cap_j : Cache_Access_Profile_Ptr; cap_k : Cache_Access_Profile_Ptr; task_k : Generic_Task_Ptr; my_iterator : Tasks_Iterator; n : Natural := 0; gamma_ij : Natural := 0; R_i : Natural := 0; R_k : Natural := 0; EkRi : Natural := 0; EjRk : Natural := 0; EjRi : Natural := 0; M_UCB_ij : Integer_Array; M_ECB_j : Integer_Array; M : Integer_Array; begin Initialize(M); ----------------------------- -- Compute: M_UCB_ij ----------------------------- reset_iterator (My_Tasks, my_iterator); loop current_element (My_Tasks, task_k, my_iterator); --aff(i,j) = hep(i) \cap lp(j) if (task_k.priority >= task_i.priority AND task_k.priority < task_j.priority AND task_k.name /= task_j.name) then -- E_k(R_i) = ceiling((R_i + J_k / T_k) EkRi := Natural(Double'Ceiling((Double(R_i) + Double(Periodic_Task_Ptr(task_k).jitter))/Double(Periodic_Task_Ptr(task_k).period))); Put_line("R_i:" & R_i'Img); Put_Line("Periodic_Task_Ptr(task_k).jitter:" & Periodic_Task_Ptr(task_k).jitter'Img); Put_Line("Periodic_Task_Ptr(task_k).period:" & Periodic_Task_Ptr(task_k).period'Img); Put_Line("EkRi:" & EkRi'Img); -- E_j(R_k) = ceiling((R_k + J_j / T_j)) for i in 0..Response_Time.nb_entries-1 loop if(Response_Time.entries(i).item.name = task_k.name) then R_k := Natural(Response_Time.entries(i).data); end if; end loop; if(task_k.name = task_i.name) then R_k := R_i; end if; EjRk := Natural(Double'Ceiling((Double(R_k) + Double(Periodic_Task_Ptr(task_j).jitter))/Double(Periodic_Task_Ptr(task_j).period))); Put_Line("R_k: " & R_k'Img); Put_Line("EjRk:" & EjRk'Img); cap_k := Search_Cache_Access_Profile(My_Cache_Access_Profiles, task_k.cache_access_profile_name); for i in 0..EkRi*EjRk-1 loop for i in 0..cap_k.UCBs.Nb_Entries-1 loop Add(M_UCB_ij, cap_k.UCBs.Entries(i).cache_block_number); end loop; end loop; end if; exit when is_last_element (My_Tasks, my_iterator); next_element (My_Tasks, my_iterator); end loop; ----------------------------- -- Compute: M_ECB_j ----------------------------- -- E_j(R_i) = ceiling((R_i + J_j / T_j) EjRi := Natural(Double'Ceiling((Double(R_i) + Double(Periodic_Task_Ptr(task_j).jitter))/Double(Periodic_Task_Ptr(task_j).period))); Put_Line("EjRi:"& EjRi'Img); cap_j := Search_Cache_Access_Profile(My_Cache_Access_Profiles,task_j.cache_access_profile_name); for l in 0..EjRi-1 loop for i in 0..cap_j.ECBs.Nb_Entries-1 loop Add(M_ECB_j, true, cap_j.ECBs.Entries(i).cache_block_number); end loop; end loop; ----------------------------- -- Union ----------------------------- M := Multiset_Intersection(M_UCB_ij,M_ECB_j); gamma_ij := Block_Reload_Time*M.Size; return gamma_ij; end Compute_Gamma_UCB_Union_Multiset; function Compute_Gamma_ECB_Union_Multiset (My_Tasks : in Tasks_Set; task_i : in Generic_Task_Ptr; task_j : in Generic_Task_Ptr; Response_Time : in Response_Time_Table; Wiq : in Double; q : in Natural; CRPD_Computation_Approach : in CRPD_Computation_Approach_Type := ECB_Only; Block_Reload_Time : in Natural := 0; My_Cache_Access_Profiles : in Cache_Access_Profiles_Set := no_cache_access_profile) return Natural is cap_j : Cache_Access_Profile_Ptr; cap_h : Cache_Access_Profile_Ptr; cap_k : Cache_Access_Profile_Ptr; task_h : Generic_Task_Ptr; task_k : Generic_Task_Ptr; my_iterator : Tasks_Iterator; arr_ecbu : Integer_Array; arr_ucb_k : Integer_Array; arr_intersect : Integer_Array; arr_cost : Integer_Array; n : Natural := 0; gamma_ij : Natural := 0; R_i : Natural := 0; R_k : Natural := 0; EkRi : Natural := 0; EjRk : Natural := 0; EjRi : Natural := 0; M : Integer_Array; begin Initialize(arr_ecbu); initialize(arr_ucb_k); initialize(arr_intersect); initialize(arr_cost); initialize(M); R_i := Natural(Wiq) - q * task_i.capacity; Put_Line("R_i: " & R_i'Img); Put_line("Task_i: " & To_String(task_i.name)); Put_line("Task_j: " & To_String(task_j.name)); ----------------------------------------------- --Compute (Union (h \in hp(j) \cup {j}) ECB_h) ----------------------------------------------- --hp(j) reset_iterator (My_Tasks, my_iterator); loop current_element (My_Tasks, task_h, my_iterator); if (task_h.priority >= task_j.priority AND task_h.name /= task_j.name) then cap_h := Search_Cache_Access_Profile(My_Cache_Access_Profiles,task_h.cache_access_profile_name); for i in 0..cap_h.ECBs.Nb_Entries-1 loop Integer_Arrays.Add(arr_ecbu, true, cap_h.ECBs.Entries(i).cache_block_number); end loop; end if; exit when is_last_element (My_Tasks, my_iterator); next_element (My_Tasks, my_iterator); end loop; --{j} cap_j := Search_Cache_Access_Profile(My_Cache_Access_Profiles,task_j.cache_access_profile_name); for i in 0..cap_j.ECBs.Nb_Entries-1 loop Integer_Arrays.Add(arr_ecbu, true, cap_j.ECBs.Entries(i).cache_block_number); end loop; Put("ECB Union Array: "); Print(arr_ecbu); ----------------------------------------------- --Compute UCB_k \cap arr_ecbu ----------------------------------------------- reset_iterator (My_Tasks, my_iterator); loop current_element (My_Tasks, task_k, my_iterator); --aff(i,j) = hep(i) \cap lp(j) if (task_k.priority >= task_i.priority AND task_k.priority < task_j.priority AND task_k.name /= task_j.name) then Put_Line("Task_k: " & To_String(task_k.name)); cap_k := Search_Cache_Access_Profile(My_Cache_Access_Profiles, task_k.cache_access_profile_name); for i in 0..cap_k.UCBs.Nb_Entries-1 loop Add(arr_ucb_k, cap_k.UCBs.Entries(i).cache_block_number); end loop; Put("Arr_UCB_k: "); Print(arr_ucb_k); --UCB_k \cap arr_ecbu Intersect(arr_a => arr_ucb_k, arr_b => arr_ecbu, arr_c => arr_intersect, n => n); -- n is number of evicting UCBs of k Put_Line("N:" & n'Img); -- E_k(R_i) = ceiling((R_i + J_k / T_k) EkRi := Natural(Double'Ceiling((Double(R_i) + Double(Periodic_Task_Ptr(task_k).jitter))/Double(Periodic_Task_Ptr(task_k).period))); Put_line("R_i:" & R_i'Img); Put_Line("Periodic_Task_Ptr(task_k).jitter:" & Periodic_Task_Ptr(task_k).jitter'Img); Put_Line("Periodic_Task_Ptr(task_k).period:" & Periodic_Task_Ptr(task_k).period'Img); Put_Line("EkRi:" & EkRi'Img); -- E_j(R_k) = ceiling((R_k + J_j / T_j)) for i in 0..Response_Time.nb_entries-1 loop if(Response_Time.entries(i).item.name = task_k.name) then R_k := Natural(Response_Time.entries(i).data); end if; end loop; if(task_k.name = task_i.name) then R_k := R_i; end if; EjRk := Natural(Double'Ceiling((Double(R_k) + Double(Periodic_Task_Ptr(task_j).jitter))/Double(Periodic_Task_Ptr(task_j).period))); Put_Line("R_k: " & R_k'Img); Put_Line("EjRk:" & EjRk'Img); for i in 0..EkRi*EjRk-1 loop Add(M,n); end loop; end if; exit when is_last_element (My_Tasks, my_iterator); next_element (My_Tasks, my_iterator); end loop; -- E_j(R_i) = ceiling((R_i + J_j / T_j) EjRi := Natural(Double'Ceiling((Double(R_i) + Double(Periodic_Task_Ptr(task_j).jitter))/Double(Periodic_Task_Ptr(task_j).period))); Put_Line("EjRi:"& EjRi'Img); -- CRPD computation Sort_DESC(M); Put("==Multi set: "); Print(M); for l in 0..EjRi-1 loop gamma_ij := gamma_ij + Block_Reload_Time * M.Elements(l); end loop; Put_Line("==Result:" & gamma_ij'Img); New_Line; return gamma_ij; end Compute_Gamma_ECB_Union_Multiset; function Compute_Wiq_preemptive (My_Tasks : in Tasks_Set; --all the task Current_Task : in Generic_Task_Ptr; --the task examine q : in Integer; Response_Time : in Response_Time_Table; -- Response Time of higher priority task will be always computed With_CRPD : in Boolean := false; CRPD_Computation_Approach : in CRPD_Computation_Approach_Type := ECB_Only; Block_Reload_Time : in Natural := 0; My_Cache_Access_Profiles : in Cache_Access_Profiles_Set := no_cache_access_profile) return Double is Iterator2 : Tasks_Iterator; Taskj : Generic_Task_Ptr; Wiq_k, Wiq_k1 : Double; A_CAP : Cache_Access_Profile_Ptr; Gamma_ij : Natural := 0; gamma_ucbum : Natural := 0; gamma_ecbum : Natural := 0; begin Wiq_k := -0.1; Wiq_k1 := 0.0; -- approximations for Wiq -- exit loop when approximations converge while Wiq_k1 /= Wiq_k loop reset_iterator (My_Tasks, Iterator2); Wiq_k := Wiq_k1; Wiq_k1 := Double ((q + 1) * Current_Task.capacity + Current_Task.blocking_time); -- Iterate on all tasks loop current_element (My_Tasks, Taskj, Iterator2); -- If Taskj is in hp(Taski) if (Taskj.priority > Current_Task.priority) then -- -- CRPD Computation -- if(With_CRPD)then A_CAP := Search_Cache_Access_Profile(My_Cache_Access_Profiles,taskj.cache_access_profile_name); -- Compute CRPD if task j preempting if(CRPD_Computation_Approach = ECB_Only) then Gamma_ij := Natural(A_CAP.ECBs.Nb_Entries) * Block_Reload_Time; elsif(CRPD_Computation_Approach = ECB_Union_Multiset) then Gamma_ij := Compute_Gamma_ECB_Union_Multiset(My_Tasks => My_Tasks, task_i => Current_Task, task_j => Taskj, Response_Time => Response_Time, Wiq => Wiq_k, q => q, CRPD_Computation_Approach => CRPD_Computation_Approach, Block_Reload_Time => Block_Reload_Time, My_Cache_Access_Profiles => My_Cache_Access_Profiles); elsif(CRPD_Computation_Approach = UCB_Union_Multiset) then Gamma_ij := Compute_Gamma_UCB_Union_Multiset(My_Tasks => My_Tasks, task_i => Current_Task, task_j => Taskj, Response_Time => Response_Time, Wiq => Wiq_k, q => q, CRPD_Computation_Approach => CRPD_Computation_Approach, Block_Reload_Time => Block_Reload_Time, My_Cache_Access_Profiles => My_Cache_Access_Profiles); elsif(CRPD_Computation_Approach = Combined_Multiset) then gamma_ucbum := Compute_Gamma_UCB_Union_Multiset(My_Tasks => My_Tasks, task_i => Current_Task, task_j => Taskj, Response_Time => Response_Time, Wiq => Wiq_k, q => q, CRPD_Computation_Approach => CRPD_Computation_Approach, Block_Reload_Time => Block_Reload_Time, My_Cache_Access_Profiles => My_Cache_Access_Profiles); gamma_ecbum := Compute_Gamma_ECB_Union_Multiset(My_Tasks => My_Tasks, task_i => Current_Task, task_j => Taskj, Response_Time => Response_Time, Wiq => Wiq_k, q => q, CRPD_Computation_Approach => CRPD_Computation_Approach, Block_Reload_Time => Block_Reload_Time, My_Cache_Access_Profiles => My_Cache_Access_Profiles); if(gamma_ecbum > gamma_ucbum) then Gamma_ij := gamma_ucbum; else Gamma_ij := gamma_ecbum; end if; end if; end if; -- -- -- Wiq_k1 := Wiq_k1 + Double'Ceiling ((Wiq_k + Double (Periodic_Task_Ptr (Taskj).jitter)) / Double (Periodic_Task_Ptr (Taskj).period)) * (Double (Taskj.capacity) + Double(Gamma_ij)); end if; -- exit loop when there is no more task exit when is_last_element (My_Tasks, Iterator2); next_element (My_Tasks, Iterator2); end loop; end loop; return Wiq_k1; end Compute_Wiq_preemptive; procedure Compute_Response_Time (My_Scheduler : in Fixed_Priority_Scheduler; My_Tasks : in out Tasks_Set; Processor_Name : in Unbounded_String; Msg : in out Unbounded_String; Response_Time : out Response_Time_Table; With_CRPD : in Boolean := false; CRPD_Computation_Approach : in CRPD_Computation_Approach_Type := ECB_Only; Block_Reload_Time : in Natural := 0; My_Cache_Access_Profiles : in Cache_Access_Profiles_Set := no_cache_access_profile) is Tmp : Tasks_Set; Iterator1 : Tasks_Iterator; Taski : Generic_Task_Ptr; I : Response_Time_Range := 0; Li, Q_double, Wiq, Ri : Double := 0.0; Q_arrete, Q : Integer; begin initialize (Response_Time); Current_Processor_Name := Processor_Name; select_and_copy (My_Tasks, Tmp, Select_Cpu'Access); -- Set priority according to the scheduler -- if (My_Scheduler.parameters.scheduler_type = Deadline_Monotonic_Protocol) then Set_Priority_According_To_Dm (Tmp); else if (My_Scheduler.parameters.scheduler_type = Rate_Monotonic_Protocol) then Set_Priority_According_To_Rm (Tmp); end if; end if; sort (Tmp, Increasing_Priority'Access); -- Bibliographical references -- if (My_Scheduler.parameters.preemptive_type = not_preemptive) then -- Non preemptive case -- Msg := To_Unbounded_String (" (") & Lb_See (Current_Language) & To_Unbounded_String ("[1], page 36, ") & Lb_Equation (Current_Language); Msg := Msg & To_Unbounded_String ("13). "); else -- Preemptive case -- Msg := To_Unbounded_String (" (") & Lb_See (Current_Language) & To_Unbounded_String ("[2], page 3, ") & Lb_Equation (Current_Language); Msg := Msg & To_Unbounded_String ("4). "); end if; -- Sort the task in decreasing priority -- Compute Response Time of the higher priority task first -- Sort(Tmp,Decreasing_Priority'Access); -- compute response time for each tasks -- reset_iterator (Tmp, Iterator1); loop -- Selection of the current task -- current_element (Tmp, Taski, Iterator1); -- Initialize response time for current task -- Response_Time.entries (I).data := 0.0; Response_Time.entries (I).item := Taski; Response_Time.nb_entries := Response_Time.nb_entries + 1; if (My_Scheduler.parameters.preemptive_type = not_preemptive) then -- Find the maximum for Ri in [0..Q] -- Q := 0; Li := compute_L (Tmp, Taski); loop Q_double := Double'Floor (Li / Double (Periodic_Task_Ptr (Taski).period)); Q_arrete := Integer (Q_double); Wiq := Compute_Wiq_non_preemptive (Tmp, Taski, Q); --Ri = Wiq + Ci - qTi -- Ri := Wiq + Double (Periodic_Task_Ptr (Taski).capacity) - Double (Q) * Double (Periodic_Task_Ptr (Taski).period); -- Is Ri greater than current maximum for Ri ? -- if (Ri > Response_Time.entries (I).data) then Response_Time.entries (I).data := Ri; end if; exit when Q = Q_arrete; Q := Q + 1; end loop; else Q := 0; loop Wiq := Compute_Wiq_preemptive (Tmp, Taski, Q, Response_Time, With_CRPD, CRPD_Computation_Approach, Block_Reload_Time, My_Cache_Access_Profiles); case Taski.task_type is when Periodic_Type => Ri := Wiq + Double (Periodic_Task_Ptr (Taski).jitter) - Double (Q) * Double (Periodic_Task_Ptr (Taski).period); when others => raise Constraint_Error; end case; -- Is Ri greater than current maximum for Ri ? -- if (Ri > Response_Time.entries (I).data) then Response_Time.entries (I).data := Ri; end if; exit when Wiq <= Double (Q + 1) * Double (Periodic_Task_Ptr (Taski).period); Q := Q + 1; end loop; end if; exit when is_last_element (Tmp, Iterator1); next_element (Tmp, Iterator1); I := I + 1; end loop; end Compute_Response_Time; end feasibility_test.periodic_task_worst_case_response_time_fixed_priority;