response_time_analysis/supply/
constrained.rs

1use super::SupplyBound;
2use crate::time::{Duration, Service};
3
4/// A periodic resource with reduced jitter.
5///
6/// This model represents a refined variant of of the
7/// [Periodic][super::Periodic] supply model wherein the availability
8/// of budget within each period is restricted by a constrained
9/// relative deadline.
10///
11/// The client(s) of this supply is/are guaranteed (at least)
12/// `budget` time units of processor service every `period` time
13/// units within `deadline` time units w.r.t. the start of the
14/// period.
15#[derive(Debug, Clone, Copy)]
16pub struct Constrained {
17    pub period: Duration,
18    pub budget: Service,
19    pub deadline: Duration,
20}
21
22impl Constrained {
23    /// Construct a new constrained periodic resource model such that
24    /// `budget <= deadline <= period`.
25    pub fn new(budget: Service, deadline: Duration, period: Duration) -> Self {
26        assert!(Duration::from(budget) <= deadline);
27        assert!(deadline <= period);
28        Constrained {
29            period,
30            budget,
31            deadline,
32        }
33    }
34}
35
36impl SupplyBound for Constrained {
37    fn provided_service(&self, delta: Duration) -> Service {
38        let budget = Duration::from(self.budget);
39        let shift = self.period - budget;
40        if shift > delta {
41            return Service::none();
42        }
43        // implicit floor due to integer division
44        let full_periods = (delta - shift) / self.period;
45        let x = shift + self.period * full_periods + self.deadline - budget;
46        let fractional_period = if x < delta {
47            self.budget.min(Service::from(delta - x))
48        } else {
49            Service::none()
50        };
51
52        self.budget * full_periods + fractional_period
53    }
54
55    fn service_time(&self, demand: Service) -> Duration {
56        if demand.is_none() {
57            return Duration::zero();
58        }
59
60        let budget = Duration::from(self.budget);
61        let demand = Duration::from(demand);
62
63        // implicit floor due to integer division
64        let full_periods = demand / budget;
65        let full_budget = budget * full_periods;
66        let fractional_budget = if full_budget < demand {
67            demand - full_budget + self.period - budget
68        } else {
69            Duration::zero()
70        };
71
72        self.deadline - budget + self.period * full_periods + fractional_budget
73    }
74}