Skip to main content

Module arena_oracle

Module arena_oracle 

Source
Expand description

phase-412 #4 — the arena’s HOST ORACLE, held to at compile time.

nros-node/build.rs is the one place that knows what this image’s declared entities cost: it sums the per-kind model over NROS_ENTITY_COUNT_* (and the declared depths) and emits the result as arena_model::REQUIRED beside the arena it derives from it (cargo:arena_size). Before this module that requirement stopped at the derivation. An image that STATED NROS_EXECUTOR_ARENA_SIZE below it built, linked, flashed and then died at the first registration that did not fit, with NodeError::BufferTooSmall — on a board whose only diagnostic channel may be a RAM record read back with a debugger (issue 1036).

Here the two numbers meet in one compilation, so the refusal is a build error that names the knob, both numbers and the shortfall.

§Which arms can be held, and which cannot

The arena is a slice of caller-supplied backing, so “the arena” is really one number per PLACEMENT. A compile-time check needs the arena and the requirement to be constants in the same compilation; that decides it.

armarena comes fromchecked
Rust .bss EXECUTOR_BACKINGExecutorSizing::DEFAULT.arena = ARENA_SIZEcompile time, the ARENA_SIZE const item below
Rust heap, default sizing (open / open_multi / open_with_rmw past the static)the same DEFAULTcompile time, same assertion
C rclc_executor_t::_opaqueEXECUTOR_OPAQUE_U64S, measured from ExecutorInlineStorage = DEFAULTcompile time, same assertion (nros-c compiles after it)
C++ Node::GlobalStorageHolder / Executor::storage_CPP_EXECUTOR_OPAQUE_U64S, measured the same waycompile time, same assertion
Rust open_in over a caller’s const sizingthe caller’s ExecutorSizing::arenacompile time, OPT-IN: ExecutorSizing::assert_covers_model
Rust heap, per-entry sizing (open_sized, arena_size_for(cbs))a RUNTIME cbs handed through BoardEntryNO — runtime
Rust open_in over a runtime slice / runtime sizingruntime valuesNO — runtime

The runtime arms are not faked. Their arena is a value, not a constant, and an executor there may hold a SUBSET of the image (a tier), so the image-wide model is not even the right bound. What they get is the registration-time refusal every arm already has: arena_alloc and arena_alloc_with_trailing report the entity, the shortfall and the knob (report_arena_exhausted, issues 0900 / 1036) and write the shortfall to the boot record.

§What the model is, and what it is not

REQUIRED is the per-kind sum, whose terms executor::arena asserts to be upper bounds on the entry types they stand for. So an arena at or above it fits what was declared. It is NOT a lower bound on what an image needs: the terms over-price (issue 1255 prices every subscription at one image-wide type bound), so an arena stated below the model may still fit. The refusal is deliberate anyway — a number below the model is a claim the build cannot check, and the tree’s answer to an over-priced model is to correct the model’s INPUTS (declared depths, NROS_PUBSUB_QOS_DEPTH, per-type bounds), which re-derive the arena, rather than to hand-state a number that goes stale the next time any term moves.

An image that declares nothing has REQUIRED == 0: the derivation then budgeted a worst case over NROS_EXECUTOR_MAX_CBS slots, which is a budget and not a requirement, and stating less than a budget is the ordinary use of the knob. Nothing is refused there.

Functions§

assert_covers_model
Refuse, during CONST EVALUATION, an arena below this image’s model.
shortfall
Bytes arena falls short of this image’s modelled requirement; 0 when it covers it, or when the image declared nothing.