v0.1: green-thread actors, supervision, channels, benchmark

Hand-rolled context switching on mmap'd stacks with guard pages,
allocator-driven RDTSC preemption, unbounded MPSC channels, supervision
via per-slot Signal mailboxes, root supervisor as sentinel PID.

Lib + tests + benches clean check/clippy. All 29 tests pass.
Bench: smarm 3.4% over serial baseline, within 160us of tokio
current-thread on prime-counting fan-out.
This commit is contained in:
Claude
2026-05-22 05:01:51 +00:00
commit 0e9d9d7d5f
17 changed files with 1938 additions and 0 deletions

89
src/stack.rs Normal file
View File

@@ -0,0 +1,89 @@
//! mmap-based growable stack with a guard page below.
//!
//! Layout (low → high address):
//! [ guard page (PROT_NONE) | stack region ]
//! ^ top() — initial stack pointer
//!
//! Stacks grow downward. Overflow lands in the guard page → SIGSEGV.
use std::io;
pub struct Stack {
/// Bottom of the entire mmap'd region (start of guard page).
base: *mut u8,
/// Total mmap'd size: guard_size + stack_size.
total_size: usize,
/// Usable stack size (excluding guard page).
stack_size: usize,
}
// Stack owns its memory; safe to send across threads.
unsafe impl Send for Stack {}
impl Stack {
/// Allocate a new stack. `stack_size` is the usable region; one page is
/// added below as a guard page. Both are rounded up to the page size.
pub fn new(stack_size: usize) -> io::Result<Self> {
let page = page_size();
let stack_size = round_up(stack_size, page);
let guard_size = page;
let total_size = guard_size + stack_size;
let base = unsafe {
libc::mmap(
std::ptr::null_mut(),
total_size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
)
};
if base == libc::MAP_FAILED {
return Err(io::Error::last_os_error());
}
let base = base as *mut u8;
let ret = unsafe {
libc::mprotect(base as *mut libc::c_void, guard_size, libc::PROT_NONE)
};
if ret != 0 {
let err = io::Error::last_os_error();
unsafe { libc::munmap(base as *mut libc::c_void, total_size) };
return Err(err);
}
Ok(Self { base, total_size, stack_size })
}
/// 16-byte-aligned top of the usable region.
pub fn top(&self) -> *mut u8 {
let raw_top = self.base as usize + self.total_size;
(raw_top & !15) as *mut u8
}
/// Pointer to the bottom of the usable region (just above the guard page).
pub fn usable_base(&self) -> *mut u8 {
unsafe { self.base.add(page_size()) }
}
pub fn stack_size(&self) -> usize {
self.stack_size
}
}
impl Drop for Stack {
fn drop(&mut self) {
unsafe {
libc::munmap(self.base as *mut libc::c_void, self.total_size);
}
}
}
fn page_size() -> usize {
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
}
fn round_up(n: usize, align: usize) -> usize {
(n + align - 1) & !(align - 1)
}