moana_std 0.1.4

moana 用户标准库
Documentation
//! sched 系列 syscall 用户态接口

use core::mem::MaybeUninit;

use moa_cpumask::CpuId;
use moa_uapi::{
    channel::ChanHandle,
    error::{ERR_BUSY, ERR_FAULT, ERR_INVAL, ERR_NOT_FOUND, ERR_PERM},
    sched::{SchedFlags, SchedHandle, SchedLoad, SchedStateInfo},
    space::SpaceId,
    sysnr::{
        SYSNR_SCHED_GET_STATE, SYSNR_SCHED_GET_TASK_LOAD, SYSNR_SCHED_REGISTER, SYSNR_SCHED_RESUME,
        SYSNR_SCHED_SET_CPU, SYSNR_SCHED_SET_MODE, SYSNR_SCHED_SUSPEND, SYSNR_SCHED_UNREGISTER,
    },
};

/// sched 系列 syscall 返回类型
pub type Result<T> = core::result::Result<T, SchedError>;

define_syscall_error! {
    /// sched 系列 syscall 错误
    pub enum SchedError {
        /// 权限不足
        Perm = ERR_PERM,
        /// 句柄不存在
        NotFound = ERR_NOT_FOUND,
        /// 无效参数
        Inval = ERR_INVAL,
        /// 无效指针(`copy_to_user` 失败)
        Fault = ERR_FAULT,
        /// 已注册(重复 register)
        Busy = ERR_BUSY,
    }
}

/// 注册调度管理器(仅进程 0)
pub fn sched_register(spaceid: SpaceId, chan: ChanHandle, flags: SchedFlags) -> Result<()> {
    let ret = unsafe {
        super::arch::syscall3(
            SYSNR_SCHED_REGISTER,
            spaceid.raw(),
            chan.raw() as usize,
            flags.bits() as usize,
        )
    };
    if ret < 0 { Err(SchedError::from_raw(ret)) } else { Ok(()) }
}

/// 撤销调度管理器注册(仅进程 0)
pub fn sched_unregister() -> Result<()> {
    let ret = unsafe { super::arch::syscall0(SYSNR_SCHED_UNREGISTER) };
    if ret < 0 { Err(SchedError::from_raw(ret)) } else { Ok(()) }
}

/// 动态切换调度管理模式
pub fn sched_set_mode(flags: SchedFlags) -> Result<()> {
    let ret = unsafe { super::arch::syscall1(SYSNR_SCHED_SET_MODE, flags.bits() as usize) };
    if ret < 0 { Err(SchedError::from_raw(ret)) } else { Ok(()) }
}

/// 恢复任务调度
pub fn sched_resume(sched: SchedHandle) -> Result<()> {
    let ret = unsafe { super::arch::syscall1(SYSNR_SCHED_RESUME, sched.raw() as usize) };
    if ret < 0 { Err(SchedError::from_raw(ret)) } else { Ok(()) }
}

/// 暂停任务调度
pub fn sched_suspend(sched: SchedHandle) -> Result<()> {
    let ret = unsafe { super::arch::syscall1(SYSNR_SCHED_SUSPEND, sched.raw() as usize) };
    if ret < 0 { Err(SchedError::from_raw(ret)) } else { Ok(()) }
}

/// 绑定任务到指定 CPU
pub fn sched_set_cpu(sched: SchedHandle, cpuid: CpuId) -> Result<()> {
    let ret =
        unsafe { super::arch::syscall2(SYSNR_SCHED_SET_CPU, sched.raw() as usize, cpuid.raw()) };
    if ret < 0 { Err(SchedError::from_raw(ret)) } else { Ok(()) }
}

/// 查询任务运行时状态
pub fn sched_get_state(sched: SchedHandle) -> Result<SchedStateInfo> {
    let mut info = MaybeUninit::<SchedStateInfo>::uninit();
    let ret = unsafe {
        super::arch::syscall2(
            SYSNR_SCHED_GET_STATE,
            sched.raw() as usize,
            info.as_mut_ptr() as usize,
        )
    };
    if ret < 0 { Err(SchedError::from_raw(ret)) } else { Ok(unsafe { info.assume_init() }) }
}

/// 获取任务 PELT 负载
pub fn sched_get_task_load(sched: SchedHandle) -> Result<SchedLoad> {
    let mut load = MaybeUninit::<SchedLoad>::uninit();
    let ret = unsafe {
        super::arch::syscall2(
            SYSNR_SCHED_GET_TASK_LOAD,
            sched.raw() as usize,
            load.as_mut_ptr() as usize,
        )
    };
    if ret < 0 { Err(SchedError::from_raw(ret)) } else { Ok(unsafe { load.assume_init() }) }
}