xref: /DragonOS/kernel/src/sched/cputime.rs (revision f0c87a897fe813b7f06bf5a9e93c43ad9519dafd)
1*f0c87a89SGnoCiYeH use core::sync::atomic::{compiler_fence, AtomicUsize, Ordering};
2*f0c87a89SGnoCiYeH 
3*f0c87a89SGnoCiYeH use crate::{
4*f0c87a89SGnoCiYeH     arch::CurrentIrqArch, exception::InterruptArch, process::ProcessControlBlock,
5*f0c87a89SGnoCiYeH     smp::core::smp_get_processor_id, time::jiffies::TICK_NESC,
6*f0c87a89SGnoCiYeH };
7*f0c87a89SGnoCiYeH use alloc::sync::Arc;
8*f0c87a89SGnoCiYeH 
9*f0c87a89SGnoCiYeH use super::{clock::SchedClock, cpu_irq_time};
10*f0c87a89SGnoCiYeH 
irq_time_read(cpu: usize) -> u6411*f0c87a89SGnoCiYeH pub fn irq_time_read(cpu: usize) -> u64 {
12*f0c87a89SGnoCiYeH     compiler_fence(Ordering::SeqCst);
13*f0c87a89SGnoCiYeH     let irqtime = cpu_irq_time(cpu);
14*f0c87a89SGnoCiYeH 
15*f0c87a89SGnoCiYeH     let mut total;
16*f0c87a89SGnoCiYeH 
17*f0c87a89SGnoCiYeH     loop {
18*f0c87a89SGnoCiYeH         let seq = irqtime.sync.load(Ordering::SeqCst);
19*f0c87a89SGnoCiYeH         total = irqtime.total;
20*f0c87a89SGnoCiYeH 
21*f0c87a89SGnoCiYeH         if seq == irqtime.sync.load(Ordering::SeqCst) {
22*f0c87a89SGnoCiYeH             break;
23*f0c87a89SGnoCiYeH         }
24*f0c87a89SGnoCiYeH     }
25*f0c87a89SGnoCiYeH     compiler_fence(Ordering::SeqCst);
26*f0c87a89SGnoCiYeH     total
27*f0c87a89SGnoCiYeH }
28*f0c87a89SGnoCiYeH 
29*f0c87a89SGnoCiYeH #[derive(Debug, Default)]
30*f0c87a89SGnoCiYeH pub struct IrqTime {
31*f0c87a89SGnoCiYeH     pub total: u64,
32*f0c87a89SGnoCiYeH     pub tick_delta: u64,
33*f0c87a89SGnoCiYeH     pub irq_start_time: u64,
34*f0c87a89SGnoCiYeH     pub sync: AtomicUsize,
35*f0c87a89SGnoCiYeH }
36*f0c87a89SGnoCiYeH 
37*f0c87a89SGnoCiYeH impl IrqTime {
account_delta(&mut self, delta: u64)38*f0c87a89SGnoCiYeH     pub fn account_delta(&mut self, delta: u64) {
39*f0c87a89SGnoCiYeH         // 开始更改时增加序列号
40*f0c87a89SGnoCiYeH         self.sync.fetch_add(1, Ordering::SeqCst);
41*f0c87a89SGnoCiYeH         self.total += delta;
42*f0c87a89SGnoCiYeH         self.tick_delta += delta;
43*f0c87a89SGnoCiYeH     }
44*f0c87a89SGnoCiYeH 
irqtime_tick_accounted(&mut self, max: u64) -> u6445*f0c87a89SGnoCiYeH     pub fn irqtime_tick_accounted(&mut self, max: u64) -> u64 {
46*f0c87a89SGnoCiYeH         let delta = self.tick_delta.min(max);
47*f0c87a89SGnoCiYeH         self.tick_delta -= delta;
48*f0c87a89SGnoCiYeH         return delta;
49*f0c87a89SGnoCiYeH     }
50*f0c87a89SGnoCiYeH 
irqtime_start()51*f0c87a89SGnoCiYeH     pub fn irqtime_start() {
52*f0c87a89SGnoCiYeH         let cpu = smp_get_processor_id().data() as usize;
53*f0c87a89SGnoCiYeH         let irq_time = cpu_irq_time(cpu);
54*f0c87a89SGnoCiYeH         compiler_fence(Ordering::SeqCst);
55*f0c87a89SGnoCiYeH         irq_time.irq_start_time = SchedClock::sched_clock_cpu(cpu) as u64;
56*f0c87a89SGnoCiYeH         compiler_fence(Ordering::SeqCst);
57*f0c87a89SGnoCiYeH     }
58*f0c87a89SGnoCiYeH 
irqtime_account_irq(_pcb: Arc<ProcessControlBlock>)59*f0c87a89SGnoCiYeH     pub fn irqtime_account_irq(_pcb: Arc<ProcessControlBlock>) {
60*f0c87a89SGnoCiYeH         compiler_fence(Ordering::SeqCst);
61*f0c87a89SGnoCiYeH         let cpu = smp_get_processor_id().data() as usize;
62*f0c87a89SGnoCiYeH         let irq_time = cpu_irq_time(cpu);
63*f0c87a89SGnoCiYeH         compiler_fence(Ordering::SeqCst);
64*f0c87a89SGnoCiYeH         let delta = SchedClock::sched_clock_cpu(cpu) as u64 - irq_time.irq_start_time;
65*f0c87a89SGnoCiYeH         compiler_fence(Ordering::SeqCst);
66*f0c87a89SGnoCiYeH 
67*f0c87a89SGnoCiYeH         irq_time.account_delta(delta);
68*f0c87a89SGnoCiYeH         compiler_fence(Ordering::SeqCst);
69*f0c87a89SGnoCiYeH     }
70*f0c87a89SGnoCiYeH }
71*f0c87a89SGnoCiYeH 
72*f0c87a89SGnoCiYeH pub struct CpuTimeFunc;
73*f0c87a89SGnoCiYeH impl CpuTimeFunc {
irqtime_account_process_tick( _pcb: &Arc<ProcessControlBlock>, _user_tick: bool, ticks: u64, )74*f0c87a89SGnoCiYeH     pub fn irqtime_account_process_tick(
75*f0c87a89SGnoCiYeH         _pcb: &Arc<ProcessControlBlock>,
76*f0c87a89SGnoCiYeH         _user_tick: bool,
77*f0c87a89SGnoCiYeH         ticks: u64,
78*f0c87a89SGnoCiYeH     ) {
79*f0c87a89SGnoCiYeH         let cputime = TICK_NESC as u64 * ticks;
80*f0c87a89SGnoCiYeH 
81*f0c87a89SGnoCiYeH         let other = Self::account_other_time(u64::MAX);
82*f0c87a89SGnoCiYeH 
83*f0c87a89SGnoCiYeH         if other >= cputime {
84*f0c87a89SGnoCiYeH             return;
85*f0c87a89SGnoCiYeH         }
86*f0c87a89SGnoCiYeH 
87*f0c87a89SGnoCiYeH         // TODO: update process time
88*f0c87a89SGnoCiYeH     }
89*f0c87a89SGnoCiYeH 
account_other_time(max: u64) -> u6490*f0c87a89SGnoCiYeH     pub fn account_other_time(max: u64) -> u64 {
91*f0c87a89SGnoCiYeH         assert!(!CurrentIrqArch::is_irq_enabled());
92*f0c87a89SGnoCiYeH 
93*f0c87a89SGnoCiYeH         let mut accounted = Self::steal_account_process_time(max);
94*f0c87a89SGnoCiYeH 
95*f0c87a89SGnoCiYeH         if accounted < max {
96*f0c87a89SGnoCiYeH             let irqtime = cpu_irq_time(smp_get_processor_id().data() as usize);
97*f0c87a89SGnoCiYeH             accounted += irqtime.irqtime_tick_accounted(max - accounted);
98*f0c87a89SGnoCiYeH         }
99*f0c87a89SGnoCiYeH 
100*f0c87a89SGnoCiYeH         accounted
101*f0c87a89SGnoCiYeH     }
102*f0c87a89SGnoCiYeH 
steal_account_process_time(_max: u64) -> u64103*f0c87a89SGnoCiYeH     pub fn steal_account_process_time(_max: u64) -> u64 {
104*f0c87a89SGnoCiYeH         // 这里未考虑虚拟机时间窃取
105*f0c87a89SGnoCiYeH         0
106*f0c87a89SGnoCiYeH     }
107*f0c87a89SGnoCiYeH }
108