Skip to content

Commit 3cbae19

Browse files
docs: correct per-endpoint queue cost math for MAX_ENDPOINTS 32 -> 64 (#4)
What: HD-01 from the backlog re-harvest. The per-endpoint message-queue memory cost was documented off the dead MAX_ENDPOINTS=32 count; it has been 64 since A-v.d.3. Corrects the stale figure in three comment/doc spots (no code change): - src/ipc/mod.rs:346 (EndpointQueue SCAFFOLDING doc): "32 endpoints ... ~= 140 KiB" -> "64 endpoints ... ~= 280 KiB". - src/ipc/mod.rs:973 (sharded-lock comment): "all 32 endpoints" -> "all 64 endpoints" (sibling caught during the edit; same stale count, same file). - docs/ASSUMPTIONS.md:88 ("Per-endpoint message queue" row): "32 x 16 x 280 B ~= 140 KB" -> "64 x 16 x 280 B ~= 280 KiB", and the stale source ref :242 -> :344 (the SCAFFOLDING bound's line; :242 now points at Message::payload). - docs/ASSUMPTIONS.md:5 frontmatter last_synced_to_code -> 2026-06-08. Arithmetic: 64 x 16 x 280 = 286,720 B = 280.0 KiB exactly. The const value (16 messages/queue) is unchanged; only the documented total cost moves. Why: section 8 doc-sync hygiene. Comment/doc math must track the live MAX_ENDPOINTS. No behavior change, no bound introduced, no gate tripped. Out of scope (follow-up, ADR-edit gate): docs/adr/005-ipc-primitives-control-and-bulk.md repeats the same stale figure at lines 43, 49, 265. Fixing the ADR body needs the ADR-edit Stop-and-Ask gate (diff + sign-off + Divergence appendix) - not bundled here. Verification: make check-stable clean (x86_64 + aarch64); make check-assumptions clean (307 baseline, 0 new); stale-math grep returns zero across both target files. Staged files: docs/ASSUMPTIONS.md src/ipc/mod.rs Co-authored-by: cambios-agent[bot] <291873290+cambios-agent[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5e3ce17 commit 3cbae19

2 files changed

Lines changed: 4 additions & 4 deletions

File tree

docs/ASSUMPTIONS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
doc_type: implementation_reference
33
owns: project-wide numeric bound catalog
44
auto_refresh: required
5-
last_synced_to_code: 2026-05-14 (ADR-029 step 5A — bitmap + journal record-type bounds)
5+
last_synced_to_code: 2026-06-08 (HD-01 — per-endpoint queue cost math corrected for MAX_ENDPOINTS 32->64)
66
authoritative_for: every fixed numeric bound, fixed-size array, hard limit in kernel code — what kind of bound it is, why this number, and what triggers re-evaluation
77
-->
88

@@ -85,7 +85,7 @@ These are the ones that will need to grow as the system matures. They are correc
8585
| `MAX_CPUS` | 256 | [src/lib.rs:91](../src/lib.rs#L91), [src/arch/x86_64/percpu.rs:23](../src/arch/x86_64/percpu.rs#L23), [src/arch/aarch64/percpu.rs:23](../src/arch/aarch64/percpu.rs#L23), [src/arch/aarch64/gic.rs:30](../src/arch/aarch64/gic.rs#L30) | Matches xAPIC 8-bit APIC ID space; statically-sized per-CPU arrays. | x2APIC support (32-bit IDs) or > 256-core targets. Not a v1 concern. |
8686
| `MAX_ENDPOINTS` | 64 | [src/ipc/mod.rs:35](../src/ipc/mod.rs#L35) | Historically matched `MAX_PROCESSES` (one endpoint per service). Sharded IPC has one shard per endpoint; static array. | `MAX_PROCESSES` is gone as of Phase 3.2a — the process table now scales with tier policy. This endpoint cap should eventually move too (tie it to `config::num_slots()` or a new `MAX_ENDPOINTS_PER_SLOT * num_slots()` computation). First Phase 3 service that needs >64 endpoints is the trigger. |
8787
| `MAX_CAPS_PER_PROCESS` (per-process capability table) | 64 (16 under `cfg(kani)`) | [src/ipc/capability.rs:133](../src/ipc/capability.rs#L133) | Bounded set for verification; cache-line-friendly linear scan. Bumped 32 → 64 at A-v.d.3 in lockstep with `MAX_ENDPOINTS` (the boot manifest grants one cap per endpoint, so the two must match or trailing endpoints silently fail their grant — the original fde-mount=32 IPC bug). `verification/capability-proofs` references this const directly. Under `cfg(kani)` it shrinks to 16: P3.7 symbolically fills a full table and `grant`'s per-call scan makes that ~O(N²), so at 64 the CBMC formula exhausts CI-runner memory (the first Tier B GitHub Actions run OOM'd). The proven "full table rejects further grants" property is size-independent, so 16 proves the same guarantee — same technique as `MAX_FRAMES`'s `cfg(kani)` shrink. | The policy service holds one capability per service it mediates, the audit consumer holds one per producer; 64 will get tight when those land at scale. |
88-
| Per-endpoint message queue | 16 | [src/ipc/mod.rs:242](../src/ipc/mod.rs#L242) | Pre-allocated 32 × 16 × 280 B ≈ 140 KB; conscious memory cap. | Phase 3 audit telemetry channel (ADR-007) will see bursts; first dropped event is the trigger. |
88+
| Per-endpoint message queue | 16 | [src/ipc/mod.rs:344](../src/ipc/mod.rs#L344) | Pre-allocated 64 × 16 × 280 B ≈ 280 KiB; conscious memory cap. | Phase 3 audit telemetry channel (ADR-007) will see bursts; first dropped event is the trigger. |
8989
| `MAX_VMAS` (per process) | 256 | [src/process.rs:35](../src/process.rs#L35) | One slot per allocated user-space region; bump allocator for vaddrs. Sized for v1 endgame graphics compositor ([ADR-011](adr/011-graphics-architecture-and-scaling.md)): ~50 VMA entries (3 framebuffer mappings + 6 scanout channels + 30 window surfaces + GPU MMIO + command/memory channels + heap + stack), 4× headroom per CLAUDE.md Convention 8. Memory cost: ~6 KiB per VmaTracker (was 1.5 KiB at 64). | Bumped 2026-04-13 from 64 in the Phase GUI-0 prep pass. Next revisit: the first service holding 50+ simultaneous channel mappings (texture-heavy GPU workloads, multi-compositor split-brain). |
9090
| `MAX_FDS_PER_PROCESS` | 64 | [src/process.rs](../src/process.rs) | Per-process file descriptor table for POSIX `FileDescriptor`s per [ADR-029 § Decision 4](adr/029-posix-file-storage-model.md). Sized for v1 endgame win-compat: a QuickBooks-class shim peaks around ~20 open files (registry-backed manifests + config + app data + a handful of stdio/IPC). 64 slots gives the 25%-utilization-rule's 4× headroom over the peak per CLAUDE.md Convention 8. Memory cost: ~3.5 KiB per process, paid out of the kernel object-table region per [ADR-008](adr/008-boot-time-sized-object-tables.md). | A single process is observed holding > 16 open fds in a real workload, or `posix-fs-service` moves opens userside (ADR-029 migration step 12) and the per-process kernel-side cap becomes superfluous. |
9191
| `MAX_OBJECTS` (RamObjectStore) | 256 | [src/fs/ram.rs:22](../src/fs/ram.rs#L22) | Phase 0 RAM-backed store, fixed-capacity array. Still in place as a fallback / test fixture after Phase 4a.i; `DiskObjectStore` is the persistent backend. | Retire `RamObjectStore` entirely once `DiskObjectStore` is the runtime default (Phase 4a.iii hot-swap). |

src/ipc/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ impl CapabilityRights {
343343
///
344344
/// SCAFFOLDING: 16 messages per endpoint queue.
345345
/// Why: verification wants a predictable memory layout and bounded queue size.
346-
/// Pre-allocated 32 endpoints × 16 messages × ~280 B ≈ 140 KiB at boot.
346+
/// Pre-allocated 64 endpoints × 16 messages × ~280 B ≈ 280 KiB at boot.
347347
/// Replace when: the audit telemetry channel (ADR-007) starts seeing bursts
348348
/// that overflow this — first dropped event is the trigger. Note: bumping
349349
/// this also bumps the boot memory cost linearly. See docs/ASSUMPTIONS.md.
@@ -970,7 +970,7 @@ impl EndpointShard {
970970

971971
/// Sharded IPC manager — per-endpoint locking eliminates global serialization.
972972
///
973-
/// Instead of one global lock for all 32 endpoints, each endpoint gets its
973+
/// Instead of one global lock for all 64 endpoints, each endpoint gets its
974974
/// own Spinlock. CPUs communicating on different endpoints never contend.
975975
///
976976
/// The interceptor is shared (read-only after boot), so it's stored separately

0 commit comments

Comments
 (0)