From b5792f5cbf80cee4985a7b20e23ebcaf47904989 Mon Sep 17 00:00:00 2001 From: Blinningjr <nicke.l@telia.com> Date: Sun, 3 Jan 2021 11:36:45 +0100 Subject: [PATCH] Moved all the added analysis function to a separate file --- srp_analysis/src/main.rs | 185 +------------------------------ srp_analysis/src/srp_analyser.rs | 185 +++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 181 deletions(-) create mode 100644 srp_analysis/src/srp_analyser.rs diff --git a/srp_analysis/src/main.rs b/srp_analysis/src/main.rs index fa13577..eadd7bd 100644 --- a/srp_analysis/src/main.rs +++ b/srp_analysis/src/main.rs @@ -1,5 +1,9 @@ mod common; +mod srp_analyser; + use common::*; +use srp_analyser::*; + fn main() { let t1 = Task { @@ -79,184 +83,3 @@ fn main() { } -/* - * Calculates the total load factor(Ltot). - * Ltot - * - * Note: We can compute the total CPU request (or load factor), as Ltot = sum(L(T)), T being the set of tasks. - */ -fn total_load_factor(tasks: &Tasks) -> f32 { - let mut ltot: f32 = 0.0; - for t in tasks { - ltot += cpu_load(t); - } - return ltot; -} - - -/* - * Calculates the cpu load of a task(L(t) where t is a task). - * L(t) - * - * Note: Each task t has a WCET C(t) and given (assumed) inter-arrival time A(t). The CPU request (or load) inferred by a task is L(t) = C(t)/A(t). Ask yourself, what is the consequence of C(t) > A(t)? - * Answer: If C(t) > A(t) then the cpu load of task t is more then the available cpu power in the - * worst case. And the task t will not be able to finish in time in the worst case. - */ -fn cpu_load(task: &Task) -> f32 { - return (wcet(&task.trace) as f32) / (task.inter_arrival as f32) -} - - -/* - * Worst case execution time(WCET) of a task t(C(t)). - * C(t) - */ -fn wcet(trace: &Trace) -> u32 { - return trace.end.wrapping_sub(trace.start); -} - - -/* - * Calculates the response time of task(R(t)). - * R(t) - * - * Note: * R(t) = B(t) + C(t) + I(t), where - * - B(t) is the blocking time for task t, and - * - I(t) is the interference (preemptions) to task t - */ -fn response_time(task: &Task, tasks: &Tasks, ip: &IdPrio, tr: &TaskResources, approx: bool) -> u32 { - let r: u32 = block_time(task, tasks, ip, tr) + wcet(&task.trace) + interference_time(task, tasks, ip, tr, approx).unwrap(); - //println!("response_time {:?}", r); - return r; -} - - -/* - * Calculates the blocking time for task t(B(t)). - * B(t) - * - * Note: B(t) = max(C(l_r)), where P(l) < P(t), π(l_r) >= P(t) - */ -fn block_time(task: &Task, tasks: &Tasks, ip: &IdPrio, tr: &TaskResources) -> u32 { - /* - * Helper function for finding the trace of a resource using only the id an a trace. - */ - fn find_res_tr<'a>(res_id: &String, trace: &'a Trace) -> Option<&'a Trace> { - if trace.id == *res_id { - return Some(trace); - } else { - for tr in &trace.inner { - match find_res_tr(res_id, tr) { - Some(val) => return Some(val), - None => (), - } - } - } - return None; - } - - - // Find all lower priority tasks - let mut lower_prio: Vec<&Task> = vec!(); - for t in tasks { - if t.prio < task.prio { - lower_prio.push(t); - } - } - - //println!("prio {:?}", task.prio); - //println!("lower_prio {:?}", lower_prio); - - // Find all resources that will block the task(resources with a higher of equal priority) from - // the resources that the lower priority tasks use. - let mut block_res: Vec<&Trace> = vec!(); - for lpt in lower_prio { - match tr.get(&lpt.id) { - Some(resources) =>{ - for r in resources { - if *ip.get(r).unwrap() >= task.prio { - block_res.push(find_res_tr(r, &lpt.trace).unwrap()); - } - } - }, - None => (), - }; - } - - //println!("block_res {:?}", block_res); - - // Calculate the max wcet of the list of blocking resource traces. - let mut block_time: u32 = 0; - for tr in block_res { - let wcet = wcet(tr); - if wcet > block_time { - block_time = wcet; - } - } - - //println!("block time {:?}", block_time); - - return block_time; -} - - - -/* - * Calculates the interference (preemptions) to task t(I(t)). - * I(t) - * - * Note: I(t) = sum(C(h) * ceiling(Bp(t)/A(h))), forall tasks h, P(h) > P(t), where - * Bp(t) is the busy-period - */ -fn interference_time(task: &Task, tasks: &Tasks, ip: &IdPrio, tr: &TaskResources, approx: bool) -> Result<u32, String> { - fn calc_interference(task: &Task, tasks: &Tasks, busy_period: u32) -> u32 { - let mut interference: u32 = 0; - for t in tasks { - if t.prio > task.prio { - interference += wcet(&t.trace) * (((busy_period as f32) / (t.inter_arrival as f32)).ceil() as u32); - } - } - return interference; - } - - if approx { - let interference: u32 = calc_interference(task, tasks, task.deadline); - //println!("interference_time {:?}", interference); - return Ok(interference); - } else { - let constant = block_time(task, tasks, ip, tr) + wcet(&task.trace); - let mut busy_period: u32 = constant + calc_interference(task, tasks, constant); - loop { - if busy_period > task.deadline { - return Err("Busy period is longer then deadline".to_string()); - } else { - let new_busy_period: u32 = constant + calc_interference(task, tasks, busy_period); - if busy_period == new_busy_period { - return Ok(new_busy_period - constant); - } else { - busy_period = new_busy_period; - } - } - } - } -} - - -/* - * Analyse tasks. - * - * Note: Finally, make a function that iterates over the task set and returns a vector with containing: -Vec<Task, R(t), C(t), B(t), I(t)>. Just a simple println! of that vector gives the essential information on the analysis. - */ -fn analyse(tasks: &Tasks, ip: &IdPrio, tr: &TaskResources, approx: bool) -> Vec<(Task, u32, u32, u32, u32)> { - let mut analysis: Vec<(Task, u32, u32, u32, u32)> = vec!(); - for t in tasks { - let r_t = response_time(t, tasks, ip, tr, approx); - let c_t = wcet(&t.trace); - let b_t = block_time(t, tasks, ip, tr); - let i_t = interference_time(t, tasks, ip, tr, approx).unwrap(); - analysis.push((t.clone(), r_t, c_t, b_t, i_t)); - } - return analysis; -} - diff --git a/srp_analysis/src/srp_analyser.rs b/srp_analysis/src/srp_analyser.rs new file mode 100644 index 0000000..4cb4524 --- /dev/null +++ b/srp_analysis/src/srp_analyser.rs @@ -0,0 +1,185 @@ +use super::common::*; + + +/* + * Calculates the total load factor(Ltot). + * Ltot + * + * Note: We can compute the total CPU request (or load factor), as Ltot = sum(L(T)), T being the set of tasks. + */ +pub fn total_load_factor(tasks: &Tasks) -> f32 { + let mut ltot: f32 = 0.0; + for t in tasks { + ltot += cpu_load(t); + } + return ltot; +} + + +/* + * Calculates the cpu load of a task(L(t) where t is a task). + * L(t) + * + * Note: Each task t has a WCET C(t) and given (assumed) inter-arrival time A(t). The CPU request (or load) inferred by a task is L(t) = C(t)/A(t). Ask yourself, what is the consequence of C(t) > A(t)? + * Answer: If C(t) > A(t) then the cpu load of task t is more then the available cpu power in the + * worst case. And the task t will not be able to finish in time in the worst case. + */ +pub fn cpu_load(task: &Task) -> f32 { + return (wcet(&task.trace) as f32) / (task.inter_arrival as f32) +} + + +/* + * Worst case execution time(WCET) of a task t(C(t)). + * C(t) + */ +pub fn wcet(trace: &Trace) -> u32 { + return trace.end.wrapping_sub(trace.start); +} + + +/* + * Calculates the response time of task(R(t)). + * R(t) + * + * Note: * R(t) = B(t) + C(t) + I(t), where + * - B(t) is the blocking time for task t, and + * - I(t) is the interference (preemptions) to task t + */ +pub fn response_time(task: &Task, tasks: &Tasks, ip: &IdPrio, tr: &TaskResources, approx: bool) -> u32 { + let r: u32 = block_time(task, tasks, ip, tr) + wcet(&task.trace) + interference_time(task, tasks, ip, tr, approx).unwrap(); + //println!("response_time {:?}", r); + return r; +} + + +/* + * Calculates the blocking time for task t(B(t)). + * B(t) + * + * Note: B(t) = max(C(l_r)), where P(l) < P(t), π(l_r) >= P(t) + */ +pub fn block_time(task: &Task, tasks: &Tasks, ip: &IdPrio, tr: &TaskResources) -> u32 { + /* + * Helper function for finding the trace of a resource using only the id an a trace. + */ + fn find_res_tr<'a>(res_id: &String, trace: &'a Trace) -> Option<&'a Trace> { + if trace.id == *res_id { + return Some(trace); + } else { + for tr in &trace.inner { + match find_res_tr(res_id, tr) { + Some(val) => return Some(val), + None => (), + } + } + } + return None; + } + + + // Find all lower priority tasks + let mut lower_prio: Vec<&Task> = vec!(); + for t in tasks { + if t.prio < task.prio { + lower_prio.push(t); + } + } + + //println!("prio {:?}", task.prio); + //println!("lower_prio {:?}", lower_prio); + + // Find all resources that will block the task(resources with a higher of equal priority) from + // the resources that the lower priority tasks use. + let mut block_res: Vec<&Trace> = vec!(); + for lpt in lower_prio { + match tr.get(&lpt.id) { + Some(resources) =>{ + for r in resources { + if *ip.get(r).unwrap() >= task.prio { + block_res.push(find_res_tr(r, &lpt.trace).unwrap()); + } + } + }, + None => (), + }; + } + + //println!("block_res {:?}", block_res); + + // Calculate the max wcet of the list of blocking resource traces. + let mut block_time: u32 = 0; + for tr in block_res { + let wcet = wcet(tr); + if wcet > block_time { + block_time = wcet; + } + } + + //println!("block time {:?}", block_time); + + return block_time; +} + + + +/* + * Calculates the interference (preemptions) to task t(I(t)). + * I(t) + * + * Note: I(t) = sum(C(h) * ceiling(Bp(t)/A(h))), forall tasks h, P(h) > P(t), where + * Bp(t) is the busy-period + */ +pub fn interference_time(task: &Task, tasks: &Tasks, ip: &IdPrio, tr: &TaskResources, approx: bool) -> Result<u32, String> { + fn calc_interference(task: &Task, tasks: &Tasks, busy_period: u32) -> u32 { + let mut interference: u32 = 0; + for t in tasks { + if t.prio > task.prio { + interference += wcet(&t.trace) * (((busy_period as f32) / (t.inter_arrival as f32)).ceil() as u32); + } + } + return interference; + } + + if approx { + let interference: u32 = calc_interference(task, tasks, task.deadline); + //println!("interference_time {:?}", interference); + return Ok(interference); + } else { + let constant = block_time(task, tasks, ip, tr) + wcet(&task.trace); + let mut busy_period: u32 = constant + calc_interference(task, tasks, constant); + loop { + if busy_period > task.deadline { + return Err("Busy period is longer then deadline".to_string()); + } else { + let new_busy_period: u32 = constant + calc_interference(task, tasks, busy_period); + if busy_period == new_busy_period { + return Ok(new_busy_period - constant); + } else { + busy_period = new_busy_period; + } + } + } + } +} + + +/* + * Analyse tasks. + * + * Note: Finally, make a function that iterates over the task set and returns a vector with containing: +Vec<Task, R(t), C(t), B(t), I(t)>. Just a simple println! of that vector gives the essential information on the analysis. + */ +pub fn analyse(tasks: &Tasks, ip: &IdPrio, tr: &TaskResources, approx: bool) -> Vec<(Task, u32, u32, u32, u32)> { + let mut analysis: Vec<(Task, u32, u32, u32, u32)> = vec!(); + for t in tasks { + let r_t = response_time(t, tasks, ip, tr, approx); + let c_t = wcet(&t.trace); + let b_t = block_time(t, tasks, ip, tr); + let i_t = interference_time(t, tasks, ip, tr, approx).unwrap(); + analysis.push((t.clone(), r_t, c_t, b_t, i_t)); + } + return analysis; +} + + -- GitLab