1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
from __future__ import division
from .quanta import quantize_wcet, quantize_period, account_for_delayed_release, stagger_latency
def charge_scheduling_overheads(oheads, num_cpus, dedicated_irq, taskset,
staggered=False, total_cpus=None,
aligned_periodic_releases=False):
if not oheads or not taskset:
return taskset
qlen = oheads.quantum_length
ev_lat = oheads.release_latency(taskset)
rel_oh = oheads.release(taskset)
# account for reduced effective quantum length
qeff = qlen \
- ev_lat \
- oheads.tick(taskset) \
- oheads.schedule(taskset) \
- oheads.ctx_switch(taskset) \
- oheads.cache_affinity_loss(taskset)
if not dedicated_irq:
# account for release interrupts
qeff -= (len(taskset) - 1) * rel_oh
# Is any useful time left in the quantum? With short quanta and high
# overheads, this may not be the case (in the analyzed worst case).
if qeff <= 0:
return False
# apply reduction
taskset = quantize_wcet(qlen, taskset, qeff)
if not taskset:
return False
# Account for release delay.
if not aligned_periodic_releases:
# Default sporadic mode: job releases are triggered sporadically,
# but newly released jobs are not considered for scheduling until
# the next quantum boundary.
release_delay = qlen + ev_lat + rel_oh
else:
# "Polling" mode. Periodic job releases are triggered
# at each quantum boundary without any delays.
release_delay = 0
# shortcut: we roll staggering into release delay
if staggered:
if total_cpus is None:
total_cpus = num_cpus;
release_delay += stagger_latency(total_cpus, qlen)
taskset = account_for_delayed_release(release_delay, taskset)
if not taskset:
return False
return quantize_period(qlen, taskset, deadline=True)
|