Skip to content

Commit cc0ade6

Browse files
wan9chicodex
andcommitted
refactor(sigsafe): extract allocator crate
Co-authored-by: GPT-5 Codex <codex@openai.com>
1 parent 2658c1d commit cc0ade6

11 files changed

Lines changed: 42 additions & 22 deletions

File tree

Cargo.lock

Lines changed: 9 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ serde_norway = "0.9.42"
131131
sha2 = "0.11.0"
132132
shell-escape = "0.1.5"
133133
sigsafe = { path = "crates/sigsafe" }
134+
sigsafe_alloc = { path = "crates/sigsafe_alloc" }
134135
similar = "3.0.0"
135136
smallvec = { version = "2.0.0-alpha.12", features = ["std"] }
136137
snapshot_test = { path = "crates/snapshot_test" }

crates/fspy_preload_unix/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fspy_shared = { workspace = true }
1717
fspy_shared_unix = { workspace = true }
1818
libc = { workspace = true }
1919
nix = { workspace = true, features = ["signal", "fs", "socket", "mman", "time"] }
20-
sigsafe = { workspace = true }
20+
sigsafe_alloc = { workspace = true }
2121

2222
[build-dependencies]
2323
artifact_profile = { workspace = true }

crates/fspy_preload_unix/src/client/raw_exec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl RawExec {
4949
// execs), where malloc's lock may be held by a thread that no longer
5050
// exists. A per-call arena has exactly this lifetime, and hands back
5151
// the memory when the call ends.
52-
let arena = sigsafe::alloc::arena();
52+
let arena = sigsafe_alloc::arena();
5353
let mut ptr_vec = allocator_api2::vec::Vec::with_capacity_in(strs.len() + 1, &arena);
5454
for s in &mut strs {
5555
s.push(0);

crates/sigsafe/Cargo.toml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ publish = false
88
doctest = false
99

1010
[target.'cfg(unix)'.dependencies]
11-
allocator-api2 = { workspace = true }
12-
bump-scope = { workspace = true }
1311
rustix = { workspace = true }
1412

1513
# On Linux the page size is probed from the kernel directly (see param.rs);
@@ -26,10 +24,5 @@ rustix = { workspace = true, features = ["runtime"] }
2624
[target.'cfg(target_os = "linux")'.dev-dependencies]
2725
rustix = { workspace = true, features = ["param"] }
2826

29-
[target.'cfg(unix)'.dev-dependencies]
30-
# The `alloc` feature provides `Global`, letting tests run the pool against
31-
# the host allocator (and thus under Miri).
32-
allocator-api2 = { workspace = true, features = ["alloc"] }
33-
3427
[lints]
3528
workspace = true

crates/sigsafe/README.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Every function in this crate follows three rules:
3232
set of atomics, each touched by single complete operations.
3333
3. **No global allocation.** No function touches a heap behind the caller's
3434
back. Code that needs memory gets it from an explicit allocator —
35-
[`alloc`](src/alloc/mod.rs) provides one built on `mmap`.
35+
[`sigsafe_alloc`](../sigsafe_alloc) provides one built on `mmap`.
3636

3737
## How rule 1 is enforced on Linux
3838

@@ -53,8 +53,5 @@ backend check above is what keeps that true.
5353

5454
- `mm` — anonymous memory mappings: `mmap_anonymous`, `munmap`.
5555
- `param``page_size`.
56-
- `alloc` — allocation without malloc: `alloc::arena()` gives one
57-
intercepted call a bump arena that draws 64 KiB chunks from a process-wide
58-
lock-free pool and returns them when the call ends. Taking or returning a
59-
chunk is one atomic swap; when the pool is empty, chunks come straight
60-
from the kernel through `mm`.
56+
57+
Allocation without malloc lives in [`sigsafe_alloc`](../sigsafe_alloc).

crates/sigsafe/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#![cfg(unix)]
1515
#![cfg_attr(not(test), no_std)]
1616

17-
pub mod alloc;
1817
pub mod mm;
1918
pub mod param;
2019

crates/sigsafe_alloc/Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[package]
2+
name = "sigsafe_alloc"
3+
edition = "2024"
4+
license.workspace = true
5+
publish = false
6+
7+
[lib]
8+
doctest = false
9+
10+
[target.'cfg(unix)'.dependencies]
11+
allocator-api2 = { workspace = true }
12+
bump-scope = { workspace = true }
13+
sigsafe = { workspace = true }
14+
15+
[target.'cfg(unix)'.dev-dependencies]
16+
# The `alloc` feature provides `Global`, letting tests run the pool against
17+
# the host allocator (and thus under Miri).
18+
allocator-api2 = { workspace = true, features = ["alloc"] }
19+
20+
[lints]
21+
workspace = true
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
//! traced program (see the crate docs), so the preload library allocates
55
//! through this module instead. It stacks three layers and exposes only the
66
//! top one, [`arena`]. `MmapAllocator` is the bottom: a stateless allocator
7-
//! where every allocation is a fresh anonymous mapping from [`crate::mm`].
7+
//! where every allocation is a fresh anonymous mapping from [`sigsafe::mm`].
88
//! `ChunkPool` sits on top of it and caches fixed-size chunks, so that
99
//! frequent short tracing calls can reuse memory instead of paying two
1010
//! syscalls per call. [`arena`] creates one `bump_scope::Bump` per
1111
//! intercepted call, drawing its chunks from the process-wide pool and
1212
//! returning them on drop.
1313
14+
#![cfg(unix)]
15+
#![cfg_attr(not(test), no_std)]
16+
1417
mod mmap;
1518
mod pool;
1619

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ use core::{
66
};
77

88
use allocator_api2::alloc::{AllocError, Allocator};
9-
10-
use crate::{
9+
use sigsafe::{
1110
mm::{MapFlags, ProtFlags, mmap_anonymous, munmap},
1211
param::page_size,
1312
};
@@ -21,7 +20,7 @@ use crate::{
2120
/// the kernel does all the bookkeeping. A signal or a `fork()` can never
2221
/// catch it holding a lock or a half-written structure, because there is
2322
/// nothing to hold. The mapping calls and the page-size read come from
24-
/// [`crate::mm`] and [`crate::param`], which carry the same guarantee (see
23+
/// [`sigsafe::mm`] and [`sigsafe::param`], which carry the same guarantee (see
2524
/// their docs).
2625
///
2726
/// # What it accepts

0 commit comments

Comments
 (0)