use crate::demand::RequestBound;
use crate::fixed_point::{self, max_response_time, SearchResult};
use crate::supply::SupplyBound;
use crate::time::{Duration, Offset, Service};
pub fn rta_event_source<SBF, RBF>(
supply: &SBF,
demand: &RBF,
limit: Duration,
) -> fixed_point::SearchResult
where
SBF: SupplyBound + ?Sized,
RBF: RequestBound + ?Sized,
{
let rhs_busy_window = |delta| demand.service_needed(delta);
let rhs = |offset: Offset, _response| demand.service_needed(offset.closed_since_time_zero());
bound_response_time(supply, demand, rhs_busy_window, rhs, limit)
}
pub fn rta_timer<SBF, RBF1, RBF2>(
supply: &SBF,
own_demand: &RBF1,
interfering_demand: &RBF2,
blocking_bound: Service,
limit: Duration,
) -> fixed_point::SearchResult
where
SBF: SupplyBound + ?Sized,
RBF1: RequestBound + ?Sized,
RBF2: RequestBound + ?Sized,
{
let rhs_bw = |delta| {
own_demand.service_needed(delta) + blocking_bound + interfering_demand.service_needed(delta)
};
let rhs = |offset: Offset, response: Duration| {
let prefix = offset.since_time_zero();
let own_wcet = Duration::from(own_demand.least_wcet_in_interval(prefix + response));
let interference_interval = if response > own_wcet {
prefix + response - own_wcet + Duration::epsilon()
} else {
prefix + Duration::epsilon()
};
own_demand.service_needed(prefix + Duration::epsilon())
+ interfering_demand.service_needed(interference_interval)
+ blocking_bound
};
bound_response_time(supply, own_demand, rhs_bw, rhs, limit)
}
pub fn rta_polling_point_callback<SBF, RBF1, RBF2>(
supply: &SBF,
own_demand: &RBF1,
interfering_demand: &RBF2,
limit: Duration,
) -> fixed_point::SearchResult
where
SBF: SupplyBound + ?Sized,
RBF1: RequestBound + ?Sized,
RBF2: RequestBound + ?Sized,
{
let rhs_bw =
|delta| own_demand.service_needed(delta) + interfering_demand.service_needed(delta);
let rhs = |offset: Offset, response: Duration| {
let prefix = offset.since_time_zero();
let own_wcet = Duration::from(own_demand.least_wcet_in_interval(prefix + response));
let interference_interval = if response > own_wcet {
prefix + response - own_wcet + Duration::epsilon()
} else {
prefix + Duration::epsilon()
};
own_demand.service_needed(prefix + Duration::epsilon())
+ interfering_demand.service_needed(interference_interval)
};
bound_response_time(supply, own_demand, rhs_bw, rhs, limit)
}
pub fn rta_processing_chain<SBF, RBF1, RBF2, RBF3, RBF4>(
supply: &SBF,
chain_last_callback: &RBF1,
chain_prefix: &RBF2,
full_chain: &RBF3,
other_chains: &RBF4,
limit: Duration,
) -> fixed_point::SearchResult
where
SBF: SupplyBound + ?Sized,
RBF1: RequestBound + ?Sized,
RBF2: RequestBound + ?Sized,
RBF3: RequestBound + ?Sized,
RBF4: RequestBound + ?Sized,
{
let rhs_bw = |delta| {
debug_assert_eq!(
full_chain.service_needed(delta),
chain_prefix.service_needed(delta) + chain_last_callback.service_needed(delta)
);
full_chain.service_needed(delta) + other_chains.service_needed(delta)
};
let rhs = |offset: Offset, response: Duration| {
let prefix = offset.since_time_zero();
let own_demand = chain_last_callback.service_needed(prefix + Duration::epsilon());
let own_wcet =
Duration::from(chain_last_callback.least_wcet_in_interval(prefix + response));
let interference_interval = if response > own_wcet {
prefix + response - own_wcet + Duration::epsilon()
} else {
prefix + Duration::epsilon()
};
let other_demand = other_chains.service_needed(interference_interval);
let self_interference = chain_prefix.service_needed(interference_interval);
own_demand + self_interference + other_demand
};
bound_response_time(supply, full_chain, rhs_bw, rhs, limit)
}
fn bound_response_time<SBF, RBF, F, G>(
supply: &SBF,
demand: &RBF,
bw_demand_bound: F,
offset_demand_bound: G,
limit: Duration,
) -> SearchResult
where
SBF: SupplyBound + ?Sized,
RBF: RequestBound + ?Sized,
F: Fn(Duration) -> Service,
G: Fn(Offset, Duration) -> Service,
{
let max_bw = fixed_point::search(supply, limit, bw_demand_bound)?;
let offsets = demand
.steps_iter()
.map(Offset::closed_from_time_zero)
.take_while(|x| *x <= Offset::from_time_zero(max_bw));
let rta_bounds = offsets.map(|offset| {
let rhs = |delta| offset_demand_bound(offset, delta);
fixed_point::search_with_offset(supply, offset, limit, &rhs)
});
max_response_time(rta_bounds)
}