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