1*f0c87a89SGnoCiYeH use core::intrinsics::unlikely;
2*f0c87a89SGnoCiYeH
3*f0c87a89SGnoCiYeH use alloc::sync::Arc;
4*f0c87a89SGnoCiYeH
5*f0c87a89SGnoCiYeH use crate::process::ProcessControlBlock;
6*f0c87a89SGnoCiYeH
7*f0c87a89SGnoCiYeH use super::{
8*f0c87a89SGnoCiYeH fair::{CfsRunQueue, FairSchedEntity},
9*f0c87a89SGnoCiYeH CpuRunQueue, LoadWeight, SchedPolicy, SCHED_CAPACITY_SCALE, SCHED_CAPACITY_SHIFT,
10*f0c87a89SGnoCiYeH };
11*f0c87a89SGnoCiYeH
12*f0c87a89SGnoCiYeH const RUNNABLE_AVG_Y_N_INV: [u32; 32] = [
13*f0c87a89SGnoCiYeH 0xffffffff, 0xfa83b2da, 0xf5257d14, 0xefe4b99a, 0xeac0c6e6, 0xe5b906e6, 0xe0ccdeeb, 0xdbfbb796,
14*f0c87a89SGnoCiYeH 0xd744fcc9, 0xd2a81d91, 0xce248c14, 0xc9b9bd85, 0xc5672a10, 0xc12c4cc9, 0xbd08a39e, 0xb8fbaf46,
15*f0c87a89SGnoCiYeH 0xb504f333, 0xb123f581, 0xad583ee9, 0xa9a15ab4, 0xa5fed6a9, 0xa2704302, 0x9ef5325f, 0x9b8d39b9,
16*f0c87a89SGnoCiYeH 0x9837f050, 0x94f4efa8, 0x91c3d373, 0x8ea4398a, 0x8b95c1e3, 0x88980e80, 0x85aac367, 0x82cd8698,
17*f0c87a89SGnoCiYeH ];
18*f0c87a89SGnoCiYeH
19*f0c87a89SGnoCiYeH pub const LOAD_AVG_PERIOD: u64 = 32;
20*f0c87a89SGnoCiYeH pub const LOAD_AVG_MAX: usize = 47742;
21*f0c87a89SGnoCiYeH pub const PELT_MIN_DIVIDER: usize = LOAD_AVG_MAX - 1024;
22*f0c87a89SGnoCiYeH
23*f0c87a89SGnoCiYeH #[derive(Debug, Default)]
24*f0c87a89SGnoCiYeH pub struct SchedulerAvg {
25*f0c87a89SGnoCiYeH /// 存储上次更新这些平均值的时间
26*f0c87a89SGnoCiYeH pub last_update_time: u64,
27*f0c87a89SGnoCiYeH /// 存储所有可运行任务的负载之和
28*f0c87a89SGnoCiYeH pub load_sum: u64,
29*f0c87a89SGnoCiYeH /// 存储所有可运行任务的时间之和
30*f0c87a89SGnoCiYeH pub runnable_sum: u64,
31*f0c87a89SGnoCiYeH /// 存储所有运行任务的时间之和
32*f0c87a89SGnoCiYeH pub util_sum: u64,
33*f0c87a89SGnoCiYeH /// 记录周期性任务的贡献值,用于计算平均CPU利用率
34*f0c87a89SGnoCiYeH pub period_contrib: u32,
35*f0c87a89SGnoCiYeH
36*f0c87a89SGnoCiYeH pub load_avg: usize,
37*f0c87a89SGnoCiYeH pub runnable_avg: usize,
38*f0c87a89SGnoCiYeH pub util_avg: usize,
39*f0c87a89SGnoCiYeH }
40*f0c87a89SGnoCiYeH
41*f0c87a89SGnoCiYeH impl SchedulerAvg {
42*f0c87a89SGnoCiYeH #[inline]
get_pelt_divider(&self) -> usize43*f0c87a89SGnoCiYeH pub fn get_pelt_divider(&self) -> usize {
44*f0c87a89SGnoCiYeH return PELT_MIN_DIVIDER + self.period_contrib as usize;
45*f0c87a89SGnoCiYeH }
46*f0c87a89SGnoCiYeH
update_load_sum( &mut self, now: u64, load: u32, mut runnable: u32, mut running: u32, ) -> bool47*f0c87a89SGnoCiYeH pub fn update_load_sum(
48*f0c87a89SGnoCiYeH &mut self,
49*f0c87a89SGnoCiYeH now: u64,
50*f0c87a89SGnoCiYeH load: u32,
51*f0c87a89SGnoCiYeH mut runnable: u32,
52*f0c87a89SGnoCiYeH mut running: u32,
53*f0c87a89SGnoCiYeH ) -> bool {
54*f0c87a89SGnoCiYeH if now < self.last_update_time {
55*f0c87a89SGnoCiYeH self.last_update_time = now;
56*f0c87a89SGnoCiYeH return false;
57*f0c87a89SGnoCiYeH }
58*f0c87a89SGnoCiYeH
59*f0c87a89SGnoCiYeH let mut delta = now - self.last_update_time;
60*f0c87a89SGnoCiYeH delta >>= 10;
61*f0c87a89SGnoCiYeH
62*f0c87a89SGnoCiYeH if delta == 0 {
63*f0c87a89SGnoCiYeH return false;
64*f0c87a89SGnoCiYeH }
65*f0c87a89SGnoCiYeH
66*f0c87a89SGnoCiYeH self.last_update_time += delta << 10;
67*f0c87a89SGnoCiYeH
68*f0c87a89SGnoCiYeH if load == 0 {
69*f0c87a89SGnoCiYeH runnable = 0;
70*f0c87a89SGnoCiYeH running = 0;
71*f0c87a89SGnoCiYeH }
72*f0c87a89SGnoCiYeH
73*f0c87a89SGnoCiYeH self.accumulate_sum(delta, load, runnable, running) != 0
74*f0c87a89SGnoCiYeH }
75*f0c87a89SGnoCiYeH
accumulate_sum( &mut self, mut delta: u64, load: u32, runnable: u32, running: u32, ) -> u6476*f0c87a89SGnoCiYeH pub fn accumulate_sum(
77*f0c87a89SGnoCiYeH &mut self,
78*f0c87a89SGnoCiYeH mut delta: u64,
79*f0c87a89SGnoCiYeH load: u32,
80*f0c87a89SGnoCiYeH runnable: u32,
81*f0c87a89SGnoCiYeH running: u32,
82*f0c87a89SGnoCiYeH ) -> u64 {
83*f0c87a89SGnoCiYeH let mut contrib = delta as u32;
84*f0c87a89SGnoCiYeH
85*f0c87a89SGnoCiYeH delta += self.period_contrib as u64;
86*f0c87a89SGnoCiYeH
87*f0c87a89SGnoCiYeH let periods = delta / 1024;
88*f0c87a89SGnoCiYeH
89*f0c87a89SGnoCiYeH if periods > 0 {
90*f0c87a89SGnoCiYeH self.load_sum = Self::decay_load(self.load_sum, periods);
91*f0c87a89SGnoCiYeH self.runnable_sum = Self::decay_load(self.runnable_sum, periods);
92*f0c87a89SGnoCiYeH self.util_sum = Self::decay_load(self.util_sum, periods);
93*f0c87a89SGnoCiYeH
94*f0c87a89SGnoCiYeH delta %= 1024;
95*f0c87a89SGnoCiYeH if load > 0 {
96*f0c87a89SGnoCiYeH contrib = Self::accumulate_pelt_segments(
97*f0c87a89SGnoCiYeH periods,
98*f0c87a89SGnoCiYeH 1024 - self.period_contrib,
99*f0c87a89SGnoCiYeH delta as u32,
100*f0c87a89SGnoCiYeH );
101*f0c87a89SGnoCiYeH }
102*f0c87a89SGnoCiYeH }
103*f0c87a89SGnoCiYeH
104*f0c87a89SGnoCiYeH self.period_contrib = delta as u32;
105*f0c87a89SGnoCiYeH
106*f0c87a89SGnoCiYeH if load > 0 {
107*f0c87a89SGnoCiYeH self.load_sum += (contrib * load) as u64;
108*f0c87a89SGnoCiYeH }
109*f0c87a89SGnoCiYeH if runnable > 0 {
110*f0c87a89SGnoCiYeH self.runnable_sum += (runnable & contrib << SCHED_CAPACITY_SHIFT) as u64;
111*f0c87a89SGnoCiYeH }
112*f0c87a89SGnoCiYeH
113*f0c87a89SGnoCiYeH if running > 0 {
114*f0c87a89SGnoCiYeH self.util_sum += (contrib << SCHED_CAPACITY_SHIFT) as u64;
115*f0c87a89SGnoCiYeH }
116*f0c87a89SGnoCiYeH
117*f0c87a89SGnoCiYeH return periods;
118*f0c87a89SGnoCiYeH }
119*f0c87a89SGnoCiYeH
decay_load(mut val: u64, n: u64) -> u64120*f0c87a89SGnoCiYeH fn decay_load(mut val: u64, n: u64) -> u64 {
121*f0c87a89SGnoCiYeH if unlikely(n > LOAD_AVG_PERIOD) {
122*f0c87a89SGnoCiYeH return 0;
123*f0c87a89SGnoCiYeH }
124*f0c87a89SGnoCiYeH
125*f0c87a89SGnoCiYeH let mut local_n = n;
126*f0c87a89SGnoCiYeH
127*f0c87a89SGnoCiYeH if unlikely(local_n >= LOAD_AVG_PERIOD) {
128*f0c87a89SGnoCiYeH val >>= local_n / LOAD_AVG_PERIOD;
129*f0c87a89SGnoCiYeH local_n %= LOAD_AVG_PERIOD;
130*f0c87a89SGnoCiYeH }
131*f0c87a89SGnoCiYeH
132*f0c87a89SGnoCiYeH ((val as i128 * RUNNABLE_AVG_Y_N_INV[local_n as usize] as i128) >> 32) as u64
133*f0c87a89SGnoCiYeH }
134*f0c87a89SGnoCiYeH
accumulate_pelt_segments(periods: u64, d1: u32, d3: u32) -> u32135*f0c87a89SGnoCiYeH fn accumulate_pelt_segments(periods: u64, d1: u32, d3: u32) -> u32 {
136*f0c87a89SGnoCiYeH /* y^0 == 1 */
137*f0c87a89SGnoCiYeH let c3 = d3;
138*f0c87a89SGnoCiYeH
139*f0c87a89SGnoCiYeH /*
140*f0c87a89SGnoCiYeH * c1 = d1 y^p
141*f0c87a89SGnoCiYeH */
142*f0c87a89SGnoCiYeH let c1 = Self::decay_load(d1 as u64, periods) as u32;
143*f0c87a89SGnoCiYeH
144*f0c87a89SGnoCiYeH /*
145*f0c87a89SGnoCiYeH * p-1
146*f0c87a89SGnoCiYeH * c2 = 1024 \Sum y^n
147*f0c87a89SGnoCiYeH * n=1
148*f0c87a89SGnoCiYeH *
149*f0c87a89SGnoCiYeH * inf inf
150*f0c87a89SGnoCiYeH * = 1024 ( \Sum y^n - \Sum y^n - y^0 )
151*f0c87a89SGnoCiYeH * n=0 n=p
152*f0c87a89SGnoCiYeH */
153*f0c87a89SGnoCiYeH let c2 = LOAD_AVG_MAX as u32 - Self::decay_load(LOAD_AVG_MAX as u64, periods) as u32 - 1024;
154*f0c87a89SGnoCiYeH
155*f0c87a89SGnoCiYeH return c1 + c2 + c3;
156*f0c87a89SGnoCiYeH }
157*f0c87a89SGnoCiYeH
update_load_avg(&mut self, load: u64)158*f0c87a89SGnoCiYeH pub fn update_load_avg(&mut self, load: u64) {
159*f0c87a89SGnoCiYeH let divider = self.get_pelt_divider();
160*f0c87a89SGnoCiYeH
161*f0c87a89SGnoCiYeH self.load_avg = (load * self.load_sum) as usize / divider;
162*f0c87a89SGnoCiYeH self.runnable_avg = self.runnable_sum as usize / divider;
163*f0c87a89SGnoCiYeH self.util_avg = self.util_sum as usize / divider;
164*f0c87a89SGnoCiYeH }
165*f0c87a89SGnoCiYeH
166*f0c87a89SGnoCiYeH #[allow(dead_code)]
post_init_entity_util_avg(pcb: &Arc<ProcessControlBlock>)167*f0c87a89SGnoCiYeH pub fn post_init_entity_util_avg(pcb: &Arc<ProcessControlBlock>) {
168*f0c87a89SGnoCiYeH let se = pcb.sched_info().sched_entity();
169*f0c87a89SGnoCiYeH let cfs_rq = se.cfs_rq();
170*f0c87a89SGnoCiYeH let sa = &mut se.force_mut().avg;
171*f0c87a89SGnoCiYeH
172*f0c87a89SGnoCiYeH // TODO: 这里和架构相关
173*f0c87a89SGnoCiYeH let cpu_scale = SCHED_CAPACITY_SCALE;
174*f0c87a89SGnoCiYeH
175*f0c87a89SGnoCiYeH let cap = (cpu_scale as isize - cfs_rq.avg.util_avg as isize) / 2;
176*f0c87a89SGnoCiYeH
177*f0c87a89SGnoCiYeH if pcb.sched_info().policy() != SchedPolicy::CFS {
178*f0c87a89SGnoCiYeH sa.last_update_time = cfs_rq.cfs_rq_clock_pelt();
179*f0c87a89SGnoCiYeH }
180*f0c87a89SGnoCiYeH
181*f0c87a89SGnoCiYeH if cap > 0 {
182*f0c87a89SGnoCiYeH if cfs_rq.avg.util_avg != 0 {
183*f0c87a89SGnoCiYeH sa.util_avg = cfs_rq.avg.util_avg * se.load.weight as usize;
184*f0c87a89SGnoCiYeH sa.util_avg /= cfs_rq.avg.load_avg + 1;
185*f0c87a89SGnoCiYeH
186*f0c87a89SGnoCiYeH if sa.util_avg as isize > cap {
187*f0c87a89SGnoCiYeH sa.util_avg = cap as usize;
188*f0c87a89SGnoCiYeH }
189*f0c87a89SGnoCiYeH } else {
190*f0c87a89SGnoCiYeH sa.util_avg = cap as usize;
191*f0c87a89SGnoCiYeH }
192*f0c87a89SGnoCiYeH }
193*f0c87a89SGnoCiYeH
194*f0c87a89SGnoCiYeH sa.runnable_avg = sa.util_avg;
195*f0c87a89SGnoCiYeH }
196*f0c87a89SGnoCiYeH }
197*f0c87a89SGnoCiYeH
198*f0c87a89SGnoCiYeH impl CpuRunQueue {
rq_clock_pelt(&self) -> u64199*f0c87a89SGnoCiYeH pub fn rq_clock_pelt(&self) -> u64 {
200*f0c87a89SGnoCiYeH self.clock_pelt - self.lost_idle_time
201*f0c87a89SGnoCiYeH }
202*f0c87a89SGnoCiYeH }
203*f0c87a89SGnoCiYeH
204*f0c87a89SGnoCiYeH impl CfsRunQueue {
cfs_rq_clock_pelt(&self) -> u64205*f0c87a89SGnoCiYeH pub fn cfs_rq_clock_pelt(&self) -> u64 {
206*f0c87a89SGnoCiYeH if unlikely(self.throttled_count > 0) {
207*f0c87a89SGnoCiYeH return self.throttled_clock_pelt - self.throttled_clock_pelt_time;
208*f0c87a89SGnoCiYeH }
209*f0c87a89SGnoCiYeH
210*f0c87a89SGnoCiYeH let rq = self.rq();
211*f0c87a89SGnoCiYeH let (rq, _guard) = rq.self_lock();
212*f0c87a89SGnoCiYeH
213*f0c87a89SGnoCiYeH return rq.rq_clock_pelt() - self.throttled_clock_pelt_time;
214*f0c87a89SGnoCiYeH }
215*f0c87a89SGnoCiYeH }
216*f0c87a89SGnoCiYeH
217*f0c87a89SGnoCiYeH impl FairSchedEntity {
update_load_avg(&mut self, cfs_rq: &mut CfsRunQueue, now: u64) -> bool218*f0c87a89SGnoCiYeH pub fn update_load_avg(&mut self, cfs_rq: &mut CfsRunQueue, now: u64) -> bool {
219*f0c87a89SGnoCiYeH if self.avg.update_load_sum(
220*f0c87a89SGnoCiYeH now,
221*f0c87a89SGnoCiYeH self.on_rq as u32,
222*f0c87a89SGnoCiYeH self.runnable() as u32,
223*f0c87a89SGnoCiYeH cfs_rq.is_curr(&self.self_arc()) as u32,
224*f0c87a89SGnoCiYeH ) {
225*f0c87a89SGnoCiYeH self.avg
226*f0c87a89SGnoCiYeH .update_load_avg(LoadWeight::scale_load_down(self.load.weight));
227*f0c87a89SGnoCiYeH
228*f0c87a89SGnoCiYeH return true;
229*f0c87a89SGnoCiYeH }
230*f0c87a89SGnoCiYeH
231*f0c87a89SGnoCiYeH return false;
232*f0c87a89SGnoCiYeH }
233*f0c87a89SGnoCiYeH }
234*f0c87a89SGnoCiYeH
235*f0c87a89SGnoCiYeH bitflags! {
236*f0c87a89SGnoCiYeH pub struct UpdateAvgFlags: u8 {
237*f0c87a89SGnoCiYeH /// 更新任务组(task group)信息
238*f0c87a89SGnoCiYeH const UPDATE_TG = 0x1;
239*f0c87a89SGnoCiYeH
240*f0c87a89SGnoCiYeH /// 跳过年龄和负载的更新
241*f0c87a89SGnoCiYeH const SKIP_AGE_LOAD = 0x2;
242*f0c87a89SGnoCiYeH /// 执行附加操作
243*f0c87a89SGnoCiYeH const DO_ATTACH = 0x4;
244*f0c87a89SGnoCiYeH /// 执行分离操作
245*f0c87a89SGnoCiYeH const DO_DETACH = 0x8;
246*f0c87a89SGnoCiYeH }
247*f0c87a89SGnoCiYeH }
248*f0c87a89SGnoCiYeH
add_positive(x: &mut isize, y: isize)249*f0c87a89SGnoCiYeH pub fn add_positive(x: &mut isize, y: isize) {
250*f0c87a89SGnoCiYeH let res = *x + y;
251*f0c87a89SGnoCiYeH *x = res.max(0);
252*f0c87a89SGnoCiYeH }
253*f0c87a89SGnoCiYeH
sub_positive(x: &mut usize, y: usize)254*f0c87a89SGnoCiYeH pub fn sub_positive(x: &mut usize, y: usize) {
255*f0c87a89SGnoCiYeH if *x > y {
256*f0c87a89SGnoCiYeH *x -= y;
257*f0c87a89SGnoCiYeH } else {
258*f0c87a89SGnoCiYeH *x = 0;
259*f0c87a89SGnoCiYeH }
260*f0c87a89SGnoCiYeH }
261