Skip to content
Snippets Groups Projects
Commit b5792f5c authored by Blinningjr's avatar Blinningjr
Browse files

Moved all the added analysis function to a separate file

parent e2876ba7
No related branches found
No related tags found
No related merge requests found
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;
}
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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment