170 lines
5.0 KiB
Rust
170 lines
5.0 KiB
Rust
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
use alloc::{
|
|
string::ToString,
|
|
sync::{Arc, Weak},
|
|
};
|
|
use core::fmt::Debug;
|
|
|
|
use aster_systree::{
|
|
inherit_sys_branch_node, BranchNodeFields, Error, Result, SysAttrSetBuilder, SysBranchNode,
|
|
SysObj, SysPerms, SysStr,
|
|
};
|
|
use inherit_methods_macro::inherit_methods;
|
|
use ostd::mm::{VmReader, VmWriter};
|
|
use spin::Once;
|
|
|
|
/// The root of a cgroup hierarchy, serving as the entry point to
|
|
/// the entire cgroup control system.
|
|
///
|
|
/// The cgroup system provides v2 unified hierarchy, and is also used as a root
|
|
/// node in the cgroup systree.
|
|
#[derive(Debug)]
|
|
pub(super) struct CgroupSystem {
|
|
fields: BranchNodeFields<CgroupNode, Self>,
|
|
}
|
|
|
|
/// A control group node in the cgroup systree.
|
|
///
|
|
/// Each node can bind a group of processes together for purpose of resource
|
|
/// management. Except for the root node, all nodes in the cgroup tree are of
|
|
/// this type.
|
|
#[derive(Debug)]
|
|
struct CgroupNode {
|
|
fields: BranchNodeFields<CgroupNode, Self>,
|
|
}
|
|
|
|
#[inherit_methods(from = "self.fields")]
|
|
impl CgroupSystem {
|
|
/// Adds a child node.
|
|
fn add_child(&self, new_child: Arc<CgroupNode>) -> Result<()>;
|
|
}
|
|
|
|
#[inherit_methods(from = "self.fields")]
|
|
impl CgroupNode {
|
|
/// Adds a child node.
|
|
fn add_child(&self, new_child: Arc<CgroupNode>) -> Result<()>;
|
|
}
|
|
|
|
impl CgroupSystem {
|
|
/// Returns the `CgroupSystem` singleton.
|
|
pub(super) fn singleton() -> &'static Arc<CgroupSystem> {
|
|
static SINGLETON: Once<Arc<CgroupSystem>> = Once::new();
|
|
|
|
SINGLETON.call_once(Self::new)
|
|
}
|
|
|
|
fn new() -> Arc<Self> {
|
|
let name = SysStr::from("cgroup");
|
|
|
|
let mut builder = SysAttrSetBuilder::new();
|
|
// TODO: Add more attributes as needed.
|
|
builder.add(
|
|
SysStr::from("cgroup.controllers"),
|
|
SysPerms::DEFAULT_RO_ATTR_PERMS,
|
|
);
|
|
builder.add(
|
|
SysStr::from("cgroup.max.depth"),
|
|
SysPerms::DEFAULT_RW_ATTR_PERMS,
|
|
);
|
|
builder.add(
|
|
SysStr::from("cgroup.threads"),
|
|
SysPerms::DEFAULT_RW_ATTR_PERMS,
|
|
);
|
|
builder.add(
|
|
SysStr::from("cpu.pressure"),
|
|
SysPerms::DEFAULT_RW_ATTR_PERMS,
|
|
);
|
|
builder.add(SysStr::from("cpu.stat"), SysPerms::DEFAULT_RO_ATTR_PERMS);
|
|
|
|
let attrs = builder.build().expect("Failed to build attribute set");
|
|
Arc::new_cyclic(|weak_self| {
|
|
let fields = BranchNodeFields::new(name, attrs, weak_self.clone());
|
|
CgroupSystem { fields }
|
|
})
|
|
}
|
|
}
|
|
|
|
impl CgroupNode {
|
|
pub(self) fn new(name: SysStr) -> Arc<Self> {
|
|
let mut builder = SysAttrSetBuilder::new();
|
|
// TODO: Add more attributes as needed. The normal cgroup node may have
|
|
// more attributes than the unified one.
|
|
builder.add(
|
|
SysStr::from("cgroup.controllers"),
|
|
SysPerms::DEFAULT_RO_ATTR_PERMS,
|
|
);
|
|
builder.add(
|
|
SysStr::from("cgroup.max.depth"),
|
|
SysPerms::DEFAULT_RW_ATTR_PERMS,
|
|
);
|
|
builder.add(
|
|
SysStr::from("cgroup.threads"),
|
|
SysPerms::DEFAULT_RW_ATTR_PERMS,
|
|
);
|
|
builder.add(
|
|
SysStr::from("cpu.pressure"),
|
|
SysPerms::DEFAULT_RW_ATTR_PERMS,
|
|
);
|
|
builder.add(SysStr::from("cpu.stat"), SysPerms::DEFAULT_RO_ATTR_PERMS);
|
|
|
|
let attrs = builder.build().expect("Failed to build attribute set");
|
|
Arc::new_cyclic(|weak_self| {
|
|
let fields = BranchNodeFields::new(name, attrs, weak_self.clone());
|
|
CgroupNode { fields }
|
|
})
|
|
}
|
|
}
|
|
|
|
inherit_sys_branch_node!(CgroupSystem, fields, {
|
|
fn is_root(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn init_parent(&self, _parent: Weak<dyn SysBranchNode>) {
|
|
// This method should be a no-op for `RootNode`.
|
|
}
|
|
|
|
fn read_attr(&self, _name: &str, _writer: &mut VmWriter) -> Result<usize> {
|
|
// TODO: Add support for reading attributes.
|
|
Err(Error::AttributeError)
|
|
}
|
|
|
|
fn write_attr(&self, _name: &str, _reader: &mut VmReader) -> Result<usize> {
|
|
// TODO: Add support for writing attributes.
|
|
Err(Error::AttributeError)
|
|
}
|
|
|
|
fn perms(&self) -> SysPerms {
|
|
SysPerms::DEFAULT_RW_PERMS
|
|
}
|
|
|
|
fn create_child(&self, name: &str) -> Result<Arc<dyn SysObj>> {
|
|
let new_child = CgroupNode::new(name.to_string().into());
|
|
self.add_child(new_child.clone())?;
|
|
Ok(new_child)
|
|
}
|
|
});
|
|
|
|
inherit_sys_branch_node!(CgroupNode, fields, {
|
|
fn read_attr(&self, _name: &str, _writer: &mut VmWriter) -> Result<usize> {
|
|
// TODO: Add support for reading attributes.
|
|
Err(Error::AttributeError)
|
|
}
|
|
|
|
fn write_attr(&self, _name: &str, _reader: &mut VmReader) -> Result<usize> {
|
|
// TODO: Add support for writing attributes.
|
|
Err(Error::AttributeError)
|
|
}
|
|
|
|
fn perms(&self) -> SysPerms {
|
|
SysPerms::DEFAULT_RW_PERMS
|
|
}
|
|
|
|
fn create_child(&self, name: &str) -> Result<Arc<dyn SysObj>> {
|
|
let new_child = CgroupNode::new(name.to_string().into());
|
|
self.add_child(new_child.clone())?;
|
|
Ok(new_child)
|
|
}
|
|
});
|