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