Skip to content

docs: add orchestrator runtime concept page and board composition - #449

Open
rusty1968 wants to merge 1 commit into
OpenPRoT:mainfrom
rusty1968:runtime-doc-concept
Open

docs: add orchestrator runtime concept page and board composition#449
rusty1968 wants to merge 1 commit into
OpenPRoT:mainfrom
rusty1968:runtime-doc-concept

Conversation

@rusty1968

Copy link
Copy Markdown
Collaborator

Introduces a design page on the orchestrator runtime and how it turns hardware and IPC activity into the events the state machine consumes.

@rusty1968
rusty1968 marked this pull request as ready for review August 27, 2026 23:32
@rusty1968
rusty1968 requested review from chrysh and leongross August 28, 2026 16:46
@rusty1968
rusty1968 force-pushed the runtime-doc-concept branch from 06c5a1a to 51b4dfa Compare August 28, 2026 16:47
@chrysh

chrysh commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Add to docs/src/SUMMARY.md:

* [Runtime](./design/orchestrator/orchestrator-runtime.md)     

@chrysh

chrysh commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

The runtime page says "The three share one object_wait, so a slow image hash on one path cannot delay a boot window on another". I don't think the wait group gives us that.

object_wait bounds how long the loop waits, not how long it works. While an effect executor runs, the loop is not in the wait at all, so no deadline is in effect. Verify is inline today: Effect::VerifyFirmware calls Verifier::verify in driver/src/driver.rs:86. With a 200ms boot window and a 2s image hash, the window lapses at 200ms, nobody notices until the hash returns at 2s, and Event::Timeout fires 1.8s late.

What actually keeps the loop live is the other half, which the page does not state: every decode and every effect executor returns promptly. That is why staging is a pump rather than a single transfer call. Could the page say that rule directly instead of deriving liveness from the shared wait?

Two related questions:

  • The platform page says commands to crypto and storage are fire-and-forget and every reply comes back as a queued event. channel_transact is synchronous and it is the only outbound primitive the kernel gives us. What is the intended shape there?
  • Sources with no signal (the BootWatch walkers, later the update pump) need the loop to wake on its own. Would an adaptive deadline cover it: now while a job is live, wait_deadline() when idle?

@chrysh

chrysh commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

The page says BootWatchdogs folds all armed boot windows and the commit window into a single deadline. There is a second tracker for the same windows though: release_reset arms a BootWatch per component, and poll_boot_walks(now_millis) returns next_deadline_millis plus Event::Timeout(id) on WalkVerdict::Failed (driver/src/driver.rs:150).

So today the same boot window is tracked twice, in two units (Instant in BootWatchdogs, u64 millis in the walkers), and both paths produce Event::Timeout(id). The state machine drops the second one as stale via is_awaiting_boot, so nothing breaks, but two owners of one deadline is the failure mode we already agreed to avoid elsewhere.

The part that does break: the walkers are polled and nothing signals the loop on their behalf. If wait_deadline() only reflects BootWatchdogs, the loop sleeps straight past a walker's deadline.

Which one is meant to survive?

@chrysh

chrysh commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

poll_boot_walks(now_millis) returns Event::Timeout(id) when a walk hits WalkVerdict::Failed (services/orchestrator/driver/src/driver.rs:150), so there is an edge from the driver back into dispatch that the picture does not show. Worth an arrow?

Comment on lines +11 to +12
It gathers three possible inbound sources — **hardware interrupts**
(boot-progress lines the orchestrator owns directly), **IPC channels**, and

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the boot monitoring really steered by hardware interrupts? Our trait based implementation as of now is naturally agnostic, but when we discussed this we talked about polling the GPIO lines, instead of waiting for real hardware interrupts handled by the hardware NVIC and ISRs.

I understand what you want to say by this, but if we are not relying on hardware inerrupts we should adapt the wording here.

`Signals::USER` on a client channel to notify without a reply). The loop is
written once against "a member that signaled, or the deadline that lapsed,"
never against a specific source; what differs between sources is only the
*decoder* that turns each into an `Event`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this decoder look like and where is it defined?

The runtime is a single-threaded loop parked in one place: a kernel
`object_wait` over a **wait group**. Every inbound source is registered once as a
*member* of that group (`wait_group_add`), and the wait returns whichever member
signaled. Each member resolves to at most one `Event`:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what is the use case for a registered member to resolve to no Event?
If this is not the case, we should be precise and say

Suggested change
signaled. Each member resolves to at most one `Event`:
signaled. Each member maps to exactly one `Event`:

The unifying idea is the kernel **wait group**: interrupts and IPC are not
separate mechanisms but interchangeable *members* of one group, and a watchdog
deadline is that same wait's *timeout* — so all three collapse into the return
of one `object_wait(handle, signal_mask, deadline)`. A *signal* here is just a

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we link the source defintiion/link to pigweed kernel upstream sources here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants