starry-kernel 0.7.7

A Linux-compatible OS kernel built on ArceOS unikernel
Documentation
//! Kernel integration for the reusable cgroup domain model.

use alloc::{string::String, sync::Arc};
use core::fmt::Write;

use ax_cgroup::{CgroupError, CgroupNode};
pub use ax_cgroup::{attach_initial_process, begin_fork, exit_process, relative_path, root};
use ax_errno::{AxError, LinuxError};

const INTERFACE_FILES: [&str; 3] = [
    "cgroup.procs",
    "cgroup.controllers",
    "cgroup.subtree_control",
];

struct KernelCgroupProvider;

impl ax_cgroup::CgroupProvider for KernelCgroupProvider {
    fn is_zombie(&self, pid: u32) -> bool {
        crate::task::is_zombie_pid(pid as _)
    }

    fn membership(&self, pid: u32) -> Option<Arc<CgroupNode>> {
        crate::task::get_process_data(pid as _)
            .ok()
            .map(|process| process.cgroup.read().clone())
    }

    fn set_membership(&self, pid: u32, cgroup: Arc<CgroupNode>) {
        if let Ok(process) = crate::task::get_process_data(pid as _) {
            *process.cgroup.write() = cgroup;
        }
    }
}

/// Initialize the cgroup hierarchy and kernel process provider.
pub fn init() {
    ax_cgroup::init();
    ax_cgroup::register_provider(&KernelCgroupProvider);
}

pub fn is_interface_file_name(name: &str) -> bool {
    INTERFACE_FILES.contains(&name)
}

pub fn controllers_text(_node: &CgroupNode) -> &'static str {
    ""
}

pub fn procs_text(node: &CgroupNode) -> String {
    let mut text = String::new();
    for pid in node.members() {
        let _ = writeln!(text, "{pid}");
    }
    text
}

pub fn subtree_control_text(_node: &CgroupNode) -> &'static str {
    ""
}

pub fn write_procs(node: Arc<CgroupNode>, data: &[u8]) -> Result<(), AxError> {
    let pid = core::str::from_utf8(data)
        .map_err(|_| AxError::InvalidInput)?
        .trim()
        .parse::<u32>()
        .map_err(|_| AxError::InvalidInput)?;
    ax_cgroup::migrate_process(pid, node).map_err(cgroup_error)
}

pub fn write_subtree_control(_node: &CgroupNode, _data: &[u8]) -> Result<(), AxError> {
    Err(LinuxError::EINVAL.into())
}

pub fn cgroup_error(error: CgroupError) -> AxError {
    let error: AxError = match error {
        CgroupError::NotInitialized | CgroupError::InvalidInput => LinuxError::EINVAL.into(),
        CgroupError::NotFound => LinuxError::ENOENT.into(),
        CgroupError::AlreadyExists => LinuxError::EEXIST.into(),
        CgroupError::ResourceBusy => LinuxError::EBUSY.into(),
        CgroupError::NoSuchProcess => LinuxError::ESRCH.into(),
        CgroupError::DirectoryNotEmpty => LinuxError::ENOTEMPTY.into(),
    };
    error.canonicalize()
}