xref: /DragonOS/kernel/src/sched/pelt.rs (revision f0c87a897fe813b7f06bf5a9e93c43ad9519dafd)
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