Releases: cedrivard/embassy-supervisor
Release list
embassy-supervisor 0.10.0
Adds a graph-level default executor, fault injection, and a stricter local
resource invariant. Companion crate versions: macros 0.10.0, syntax 0.4.0,
tools 0.5.0.
Added
default executor NAME;sets a default executor for alltask:andspawn:
nodes and pools. An explicitexecutor:override still wins. One per graph,
not#[cfg]-gable. See the README for usage on interrupt tiers.fault-injectfeature addsTaskNode::inject(Fault),clear_fault(), and
fault()withFault::{Stall, Wedge, Crash, Hog(Duration)}. Thetask:shell
intercepts polls for stall, crash, and hog faults. Wedge hides shutdown
requests and swallows acks until cleared or replaced. Hand-writtenspawn:
tasks only support wedge. Adds oneAtomicU8, oneAtomicU32, and one
AtomicWakerper node. Off by default.
Changed
localresources are now local to the node's executor, not the supervisor.
Thelocal+executor:rejection is removed; instead, the macro checks that
everylocalslot resolves to one executor. Bring-up now peeks the slot
without moving the value.wait_shutdown()re-checks the request after a wake whenfault-injectis
enabled. Unchanged otherwise.
Fixed
- Fixed docs: the
Sendbound applies to spawn arguments, not the routed future
itself.SpawnerSlot's rustdoc now explains this with acompile_fail
doctest.
embassy-supervisor-tools 0.5.0
embassy-supervisor-tools-v0.5.0 embassy-supervisor-tools 0.5.0
embassy-supervisor-syntax 0.4.0
Adds default executor NAME; and drops the local + executor: rejection.
Requires embassy-supervisor-macros 0.10.0 and embassy-supervisor-tools 0.5.0.
Added
default executor NAME;item, applied to eligible nodes and pools with
executor_defaulted = true. Errors if it has#[cfg], appears in a fragment, or is
duplicated.
Removed
- Rejection of
localcombined withexecutor:. The macro crate now checks that every
localslot resolves to one executor.
embassy-supervisor-macros 0.10.0
Pins embassy-supervisor-syntax 0.4.0.
Added
default executor NAME;: the default executor is seen by all downstream checks, and
fragments declaring one are rejected at the fragment site as well as at compose.fault-injectfeature:task:shells wrap the worker inInjectedand mark the node
shelled.exit:provides the wrappedOption, preserving the "unreachable call"
diagnostic for diverging workers.- Reject a
localslot declared on two executors, naming both declarers and their
tiers, including aprovides:whose node tier differs.
Changed
- Local slot
is_fillednow peeks through the cell pointer under the lock, so the
supervisor's executor never moves the!Sendvalue even bytewise. - Updated the
executor:routing comment to state theSendbound is on the spawn
arguments, not the future.
embassy-supervisor v0.9.0
One waker per budget slot, and the crates point at the documentation site.
-
Breaking (hand-written
Divisibleonly):Divisible::registernow takes
the slot to park on.Budgetkeeps oneAtomicWakerper slot and only wakes
slots whose grant changed during rebalance. -
Corrected the
vetofeature's cost note: 4 bytes perCouplingwithout
coupling-observe(16 to 20 bytes on thumbv8m), zero with it. Thebudget
note now states the budget size and the 8-byteclaimsslice per node.
embassy-supervisor v0.8.1
Ships with embassy-supervisor-macros 0.9.1 (pinned by exact version) on
embassy-supervisor-syntax 0.3.1; embassy-supervisor-tools 0.4.1 scans
cfg_attr-applied #[dataflow] fns.
Fixed
#[dataflow_bundle]no longer drops a member fn whose#[dataflow]is
applied throughcfg_attr: the bundle macro reads the module's attributes
before the compiler appliescfg_attr, so the layer is unwrapped there.
The tools' scanners see the same form now, sosupervisor-mermaiddraws
such a fn's derived edges instead of warning that it found no#[dataflow].
Changed
- The trace hooks follow the executor's next API. embassy-executor's git
main (the release after 0.10) replaces the seven_embassy_trace_*symbols
with araw::trace::Traceimpl registered throughtrace_impl!, and passes
ExecutorId/TaskIdnewtypes instead ofu32s.RUSTFLAGS="--cfg embassy_supervisor_trace_v2"builds the trace layer against it; the
recorders keep theiru32keys, ids narrowing through the new
trace::task_key/trace::executor_key(cfg-only). The hook bodies moved
from the proc-macro into__sv_trace_hooks!, a hidden macro of this crate
thatsupervisor_graph!expands undertrace-hooks, so which API they
speak is decided by this crate's build. No change on embassy-executor 0.10. - CI's
trace vs embassy git (canary)job now also runs the trace test
suite, and patchesembassy-executor-timer-queueto git together with the
executor: with only the executor patched, embassy-time's queue utils kept a
second copy of the timer-queue crate, sized differently, and every timeout
in the wedged-task tests silently never fired.
embassy-supervisor-tools 0.4.1
Pins embassy-supervisor-syntax = "=0.3.1".
Fixed
- A fn whose
#[dataflow]is applied throughcfg_attrwas reported as
"no#[dataflow]fn among the scanned files" and its derived edges left
undrawn.supervisor-mermaidandsupervisor-lintnow scan it; the
cfg_attrpredicate draws on its edges like a#[cfg]on the fn.
embassy-supervisor-syntax 0.3.1
Additive. embassy-supervisor-macros = "=0.9.1" and embassy-supervisor-tools
0.4.1 are the matching consumers.
Added
dataflow_attr(&Attribute) -> Option<(Attribute, Option<String>)>: the
dataflowattribute an attribute carries oncecfg_attris applied, plus
the predicate it sits under (feature="grown"; nested layers fold into
all(..)).
Fixed
is_dataflow_attrandscan_dataflownow see a#[dataflow]written as
#[cfg_attr(pred, dataflow)]. The compiler expands that form, so the
tables were emitted while the textual scan skipped the fn. Accesses found
this way carrypredincfgs, as a#[cfg]on the fn would.Access::cfgsrecords a predicate once when the fn and the call site
repeat it, instead of twice.
embassy-supervisor-macros 0.9.1
Rides embassy-supervisor-syntax = "=0.3.1"; ships with embassy-supervisor
0.8.1, whose __sv_trace_hooks! the trace-hooks expansion now calls.
Changed
trace-hooksexpands the supervisor's__sv_trace_hooks!at the unnamed
graph's declaration site instead of spelling out the sevenno_mangle
_embassy_trace_*functions itself: the hook bodies are the supervisor's,
so which executor hook API they speak (0.10's symbols, or theTraceimpl
embassy git main takes under--cfg embassy_supervisor_trace_v2) is
decided by that crate's build. Same expansion result on embassy-executor 0.10.
Fixed
#[dataflow_bundle]sees its members' attributes as written, before the
compiler appliescfg_attr. A member declared#[cfg_attr(pred, dataflow)]
was skipped, its write or read missing from the bundle while the fn's own
tables carried it. The bundle now unwraps the layer through the syntax
crate'sdataflow_attr.
embassy-supervisor v0.8.0
Six things a graph could not say about its couplings, and now can.
Ships with embassy-supervisor-macros 0.9.0 (pinned by exact version) on
embassy-supervisor-syntax 0.3.0; embassy-supervisor-tools 0.4.0 reads the
new markers.
Added
- The other half of demand-start.
Backedcounts its readers:open
hands back anOpen<T>guard (Derefto the signal,signal()for the
'staticreference),Backed::openers()is the count, and
Backed::unwatched(cooldown)resolves once it has sat at zero for the
whole cooldown — a reader arriving inside it restarts the clock.
TaskNode::retire(&SIG, cooldown)is the producer's verb: it waits that
out, withdraws readiness (so a late opener waits instead of reading a
producer on its way out, and an opener admitted just before cancels the
retirement), and withcontrolrequests its ownDeactivate. The next
openre-activates it, as before. divisibleresources (featurebudget).resources: [POWER: divisible]declares aBudget<K>the graph sizes to its holders (one slot
per node, one per pool member). Each holder's shell receives aClaimant
bound to its slot (want,grant,wait_grant_change); an allocator
provides the capacity and divides it with aBudgetPolicy—FairShare
orShrinkFastGrowSlow— onwait_change(); a change landing while
rebalanceruns re-armswait_change, so a looping allocator re-divides
at once. The supervisor releases a
holder's share when it stops, including a holder that misses its shutdown
ack; aPausepark keeps it. An unprovided budget isResourceMissing;
provides:may name one.- Distributed veto (feature
veto).writes: [crate::TRIP veto]gives a
writer one contributor slot of aVetoGate<N>: asserted while any
contributor holds it, released only once all let go. The macro numbers the
writers per gate and emits a compile-time check that the target is a
VetoGatewith a slot for each.node.veto(&TRIP)yields aVetothat
moves only its own bit; the actuator parks onwait_asserted/
wait_released. A stopped writer's bit stays asserted; release is explicit.
Undercoupling-observethe gate counts its flips, soveto observed beat
is a heartbeat. shared serialized: a compile-time rule that every holder of the slot
runs on one executor — priority ceiling by construction for a serialized
link, since embassy can neither boost a holder nor migrate a task. No
feature, no runtime cost.Stamped<T>(featurecoupling):w()stamps when a write begins and
hands the inner signal over, so a consumer can askage(),is_fresh(max)
orread_fresh(max); the token forwards to the inner signal. The read-side
half of write freshness; the README draws the line to value validity, which
stays the consumer's.- The README states the private-module recipe for gated statics and its
limit ("bypass requires going out of your way");supervisor-lint --only public-gatereports aBacked/Leased/VetoGatestatic that is not
private.
Changed
- Breaking:
TaskNode::openreturnsT::Handleinstead of&'static T—
anOpen<T>forBacked. A reader that chained a'static-taking call
onto the result (node.open(&X).await.receiver()) binds the guard first;
one that needs the'staticreference itself calls.signal().Gated
gainstype Handle: Derefandfn admit(&'static self) -> Self::Handle; a
wrapper that only waits setsHandle = &'static Self. retireandvetoare built-in write verbs of the#[dataflow]scanner.
A body that already called a node method by either name is now rewritten.ack_droppedalso wakes openers parked on the stopped producer's gate (so
they request the next start without waiting out the retry) and releases the
node'sdivisibleshares;FaultKind::ShutdownTimeoutreleases them too.- Signal entry markers (
observed,beat,veto) parse in any order;
via <expr>still qualifiesobservedand ends the entry.
Migration notes in the README, full details in the CHANGELOG.