diff --git a/kernel/src/arch/x86_64/driver/apic/apic_timer.rs b/kernel/src/arch/x86_64/driver/apic/apic_timer.rs index 7d00eb9b..31f23579 100644 --- a/kernel/src/arch/x86_64/driver/apic/apic_timer.rs +++ b/kernel/src/arch/x86_64/driver/apic/apic_timer.rs @@ -8,6 +8,7 @@ use crate::mm::percpu::PerCpu; use crate::sched::core::sched_update_jiffies; use crate::smp::core::smp_get_processor_id; use crate::syscall::SystemError; +use crate::time::clocksource::HZ; pub use drop; use x86::cpuid::cpuid; use x86::msr::{wrmsr, IA32_X2APIC_DIV_CONF, IA32_X2APIC_INIT_COUNT}; @@ -110,7 +111,7 @@ pub enum LocalApicTimerMode { impl LocalApicTimer { /// 定时器中断的间隔 - pub const INTERVAL_MS: u64 = 5; + pub const INTERVAL_MS: u64 = 1000 / HZ as u64; pub const DIVISOR: u64 = 3; /// IoApicManager 初值为0或false diff --git a/kernel/src/common/time.h b/kernel/src/common/time.h index 704e3302..3d4cd44f 100644 --- a/kernel/src/common/time.h +++ b/kernel/src/common/time.h @@ -4,11 +4,3 @@ // 操作系统定义时间以ns为单位 #define CLOCKS_PER_SEC 1000000 - - -/** - * @brief 获取当前的CPU时间 - * - * @return uint64_t timer_jiffies - */ -extern uint64_t rs_clock(); \ No newline at end of file diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 13b229ad..9c064b9b 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -61,6 +61,7 @@ pub mod init; pub mod kthread; pub mod pid; pub mod process; +pub mod resource; pub mod syscall; /// 系统中所有进程的pcb diff --git a/kernel/src/process/resource.rs b/kernel/src/process/resource.rs new file mode 100644 index 00000000..7f187fff --- /dev/null +++ b/kernel/src/process/resource.rs @@ -0,0 +1,85 @@ +use crate::{syscall::SystemError, time::TimeSpec}; + +use super::ProcessControlBlock; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +#[repr(C)] +pub struct RUsage { + /// User time used + pub ru_utime: TimeSpec, + /// System time used + pub ru_stime: TimeSpec, + + // 以下是linux的rusage结构体扩展 + /// Maximum resident set size + pub ru_maxrss: usize, + /// Integral shared memory size + pub ru_ixrss: usize, + /// Integral unshared data size + pub ru_idrss: usize, + /// Integral unshared stack size + pub ru_isrss: usize, + /// Page reclaims (soft page faults) + pub ru_minflt: usize, + /// Page faults (hard page faults) + pub ru_majflt: usize, + /// Swaps + pub ru_nswap: usize, + /// Block input operations + pub ru_inblock: usize, + /// Block output operations + pub ru_oublock: usize, + /// IPC messages sent + pub ru_msgsnd: usize, + /// IPC messages received + pub ru_msgrcv: usize, + /// Signals received + pub ru_nsignals: usize, + /// Voluntary context switches + pub ru_nvcsw: usize, + /// Involuntary context switches + pub ru_nivcsw: usize, +} + +/// +/// Definition of struct rusage taken from BSD 4.3 Reno +/// +/// We don't support all of these yet, but we might as well have them.... +/// Otherwise, each time we add new items, programs which depend on this +/// structure will lose. This reduces the chances of that happening. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum RUsageWho { + RUsageSelf = 0, + RUsageChildren = -1, + /// sys_wait4() uses this + RUsageBoth = -2, + /// only the calling thread + RusageThread = 1, +} + +impl TryFrom for RUsageWho { + type Error = SystemError; + + fn try_from(value: i32) -> Result { + match value { + 0 => Ok(RUsageWho::RUsageSelf), + -1 => Ok(RUsageWho::RUsageChildren), + -2 => Ok(RUsageWho::RUsageBoth), + 1 => Ok(RUsageWho::RusageThread), + _ => Err(SystemError::EINVAL), + } + } +} + +impl ProcessControlBlock { + /// 获取进程资源使用情况 + /// + /// ## TODO + /// + /// 当前函数尚未实现,只是返回了一个默认的RUsage结构体 + pub fn get_rusage(&self, _who: RUsageWho) -> Option { + let rusage = RUsage::default(); + + Some(rusage) + } +} diff --git a/kernel/src/process/syscall.rs b/kernel/src/process/syscall.rs index aa820a75..14a629ce 100644 --- a/kernel/src/process/syscall.rs +++ b/kernel/src/process/syscall.rs @@ -9,6 +9,7 @@ use alloc::{ use super::{ abi::WaitOption, fork::{CloneFlags, KernelCloneArgs}, + resource::{RUsage, RUsageWho}, KernelStack, Pid, ProcessManager, ProcessState, }; use crate::{ @@ -320,4 +321,16 @@ impl Syscall { // todo: 增加credit功能之后,需要修改 return Ok(0); } + + pub fn get_rusage(who: i32, rusage: *mut RUsage) -> Result { + let who = RUsageWho::try_from(who)?; + let mut writer = UserBufferWriter::new(rusage, core::mem::size_of::(), true)?; + let pcb = ProcessManager::current_pcb(); + let rusage = pcb.get_rusage(who).ok_or(SystemError::EINVAL)?; + + let ubuf = writer.buffer::(0).unwrap(); + ubuf.copy_from_slice(&[rusage]); + + return Ok(0); + } } diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 65e6be2e..68886f87 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -5,7 +5,7 @@ use core::{ use crate::{ libs::{futex::constant::FutexFlag, rand::GRandFlags}, - process::fork::KernelCloneArgs, + process::{fork::KernelCloneArgs, resource::RUsage}, }; use num_traits::{FromPrimitive, ToPrimitive}; @@ -400,6 +400,7 @@ pub const SYS_CHDIR: usize = 80; pub const SYS_MKDIR: usize = 83; pub const SYS_GETTIMEOFDAY: usize = 96; +pub const SYS_GETRUSAGE: usize = 98; pub const SYS_GETUID: usize = 102; pub const SYS_SYSLOG: usize = 103; @@ -1164,6 +1165,11 @@ impl Syscall { } SYS_GETEUID => Self::geteuid().map(|euid| euid.into()), SYS_GETEGID => Self::getegid().map(|egid| egid.into()), + SYS_GETRUSAGE => { + let who = args[0] as c_int; + let rusage = args[1] as *mut RUsage; + Self::get_rusage(who, rusage) + } _ => panic!("Unsupported syscall ID: {}", syscall_num), }; diff --git a/kernel/src/time/clocksource.rs b/kernel/src/time/clocksource.rs index 917b68c2..ccf01ce7 100644 --- a/kernel/src/time/clocksource.rs +++ b/kernel/src/time/clocksource.rs @@ -40,7 +40,7 @@ pub static mut FINISHED_BOOTING: AtomicBool = AtomicBool::new(false); /// Interval: 0.5sec Threshold: 0.0625s /// 系统节拍率 -pub const HZ: u64 = 1000; +pub const HZ: u64 = 250; /// watchdog检查间隔 pub const WATCHDOG_INTERVAL: u64 = HZ >> 1; /// 最大能接受的误差大小 diff --git a/kernel/src/time/timekeeping.rs b/kernel/src/time/timekeeping.rs index 447c5e09..7dc9ddc2 100644 --- a/kernel/src/time/timekeeping.rs +++ b/kernel/src/time/timekeeping.rs @@ -1,6 +1,5 @@ use alloc::sync::Arc; use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering}; -use x86_64::align_up; use crate::{ arch::CurrentIrqArch, @@ -238,9 +237,6 @@ pub fn timekeeping_init() { /// # 使用当前时钟源增加wall time pub fn update_wall_time() { - let rsp = unsafe { crate::include::bindings::bindings::get_rsp() } as usize; - let _stack_use = align_up(rsp as u64, 32768) - rsp as u64; - // kdebug!("enter update_wall_time, stack_use = {:}",stack_use); compiler_fence(Ordering::SeqCst); let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; @@ -267,7 +263,8 @@ pub fn update_wall_time() { // } // ================ compiler_fence(Ordering::SeqCst); - // 一分钟同步一次 + + // !!! todo: 这里是硬编码了HPET的500us中断,需要修改 __ADDED_USEC.fetch_add(500, Ordering::SeqCst); compiler_fence(Ordering::SeqCst); let mut retry = 10; @@ -279,6 +276,7 @@ pub fn update_wall_time() { __ADDED_SEC.fetch_add(1, Ordering::SeqCst); compiler_fence(Ordering::SeqCst); } + // 一分钟同步一次 loop { if (usec & !((1 << 26) - 1)) != 0 { if __ADDED_USEC @@ -289,7 +287,7 @@ pub fn update_wall_time() { // 同步时间 // 我感觉这里会出问题:多个读者不退出的话,写者就无法写入 // 然后这里会超时,导致在中断返回之后,会不断的进入这个中断,最终爆栈。 - let mut timekeeper = timekeeper().0.write(); + let mut timekeeper = timekeeper().0.write_irqsave(); timekeeper.xtime.tv_nsec = ktime_get_real_ns(); timekeeper.xtime.tv_sec = 0; __ADDED_SEC.store(0, Ordering::SeqCst); diff --git a/kernel/src/time/timer.h b/kernel/src/time/timer.h index e041804d..8eaaac5d 100644 --- a/kernel/src/time/timer.h +++ b/kernel/src/time/timer.h @@ -7,9 +7,5 @@ #define MAX_TIMEOUT (int64_t)((1ul << 63) - 1) extern void rs_timer_init(); -extern int64_t rs_timer_get_first_expire(); -extern uint64_t rs_timer_next_n_ms_jiffies(uint64_t expire_ms); -extern int64_t rs_schedule_timeout(int64_t timeout); -extern uint64_t rs_clock(); extern void rs_jiffies_init(); diff --git a/kernel/src/time/timer.rs b/kernel/src/time/timer.rs index dc1f43d2..ca8cdb1a 100644 --- a/kernel/src/time/timer.rs +++ b/kernel/src/time/timer.rs @@ -16,7 +16,7 @@ use crate::{ softirq::{softirq_vectors, SoftirqNumber, SoftirqVec}, InterruptArch, }, - kdebug, kerror, kinfo, + kerror, kinfo, libs::spinlock::SpinLock, process::{ProcessControlBlock, ProcessManager}, syscall::SystemError, @@ -253,6 +253,7 @@ pub fn next_n_us_timer_jiffies(expire_us: u64) -> u64 { pub fn schedule_timeout(mut timeout: i64) -> Result { // kdebug!("schedule_timeout"); if timeout == MAX_TIMEOUT { + ProcessManager::mark_sleep(true).ok(); sched(); return Ok(MAX_TIMEOUT); } else if timeout < 0 { @@ -287,7 +288,7 @@ pub fn timer_get_first_expire() -> Result { // FIXME // kdebug!("rs_timer_get_first_expire,timer_jif = {:?}", TIMER_JIFFIES); for _ in 0..10 { - match TIMER_LIST.try_lock() { + match TIMER_LIST.try_lock_irqsave() { Ok(timer_list) => { // kdebug!("rs_timer_get_first_expire TIMER_LIST lock successfully"); if timer_list.is_empty() { @@ -305,6 +306,9 @@ pub fn timer_get_first_expire() -> Result { return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); } +/// 更新系统时间片 +/// +/// todo: 这里的实现有问题,貌似把HPET的500us当成了500个jiffies,然后update_wall_time()里面也硬编码了这个500us pub fn update_timer_jiffies(add_jiffies: u64) -> u64 { let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst); compiler_fence(Ordering::SeqCst); @@ -317,50 +321,10 @@ pub fn update_timer_jiffies(add_jiffies: u64) -> u64 { pub fn clock() -> u64 { return TIMER_JIFFIES.load(Ordering::SeqCst); } -// ====== 重构完成后请删掉extern C ====== -#[no_mangle] -pub extern "C" fn rs_clock() -> u64 { - clock() -} // ====== 以下为给C提供的接口 ====== -#[no_mangle] -pub extern "C" fn rs_schedule_timeout(timeout: i64) -> i64 { - match schedule_timeout(timeout) { - Ok(v) => { - return v; - } - Err(e) => { - kdebug!("rs_schedule_timeout run failed"); - return e.to_posix_errno() as i64; - } - } -} #[no_mangle] pub extern "C" fn rs_timer_init() { timer_init(); } - -#[no_mangle] -pub extern "C" fn rs_timer_next_n_ms_jiffies(expire_ms: u64) -> u64 { - return next_n_ms_timer_jiffies(expire_ms); -} - -#[no_mangle] -pub extern "C" fn rs_timer_next_n_us_jiffies(expire_us: u64) -> u64 { - return next_n_us_timer_jiffies(expire_us); -} - -#[no_mangle] -pub extern "C" fn rs_timer_get_first_expire() -> i64 { - match timer_get_first_expire() { - Ok(v) => return v as i64, - Err(_) => return 0, - } -} - -#[no_mangle] -pub extern "C" fn rs_update_timer_jiffies(add_jiffies: u64) -> u64 { - return update_timer_jiffies(add_jiffies); -}