mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-12 18:26:50 +00:00
增加getrusage,并把apic timer的频率调整为系统HZ (#435)
This commit is contained in:
parent
02e249f30b
commit
be8cdf4b8e
@ -8,6 +8,7 @@ use crate::mm::percpu::PerCpu;
|
|||||||
use crate::sched::core::sched_update_jiffies;
|
use crate::sched::core::sched_update_jiffies;
|
||||||
use crate::smp::core::smp_get_processor_id;
|
use crate::smp::core::smp_get_processor_id;
|
||||||
use crate::syscall::SystemError;
|
use crate::syscall::SystemError;
|
||||||
|
use crate::time::clocksource::HZ;
|
||||||
pub use drop;
|
pub use drop;
|
||||||
use x86::cpuid::cpuid;
|
use x86::cpuid::cpuid;
|
||||||
use x86::msr::{wrmsr, IA32_X2APIC_DIV_CONF, IA32_X2APIC_INIT_COUNT};
|
use x86::msr::{wrmsr, IA32_X2APIC_DIV_CONF, IA32_X2APIC_INIT_COUNT};
|
||||||
@ -110,7 +111,7 @@ pub enum LocalApicTimerMode {
|
|||||||
|
|
||||||
impl LocalApicTimer {
|
impl LocalApicTimer {
|
||||||
/// 定时器中断的间隔
|
/// 定时器中断的间隔
|
||||||
pub const INTERVAL_MS: u64 = 5;
|
pub const INTERVAL_MS: u64 = 1000 / HZ as u64;
|
||||||
pub const DIVISOR: u64 = 3;
|
pub const DIVISOR: u64 = 3;
|
||||||
|
|
||||||
/// IoApicManager 初值为0或false
|
/// IoApicManager 初值为0或false
|
||||||
|
@ -4,11 +4,3 @@
|
|||||||
|
|
||||||
// 操作系统定义时间以ns为单位
|
// 操作系统定义时间以ns为单位
|
||||||
#define CLOCKS_PER_SEC 1000000
|
#define CLOCKS_PER_SEC 1000000
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 获取当前的CPU时间
|
|
||||||
*
|
|
||||||
* @return uint64_t timer_jiffies
|
|
||||||
*/
|
|
||||||
extern uint64_t rs_clock();
|
|
@ -61,6 +61,7 @@ pub mod init;
|
|||||||
pub mod kthread;
|
pub mod kthread;
|
||||||
pub mod pid;
|
pub mod pid;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
|
pub mod resource;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
|
|
||||||
/// 系统中所有进程的pcb
|
/// 系统中所有进程的pcb
|
||||||
|
85
kernel/src/process/resource.rs
Normal file
85
kernel/src/process/resource.rs
Normal file
@ -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<i32> for RUsageWho {
|
||||||
|
type Error = SystemError;
|
||||||
|
|
||||||
|
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
||||||
|
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<RUsage> {
|
||||||
|
let rusage = RUsage::default();
|
||||||
|
|
||||||
|
Some(rusage)
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ use alloc::{
|
|||||||
use super::{
|
use super::{
|
||||||
abi::WaitOption,
|
abi::WaitOption,
|
||||||
fork::{CloneFlags, KernelCloneArgs},
|
fork::{CloneFlags, KernelCloneArgs},
|
||||||
|
resource::{RUsage, RUsageWho},
|
||||||
KernelStack, Pid, ProcessManager, ProcessState,
|
KernelStack, Pid, ProcessManager, ProcessState,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -320,4 +321,16 @@ impl Syscall {
|
|||||||
// todo: 增加credit功能之后,需要修改
|
// todo: 增加credit功能之后,需要修改
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_rusage(who: i32, rusage: *mut RUsage) -> Result<usize, SystemError> {
|
||||||
|
let who = RUsageWho::try_from(who)?;
|
||||||
|
let mut writer = UserBufferWriter::new(rusage, core::mem::size_of::<RUsage>(), true)?;
|
||||||
|
let pcb = ProcessManager::current_pcb();
|
||||||
|
let rusage = pcb.get_rusage(who).ok_or(SystemError::EINVAL)?;
|
||||||
|
|
||||||
|
let ubuf = writer.buffer::<RUsage>(0).unwrap();
|
||||||
|
ubuf.copy_from_slice(&[rusage]);
|
||||||
|
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use core::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
libs::{futex::constant::FutexFlag, rand::GRandFlags},
|
libs::{futex::constant::FutexFlag, rand::GRandFlags},
|
||||||
process::fork::KernelCloneArgs,
|
process::{fork::KernelCloneArgs, resource::RUsage},
|
||||||
};
|
};
|
||||||
|
|
||||||
use num_traits::{FromPrimitive, ToPrimitive};
|
use num_traits::{FromPrimitive, ToPrimitive};
|
||||||
@ -400,6 +400,7 @@ pub const SYS_CHDIR: usize = 80;
|
|||||||
pub const SYS_MKDIR: usize = 83;
|
pub const SYS_MKDIR: usize = 83;
|
||||||
|
|
||||||
pub const SYS_GETTIMEOFDAY: usize = 96;
|
pub const SYS_GETTIMEOFDAY: usize = 96;
|
||||||
|
pub const SYS_GETRUSAGE: usize = 98;
|
||||||
|
|
||||||
pub const SYS_GETUID: usize = 102;
|
pub const SYS_GETUID: usize = 102;
|
||||||
pub const SYS_SYSLOG: usize = 103;
|
pub const SYS_SYSLOG: usize = 103;
|
||||||
@ -1164,6 +1165,11 @@ impl Syscall {
|
|||||||
}
|
}
|
||||||
SYS_GETEUID => Self::geteuid().map(|euid| euid.into()),
|
SYS_GETEUID => Self::geteuid().map(|euid| euid.into()),
|
||||||
SYS_GETEGID => Self::getegid().map(|egid| egid.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),
|
_ => panic!("Unsupported syscall ID: {}", syscall_num),
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,7 @@ pub static mut FINISHED_BOOTING: AtomicBool = AtomicBool::new(false);
|
|||||||
|
|
||||||
/// Interval: 0.5sec Threshold: 0.0625s
|
/// Interval: 0.5sec Threshold: 0.0625s
|
||||||
/// 系统节拍率
|
/// 系统节拍率
|
||||||
pub const HZ: u64 = 1000;
|
pub const HZ: u64 = 250;
|
||||||
/// watchdog检查间隔
|
/// watchdog检查间隔
|
||||||
pub const WATCHDOG_INTERVAL: u64 = HZ >> 1;
|
pub const WATCHDOG_INTERVAL: u64 = HZ >> 1;
|
||||||
/// 最大能接受的误差大小
|
/// 最大能接受的误差大小
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering};
|
use core::sync::atomic::{compiler_fence, AtomicBool, AtomicI64, Ordering};
|
||||||
use x86_64::align_up;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::CurrentIrqArch,
|
arch::CurrentIrqArch,
|
||||||
@ -238,9 +237,6 @@ pub fn timekeeping_init() {
|
|||||||
|
|
||||||
/// # 使用当前时钟源增加wall time
|
/// # 使用当前时钟源增加wall time
|
||||||
pub fn update_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);
|
// kdebug!("enter update_wall_time, stack_use = {:}",stack_use);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
|
||||||
@ -267,7 +263,8 @@ pub fn update_wall_time() {
|
|||||||
// }
|
// }
|
||||||
// ================
|
// ================
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
// 一分钟同步一次
|
|
||||||
|
// !!! todo: 这里是硬编码了HPET的500us中断,需要修改
|
||||||
__ADDED_USEC.fetch_add(500, Ordering::SeqCst);
|
__ADDED_USEC.fetch_add(500, Ordering::SeqCst);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
let mut retry = 10;
|
let mut retry = 10;
|
||||||
@ -279,6 +276,7 @@ pub fn update_wall_time() {
|
|||||||
__ADDED_SEC.fetch_add(1, Ordering::SeqCst);
|
__ADDED_SEC.fetch_add(1, Ordering::SeqCst);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
// 一分钟同步一次
|
||||||
loop {
|
loop {
|
||||||
if (usec & !((1 << 26) - 1)) != 0 {
|
if (usec & !((1 << 26) - 1)) != 0 {
|
||||||
if __ADDED_USEC
|
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_nsec = ktime_get_real_ns();
|
||||||
timekeeper.xtime.tv_sec = 0;
|
timekeeper.xtime.tv_sec = 0;
|
||||||
__ADDED_SEC.store(0, Ordering::SeqCst);
|
__ADDED_SEC.store(0, Ordering::SeqCst);
|
||||||
|
@ -7,9 +7,5 @@
|
|||||||
#define MAX_TIMEOUT (int64_t)((1ul << 63) - 1)
|
#define MAX_TIMEOUT (int64_t)((1ul << 63) - 1)
|
||||||
|
|
||||||
extern void rs_timer_init();
|
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();
|
extern void rs_jiffies_init();
|
||||||
|
@ -16,7 +16,7 @@ use crate::{
|
|||||||
softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
|
softirq::{softirq_vectors, SoftirqNumber, SoftirqVec},
|
||||||
InterruptArch,
|
InterruptArch,
|
||||||
},
|
},
|
||||||
kdebug, kerror, kinfo,
|
kerror, kinfo,
|
||||||
libs::spinlock::SpinLock,
|
libs::spinlock::SpinLock,
|
||||||
process::{ProcessControlBlock, ProcessManager},
|
process::{ProcessControlBlock, ProcessManager},
|
||||||
syscall::SystemError,
|
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<i64, SystemError> {
|
pub fn schedule_timeout(mut timeout: i64) -> Result<i64, SystemError> {
|
||||||
// kdebug!("schedule_timeout");
|
// kdebug!("schedule_timeout");
|
||||||
if timeout == MAX_TIMEOUT {
|
if timeout == MAX_TIMEOUT {
|
||||||
|
ProcessManager::mark_sleep(true).ok();
|
||||||
sched();
|
sched();
|
||||||
return Ok(MAX_TIMEOUT);
|
return Ok(MAX_TIMEOUT);
|
||||||
} else if timeout < 0 {
|
} else if timeout < 0 {
|
||||||
@ -287,7 +288,7 @@ pub fn timer_get_first_expire() -> Result<u64, SystemError> {
|
|||||||
// FIXME
|
// FIXME
|
||||||
// kdebug!("rs_timer_get_first_expire,timer_jif = {:?}", TIMER_JIFFIES);
|
// kdebug!("rs_timer_get_first_expire,timer_jif = {:?}", TIMER_JIFFIES);
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
match TIMER_LIST.try_lock() {
|
match TIMER_LIST.try_lock_irqsave() {
|
||||||
Ok(timer_list) => {
|
Ok(timer_list) => {
|
||||||
// kdebug!("rs_timer_get_first_expire TIMER_LIST lock successfully");
|
// kdebug!("rs_timer_get_first_expire TIMER_LIST lock successfully");
|
||||||
if timer_list.is_empty() {
|
if timer_list.is_empty() {
|
||||||
@ -305,6 +306,9 @@ pub fn timer_get_first_expire() -> Result<u64, SystemError> {
|
|||||||
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 更新系统时间片
|
||||||
|
///
|
||||||
|
/// todo: 这里的实现有问题,貌似把HPET的500us当成了500个jiffies,然后update_wall_time()里面也硬编码了这个500us
|
||||||
pub fn update_timer_jiffies(add_jiffies: u64) -> u64 {
|
pub fn update_timer_jiffies(add_jiffies: u64) -> u64 {
|
||||||
let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
|
let prev = TIMER_JIFFIES.fetch_add(add_jiffies, Ordering::SeqCst);
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
@ -317,50 +321,10 @@ pub fn update_timer_jiffies(add_jiffies: u64) -> u64 {
|
|||||||
pub fn clock() -> u64 {
|
pub fn clock() -> u64 {
|
||||||
return TIMER_JIFFIES.load(Ordering::SeqCst);
|
return TIMER_JIFFIES.load(Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
// ====== 重构完成后请删掉extern C ======
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn rs_clock() -> u64 {
|
|
||||||
clock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====== 以下为给C提供的接口 ======
|
// ====== 以下为给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]
|
#[no_mangle]
|
||||||
pub extern "C" fn rs_timer_init() {
|
pub extern "C" fn rs_timer_init() {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user