Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
85cd3b6
The terminal and toyos-window never block on a readiness answer alrea…
Japabu Oct 1, 2026
045b143
Merge remote-tracking branch 'origin/main' into wt/toyos-winitstall
Japabu Oct 1, 2026
aac1a75
toyos::poller hands out only the answer of a handle's latest registra…
Japabu Oct 1, 2026
9ba71ec
The terminal and toyos-window read on the poller's answer again
Japabu Oct 1, 2026
bd06aa1
issues: a Finder file in the C++ runtime scratch panics its removal
Japabu Oct 1, 2026
438da6d
Merge remote-tracking branch 'origin/main' into wt/toyos-winitstall
Japabu Oct 1, 2026
4812962
poller: an empty drain asserts against what it handed out
Japabu Oct 1, 2026
4a26c19
poller: a registration that answered holds no place in the registry
Japabu Oct 1, 2026
4aac657
poller: the registry's bound says what it rests on
Japabu Oct 1, 2026
950311c
Merge remote-tracking branch 'origin/main' into wt/toyos-winitstall
Japabu Oct 1, 2026
7d31aca
inbox: a watch is answered after a look at its object, never by a post
Japabu Oct 1, 2026
c3e104a
issues: one Finder issue for both build steps; a ring's IRQ lock no h…
Japabu Oct 1, 2026
67881a6
inbox: the host gates know a poll can end, and the control is declared
Japabu Oct 1, 2026
9063ab6
Merge origin/main (a31eec595: #659, #643, #660, #663, #668, #671, #67…
Japabu Oct 2, 2026
648ced1
inbox: a submitter parks on its polls, a watch during a look holds it…
Japabu Oct 2, 2026
b6b6196
inbox: one look is one pass, so a peer posting an empty pipe holds no…
Japabu Oct 2, 2026
f2c8768
Merge origin/main (b331934c9: #636) into wt/toyos-winitstall
Japabu Oct 2, 2026
5f62645
inbox: a wait that goes round reads its kill, an answer's wake is the…
Japabu Oct 2, 2026
fac2352
Review round on #655: `HELD`'s doc drops the clause the header alread…
Japabu Oct 2, 2026
ce81551
Merge origin/main (dc8212c7f: #642) into wt/toyos-winitstall
Japabu Oct 2, 2026
4695a65
Merge origin/main (dd8738302: #647) into wt/toyos-winitstall
Japabu Oct 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
status: open
kind: defect
opened: 2026-10-02
---

# `toyos::Poller` is `Sync`, and a watch moves the submission tail in two steps

`Poller::watch_raw` loads the submission tail, writes the entry at it and
stores the tail plus one, through `&self`, and `Poller` is `unsafe impl Sync`
(`toyos/src/poller.rs`). Two threads watching through one `&Poller` write one
slot at once and advance the tail once, so one watch is lost. `rg 'Arc<Poller>'`
and `rg 'static.*Poller'` over `toyos`, `userland` and `tests` find no poller
shared between threads.

**Exit**: `Poller` is not `Sync`, or a watch claims its slot in one step.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
status: open
kind: defect
opened: 2026-10-02
---

# A ring handed to another process resolves its watches in the receiver's table

An `Inbox` handle carries `DUP` and `TRANSFER` (`ops::initial_rights`), and
`inbox_submit` resolves every handle a watch names in the calling process's
table (`inbox::resolve`): an `OP_WATCH` when it is submitted, and a fired
poll's when its submitter looks at the object again. The ring's page is mapped
into its creator alone, so a process handed the ring runs the submissions the
creator wrote, and looks at the creator's fired polls, against whatever its
own table holds under the creator's handle numbers. It reaches no object it
does not hold.

**Exit**: a ring cannot leave the process that made it, or a watch names its
object by something its registrant's table decided; a test hands a ring to a
child.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
status: open
kind: defect
opened: 2026-10-02
---

# A close of one handle ends every ring's poll on its object

`ops::close` answers every poll on a watch its object ends with `-NotFound`
(`Watch::cancel_polls`), in every ring, when any one handle to a pipe's read
end or an acceptor closes. A sibling handle from `dup` keeps the object open,
and its polls end all the same. `toyos::poller`'s `drain` hands the token of a
negative completion to its caller as it does a ready one's, so a reader that
takes that token for bytes and reads blocking parks on an object that is open
and empty. No caller in the tree reaches it: fsd's acceptors are endowed and
never duplicated. `inbox_cancel_wakes` stages the close.

**Exit**: a poll ends only when the last handle to its source closes, or a
completion's result reaches `Poller`'s caller; a test closes a duplicate under
a watch and reads what the wait hands back.
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ Held by the small-kernel track's stage 6 step 2
(`issues/kernel/the-kernel-is-small-interrupts-post-and-threads-wait.md`),
whose instrument is the only thing that can read it.

Every poll ring's own watch and its completions sit behind an `IrqLock`
Every poll ring's own watch sits behind an `IrqLock`
(`kernel/src/inbox/mod.rs`), because a device handler's post
reaches them through the polls it fires. So any process, not only a device's
reaches it through the polls it fires. So any process, not only a device's
holder, decides how long a CPU runs with interrupts masked:

- **N threads parked in `submit` on one ring**
Expand All @@ -25,9 +25,9 @@ holder, decides how long a CPU runs with interrupts masked:
that finds the list full copies it, all with interrupts masked.
- **A claim's holder polling its claim from R rings, P polls each** (up to
`MAX_PENDING_WATCHES`, 1024) makes its device's
handler fire R × P entries under the claim's list lock, each taking that
ring's completions lock and posting that ring's watch, whose own N threads
it notifies. Entries a post in place fired stay in the list until
handler fire R × P entries under the claim's list lock, each posting its
ring's watch, whose own N threads it notifies. Entries a post in place
fired stay in the list until
registrations sweep them four at a time.

Nothing caps N: a thread costs its process a 128 KiB kernel stack
Expand Down
27 changes: 0 additions & 27 deletions issues/kernel/a-zero-byte-pipe-write-wakes-the-readers-watch.md

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
status: open
kind: defect
opened: 2026-10-02
---

# Two submitters of one ring race its last completion slot

`polls::deliver` asks the ring for room and then answers, in two holds of the
completions' lock. Two threads in `inbox_submit` on one ring can both find the
last slot free; the second answer finds the ring full, and `post_completion`
drops it and counts it in `dropped`, as it does every completion written to a
full ring. A ring one thread submits to drops no watch's answer, and
`toyos::Poller` sizes its rings past what its watches can answer.

**Exit**: the room an answer was looked up for is the room it is written
into; a test runs two submitters against a ring with one slot.
9 changes: 9 additions & 0 deletions kernel-loom/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ wake-fence-off = []
#
# Never on by default, and no kernel build can reach it.
poll-fire-load-store = []
# The negative control for a poll ring's answer. It makes `inbox/polls.rs`
# answer a fired poll with its interest and look at nothing, so a post with
# nothing behind it is an answer and `inbox_answer.rs` must red:
#
# cargo test --manifest-path kernel-loom/Cargo.toml --features post-is-an-answer \
# --test inbox_answer
#
# Never on by default, and no kernel build can reach it.
post-is-an-answer = []
# The negative control for the ticket lock's acquire edge. It makes `sync.rs`'s
# two loads of `now` — the ones that decide ownership — `Relaxed`, so the
# previous owner's writes are unordered against the next owner's reads, and
Expand Down
12 changes: 12 additions & 0 deletions kernel-loom/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,18 @@ pub mod device_irq;
#[path = "../../kernel/src/inbox/once.rs"]
pub mod poll_once;

/// `polls.rs` names its one-shot as `super::once`, which in the kernel is
/// `crate::inbox::once`; this is what makes that path resolve here.
pub use poll_once as once;

extern crate alloc;

/// A ring's polls and when one is answered, driven against a fake object by
/// `tests/inbox_answer.rs`. It names the one-shot above, `toyos-abi` and
/// `alloc`, and nothing of the kernel's.
#[path = "../../kernel/src/inbox/polls.rs"]
pub mod inbox_polls;

/// What `sleeplock.rs` names of the kernel's watch, and nothing more.
///
/// **The park is shimmed, and that is the scope statement for
Expand Down
Loading
Loading