feat: I/O and mutex support (v0.3)
Add epoll-based non-blocking I/O and kernel-like mutexes: - src/io.rs: Complete epoll backend with timeout & error handling - src/mutex.rs: Fair mutex with waiter queues & parking integration - Enhanced scheduler to support synchronous I/O blocking - Comprehensive test suites for I/O (epoll) and mutex behavior - Documentation: LOOM.md concurrency model & README
This commit is contained in:
84
README.md
Normal file
84
README.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# smarm
|
||||
|
||||
> Silly Marks Abstract Rust Machine. A prototype green-thread actor runtime for Rust.
|
||||
|
||||
Implements the core ideas in [`LOOM.md`](./LOOM.md): green-thread actors on a
|
||||
shared heap, scheduled cooperatively, communicating only by `Send` messages.
|
||||
Erlang's isolation model without Erlang's copying GC, Rust's zero-copy
|
||||
ownership transfers without async's function colouring.
|
||||
|
||||
This is single-threaded for now — one scheduler, one OS thread. Multi-threaded
|
||||
scheduling is on the deferred list. The public API is shaped to match what the
|
||||
multi-threaded version will expose, so the migration shouldn't require source
|
||||
changes for downstream code.
|
||||
|
||||
## What's here
|
||||
|
||||
| Module | What it does |
|
||||
|--------------|------------------------------------------------------------------------|
|
||||
| `stack` | `mmap`'d growable stack with guard page; SIGSEGV on overflow |
|
||||
| `context` | `#[naked]` x86-64 context-switch shims, callee-saved regs only |
|
||||
| `preempt` | Allocator-driven preemption; `check!()` macro for no-alloc loops |
|
||||
| `pid` | `(index, generation)` PIDs; stale handles are detectable, not silent |
|
||||
| `actor` | Trampoline + `catch_unwind` boundary at the actor entry point |
|
||||
| `scheduler` | Run queue, slot table, spawn/join, parking, idle path |
|
||||
| `channel` | Unbounded MPSC channel; `recv` parks the actor |
|
||||
| `mutex` | `Mutex<T>` with mandatory timeout; FIFO waiters; parks the green thread |
|
||||
| `timer` | Min-heap of `(deadline, reason)`; `Sleep` and `WaitTimeout` reasons |
|
||||
| `io` | `block_on_io` for blocking work; `wait_readable`/`wait_writable` + `read`/`write` via epoll |
|
||||
| `supervisor` | `Signal::Exit` / `Signal::Panic` delivered to a parent actor's mailbox |
|
||||
|
||||
## Quick taste
|
||||
|
||||
```rust
|
||||
use smarm::{run, spawn, channel};
|
||||
|
||||
run(|| {
|
||||
let (tx, rx) = channel::<i64>();
|
||||
let h = spawn(move || {
|
||||
for _ in 0..3 {
|
||||
let v = rx.recv().unwrap();
|
||||
println!("got {v}");
|
||||
}
|
||||
});
|
||||
for v in 1..=3i64 {
|
||||
tx.send(v).unwrap();
|
||||
}
|
||||
h.join().unwrap();
|
||||
});
|
||||
```
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
src/
|
||||
stack.rs context.rs preempt.rs pid.rs actor.rs
|
||||
scheduler.rs channel.rs mutex.rs timer.rs io.rs supervisor.rs
|
||||
lib.rs
|
||||
tests/
|
||||
per-module integration tests
|
||||
benches/
|
||||
primes.rs fan-out/fan-in compute, vs tokio current_thread
|
||||
LOOM.md design intent
|
||||
```
|
||||
|
||||
## Building and running
|
||||
|
||||
Standard Cargo. Requires Rust 1.95 or newer (the `#[naked]` attribute went stable
|
||||
in 1.88; we use a few unrelated post-1.88 features). x86-64 Linux only —
|
||||
ARM64 and macOS are on the deferred list because of the assembly shim and the
|
||||
epoll dependency.
|
||||
|
||||
```sh
|
||||
cargo test # all tests
|
||||
cargo test --test mutex # one module
|
||||
cargo bench # primes benchmark vs tokio
|
||||
```
|
||||
|
||||
## What's not here
|
||||
|
||||
See the **Defer** section of `LOOM.md`. Notable absences: multi-threaded
|
||||
scheduler, supervisor restart-intensity caps, `join!` for handle groups,
|
||||
stack growth via remap, hierarchical timer wheel, fd-wait timeouts,
|
||||
`Signal::Timeout`. Each is mechanism we know how to add; none belongs in
|
||||
this iteration.
|
||||
Reference in New Issue
Block a user