Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
418 changes: 149 additions & 269 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ members = [
"bootloader/axloader",

"components/aic8800",
"components/ax-cgroup",
Comment thread
SongShiQ marked this conversation as resolved.
"components/ax-lazyinit",
"components/axbacktrace",
"components/axcpu",
Expand Down Expand Up @@ -130,6 +131,7 @@ ax-alloc = { version = "0.8.4", path = "os/arceos/modules/axalloc", default-feat
ax-allocator = { version = "0.5.3", path = "memory/axallocator" }
ax-api = { version = "0.6.1", path = "os/arceos/api/arceos_api" }
ax-arm-pl031 = { version = "0.4.7", path = "drivers/rtc/arm_pl031" }
ax-cgroup = { version = "0.1.0", path = "components/ax-cgroup" }
ax-config = { version = "0.5.14", path = "os/arceos/modules/axconfig" }
ax-config-gen = { version = "0.4.11", path = "components/axconfig-gen/axconfig-gen" }
ax-config-macros = { version = "0.4.11", path = "components/axconfig-gen/axconfig-macros" }
Expand Down
16 changes: 16 additions & 0 deletions components/ax-cgroup/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "ax-cgroup"
version = "0.1.0"
repository = "https://github.com/rcore-os/tgoskits"
edition.workspace = true
authors = ["SongShiQ"]
description = "cgroup v2 subsystem for StarryOS"
keywords = ["arceos", "cgroup", "starry"]
categories = ["no-std", "os"]
license = "Apache-2.0"
readme = "README.md"

[dependencies]
ax-kspin = { workspace = true }
ax-lazyinit = { workspace = true }
log = "0.4"
132 changes: 132 additions & 0 deletions components/ax-cgroup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<h1 align="center">ax-cgroup</h1>

<p align="center">cgroup v2 subsystem for StarryOS</p>

<div align="center">

[![Crates.io](https://img.shields.io/crates/v/ax-cgroup.svg)](https://crates.io/crates/ax-cgroup)
[![Docs.rs](https://docs.rs/ax-cgroup/badge.svg)](https://docs.rs/ax-cgroup)
[![Rust](https://img.shields.io/badge/edition-2021-orange.svg)](https://www.rust-lang.org/)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](./LICENSE)

</div>

English | [中文](README_CN.md)

# Introduction

`ax-cgroup` provides a kernel-independent cgroup v2 subsystem for StarryOS. It
owns the cgroup hierarchy, per-controller state, and process membership
bookkeeping. The crate is `no_std` and does not depend on the kernel task
layer directly: the kernel supplies the task/process primitives by
implementing the [`CgroupProvider`] trait and registering it during boot.

This crate is maintained as part of the TGOSKits component set and is intended
for Rust projects that integrate with ArceOS, StarryOS, or related low-level
systems software.

## Design

The implementation follows the Linux cgroup v2 semantics and borrows several
ideas from the [Asterinas](https://github.com/asterinas/asterinas) cgroupfs
(domain-controller rules, global membership serialization, `subtree_control`
propagation). It is **not** a port of Asterinas' `SysTree`-based architecture:
StarryOS has no `aster_systree` component and uses `axfs-ng-vfs`, so the
hierarchy here is a self-contained tree rather than a `SysBranchNode` graph.

Concrete differences from Asterinas:

| Aspect | Asterinas | ax-cgroup |
| ----------------- | --------------------------------------- | ---------------------------------------------- |
| Hierarchy | `SysTree` (`SysBranchNode` / `SysObj`) | self-managed `BTreeMap<String, Arc<CgroupNode>>` |
| Controller access | `Controller` + `SubControl` trait | fixed `pids` / `cpu` fields on the node |
| Attribute I/O | trait-method dispatch | `match name { ... }` in `read_attr_at`/`write_attr` |
| Membership lock | `CgroupMembership` global `Mutex` | `SpinNoIrq<MembershipState>` (`LazyInit`) |
| Filesystem | custom cgroupfs over `SysTree` | `axfs-ng-vfs` adapter in the kernel |

### Module layout

| Module | Responsibility |
| ------------- | -------------------------------------------------------------------- |
| `core` | `CgroupNode`, the global root, and the id-to-node registry. |
| `pids` | `PidsState` — process-count accounting with a CAS-based charge path. |
| `cpu` | `CpuState` / `BandwidthState` — `cpu.weight` and `cpu.max` state. |
| `provider` | `CgroupProvider` trait and the registration cell. |
| crate root | membership, fork/migrate/exit transactions, and attribute parsing. |

### Controllers

Two controllers are implemented:

- **pids** — `pids.max` / `pids.current`. Charging walks the path to the root
and rolls back partial charges on failure; the per-node counter uses a CAS
loop to avoid the TOCTOU race on SMP.
- **cpu** — `cpu.weight`, `cpu.max` (quota/period), and `cpu.stat`. The
bandwidth quota/period state is maintained here; the timer-tick enforcement
hook lives on the kernel side because it needs `ax_task` / `ax_hal` access.

## Quick Start

### Installation

Add this crate to your `Cargo.toml`:

```toml
[dependencies]
ax-cgroup = "0.1.0"
```

### Usage

```rust,ignore
use alloc::sync::Arc;
use ax_cgroup::{CgroupNode, CgroupProvider};

struct KernelProvider;

impl CgroupProvider for KernelProvider {
fn is_zombie(&self, pid: u32) -> bool {
// query the kernel process table
}
fn get_cgroup(&self, pid: u32) -> Option<Arc<CgroupNode>> {
// return the process's current cgroup
}
fn set_cgroup(&self, pid: u32, cgroup: Arc<CgroupNode>) {
// store the process's new cgroup
}
}

static PROVIDER: KernelProvider = KernelProvider;

fn boot() {
ax_cgroup::init();
ax_cgroup::register_provider(&PROVIDER);
}
```

### Run Check and Test

```bash
# Enter the crate directory
cd components/ax-cgroup

# Format code
cargo fmt --all

# Run clippy
cargo clippy --all-targets --all-features

# Build documentation
cargo doc --no-deps
```

# Contributing

1. Fork the repository and create a branch
2. Run local format and checks
3. Run local tests relevant to this crate
4. Submit a PR and ensure CI passes

# License

Licensed under the Apache License, Version 2.0. See [LICENSE](../../LICENSE) for details.
131 changes: 131 additions & 0 deletions components/ax-cgroup/README_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<h1 align="center">ax-cgroup</h1>

<p align="center">StarryOS 的 cgroup v2 子系统</p>

<div align="center">

[![Crates.io](https://img.shields.io/crates/v/ax-cgroup.svg)](https://crates.io/crates/ax-cgroup)
[![Docs.rs](https://docs.rs/ax-cgroup/badge.svg)](https://docs.rs/ax-cgroup)
[![Rust](https://img.shields.io/badge/edition-2021-orange.svg)](https://www.rust-lang.org/)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](./LICENSE)

</div>

[English](README.md) | 中文

# 介绍

`ax-cgroup` 为 StarryOS 提供一个与内核解耦的 cgroup v2 子系统。它负责维护
cgroup 层次结构、各控制器状态以及进程成员关系。该 crate 是 `no_std` 的,
不直接依赖内核任务层:内核通过实现 [`CgroupProvider`] trait 并在启动时注册,
来提供任务/进程相关的原语。

本 crate 是 TGOSKits 组件集合的一部分,可用于集成 ArceOS、StarryOS 及相关
底层系统软件的 Rust 项目。

## 设计

实现遵循 Linux cgroup v2 语义,并借鉴了
[Asterinas](https://github.com/asterinas/asterinas) cgroupfs 的若干思路
(domain 控制器规则、全局成员关系串行化、`subtree_control` 传播)。但它
**不是** Asterinas 基于 `SysTree` 架构的移植:StarryOS 没有 `aster_systree`
组件,使用的是 `axfs-ng-vfs`,因此这里的层次结构是一棵自管理的树,而非
`SysBranchNode` 图。

与 Asterinas 的具体差异:

| 方面 | Asterinas | ax-cgroup |
| ---------- | -------------------------------------- | ------------------------------------------------ |
| 层次框架 | `SysTree`(`SysBranchNode` / `SysObj`) | 自管理的 `BTreeMap<String, Arc<CgroupNode>>` |
| 控制器访问 | `Controller` + `SubControl` trait | 节点上固定的 `pids` / `cpu` 字段 |
| 属性读写 | trait 方法分发 | `read_attr_at`/`write_attr` 中的 `match name` |
| 成员关系锁 | `CgroupMembership` 全局 `Mutex` | `SpinNoIrq<MembershipState>`(`LazyInit`) |
| 文件系统 | 基于 `SysTree` 的自定义 cgroupfs | 内核侧的 `axfs-ng-vfs` 适配 |

### 模块划分

| 模块 | 职责 |
| ---------- | ------------------------------------------------------------ |
| `core` | `CgroupNode`、全局根节点,以及 id 到节点的注册表。 |
| `pids` | `PidsState` —— 基于 CAS 充值路径的进程数计量。 |
| `cpu` | `CpuState` / `BandwidthState` —— `cpu.weight` 与 `cpu.max` 状态。 |
| `provider` | `CgroupProvider` trait 与注册单元。 |
| crate 根 | 成员关系、fork/migrate/exit 事务,以及属性解析。 |

### 控制器

实现了两个控制器:

- **pids** —— `pids.max` / `pids.current`。充值会沿路径回溯到根节点,失败时
回滚已充值部分;每个节点的计数器使用 CAS 循环,以避免 SMP 上的 TOCTOU 竞态。
- **cpu** —— `cpu.weight`、`cpu.max`(quota/period)与 `cpu.stat`。带宽
quota/period 状态在此维护;定时器 tick 的限流执行钩子位于内核侧,因为它
需要访问 `ax_task` / `ax_hal`。

## 快速开始

### 添加依赖

在 `Cargo.toml` 中加入:

```toml
[dependencies]
ax-cgroup = "0.1.0"
```

### 使用方式

```rust,ignore
use alloc::sync::Arc;
use ax_cgroup::{CgroupNode, CgroupProvider};

struct KernelProvider;

impl CgroupProvider for KernelProvider {
fn is_zombie(&self, pid: u32) -> bool {
// 查询内核进程表
# false
}
fn get_cgroup(&self, pid: u32) -> Option<Arc<CgroupNode>> {
// 返回该进程当前所属的 cgroup
# None
}
fn set_cgroup(&self, pid: u32, cgroup: Arc<CgroupNode>) {
// 保存该进程新的 cgroup
}
}

static PROVIDER: KernelProvider = KernelProvider;

fn boot() {
ax_cgroup::init();
ax_cgroup::register_provider(&PROVIDER);
}
```

### 检查与测试

```bash
# 进入 crate 目录
cd components/ax-cgroup

# 代码格式化
cargo fmt --all

# 运行 clippy
cargo clippy --all-targets --all-features

# 生成文档
cargo doc --no-deps
```

# 贡献

1. Fork 仓库并创建分支
2. 在本地运行格式化与检查
3. 运行与该 crate 相关的测试
4. 提交 PR 并确保 CI 通过

# 许可证

本项目采用 Apache License 2.0 许可证。详情见 [LICENSE](../../LICENSE)。
Loading
Loading