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