From a6d4695c6d8e4ccfee99fd47ebdd26937f05a36f Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 21 Oct 2026 10:24:55 +0200 Subject: [PATCH 1/3] sdk: the transport is toyos::transport, and no crate of its own The owner decided (2026-10-21) that the transport belongs in the SDK and is not published as a separate crate. `toyos-transport` was in `PUBLISHED`, and crates.io's trusted-publishing token cannot create a crate, so every publish run since #905 has been red and the nightly release refuses. - `sdk/transport/src` is now `sdk/toyos/src/transport`, unchanged in logic. The module keeps `#![forbid(unsafe_code)]` and its clippy forbids as inner attributes, makes no syscall and allocates nothing, and is host-tested through `toyos`'s library tests. `toyos::net::stream` stays its syscall adapter. - The loom models are `sdk/toyos/tests/transport_loom.rs`. Their controls are `toyos` features, named `transport-*` beside the SDK's `log-ring-*`, and `build/ci.rs`'s `CONTROLS` runs each under package `toyos`. - `every_model_control_is_run` now reads the guest libraries' manifests as well as the host members', since a host tests both and `toyos` now declares controls. A clippy shape lints `transport_loom`; the workspace shapes already lint `toyos`'s library as a dependency. - blockring depends on `toyos`; netstack and its node drop the extra dependency. - The crate's workspace membership, `PUBLISHED` entry, std sources, manifests and `[patch]` in `build/sysroot.rs` are removed. Three lockfiles drop the package, and the Rust fork's `library/Cargo.lock` drops it in fork commit 11e31a52778, which the `rust` gitlink now names. - `PUBLISHED`'s doc comment says a crate joins only once crates.io holds it. The record of the red publish runs now waits only for green runs after this lands. The issue records naming the crate, its path or its controls are updated. Co-Authored-By: Claude Opus 5.5 --- Cargo.lock | 14 +--- Cargo.toml | 1 - build/build.rs | 10 ++- build/ci.rs | 31 +++++---- build/clippy.rs | 15 ++-- build/hostws.rs | 2 +- build/sdkversion.rs | 4 +- build/sysroot.rs | 18 ++--- build/toolchain.rs | 3 +- ...names-an-error-code-rustdoc-never-reads.md | 2 +- ...ublish-until-someone-puts-it-up-by-hand.md | 15 ++-- ...n-its-drop-while-a-failed-model-unwinds.md | 3 +- ...ves-every-byte-through-two-kernel-pipes.md | 6 +- ...ransport-heads-orderings-have-no-oracle.md | 4 +- issues/there-is-no-wifi.md | 4 +- lib/blockring/Cargo.toml | 8 +-- lib/blockring/src/client.rs | 2 +- lib/blockring/src/entry.rs | 2 +- lib/blockring/src/layout.rs | 2 +- lib/blockring/src/lib.rs | 6 +- lib/blockring/src/model.rs | 2 +- lib/blockring/src/wire.rs | 2 +- rust | 2 +- sdk/libc/Cargo.lock | 5 -- sdk/toyos/Cargo.toml | 51 +++++++++++++- sdk/toyos/src/lib.rs | 4 +- sdk/toyos/src/net/stream.rs | 8 +-- .../src => toyos/src/transport}/arena.rs | 2 +- .../src => toyos/src/transport}/inflight.rs | 6 +- .../src/lib.rs => toyos/src/transport/mod.rs} | 24 +++---- .../src => toyos/src/transport}/queue.rs | 10 +-- .../src => toyos/src/transport}/session.rs | 21 +++--- .../src => toyos/src/transport}/stream.rs | 20 +++--- .../loom.rs => toyos/tests/transport_loom.rs} | 49 ++++++------- sdk/transport/Cargo.toml | 69 ------------------- system/netstack/Cargo.toml | 1 - system/netstack/node/Cargo.toml | 1 - system/netstack/node/src/streams.rs | 4 +- system/netstack/node/tests/common/client.rs | 4 +- system/netstack/node/tests/listeners.rs | 6 +- system/netstack/node/tests/streams.rs | 6 +- system/netstack/src/lent.rs | 2 +- tests/guest/rust-tests/Cargo.lock | 5 -- 43 files changed, 214 insertions(+), 242 deletions(-) rename sdk/{transport/src => toyos/src/transport}/arena.rs (99%) rename sdk/{transport/src => toyos/src/transport}/inflight.rs (97%) rename sdk/{transport/src/lib.rs => toyos/src/transport/mod.rs} (79%) rename sdk/{transport/src => toyos/src/transport}/queue.rs (98%) rename sdk/{transport/src => toyos/src/transport}/session.rs (97%) rename sdk/{transport/src => toyos/src/transport}/stream.rs (97%) rename sdk/{transport/tests/loom.rs => toyos/tests/transport_loom.rs} (94%) delete mode 100644 sdk/transport/Cargo.toml diff --git a/Cargo.lock b/Cargo.lock index 708ed43915c..0fd0f191690 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2250,7 +2250,6 @@ dependencies = [ "toyos-net-wire", "toyos-pci-claim", "toyos-tco", - "toyos-transport", "toyos-virtio", ] @@ -4321,9 +4320,9 @@ dependencies = [ name = "toyos" version = "0.18.0" dependencies = [ + "loom", "rustc-std-workspace-core", "toyos-abi", - "toyos-transport", ] [[package]] @@ -4367,8 +4366,8 @@ version = "0.1.0" name = "toyos-blockring" version = "0.1.0" dependencies = [ + "toyos", "toyos-blockhold", - "toyos-transport", ] [[package]] @@ -4662,7 +4661,6 @@ dependencies = [ "toyos-net-tcp", "toyos-net-udp", "toyos-net-wire", - "toyos-transport", ] [[package]] @@ -4851,14 +4849,6 @@ dependencies = [ "toyos-abi", ] -[[package]] -name = "toyos-transport" -version = "0.1.0" -dependencies = [ - "loom", - "rustc-std-workspace-core", -] - [[package]] name = "toyos-tsc" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index a05fee81c99..03dd2b64972 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,7 +88,6 @@ members = [ "sdk/std/copies", "sdk/osrelease", "sdk/toyos", - "sdk/transport", "sdk/window", "system/acpiserver", "system/acpiserver/aml", diff --git a/build/build.rs b/build/build.rs index d5b4bdeb482..94170272d77 100644 --- a/build/build.rs +++ b/build/build.rs @@ -2734,6 +2734,7 @@ mod tests { "core", "default", "flaws", + "host-grant", "loom", "portable", "rustc-dep-of-std", @@ -2741,6 +2742,7 @@ mod tests { "sign", "std", "std-runtime", + "ttf", "wpa2", ]; @@ -2799,7 +2801,8 @@ mod tests { /// Every negative control the tree declares: every feature of the kernel's /// manifest but its builds and [`KERNEL_CARRIES`], and every feature of every - /// host workspace member's but [`NOT_A_CONTROL`]. + /// host workspace member's and guest library's (`hostws::GUEST_LIBRARIES`, + /// which a host tests too) but [`NOT_A_CONTROL`]. /// /// **Every manifest, and no list of the crates that hold a model.** A model /// of memory orderings, of the process table's interleavings, of a simulated @@ -2809,7 +2812,10 @@ mod tests { /// Each file's own comment beside a name carries the argument for it. fn declared_model_controls(root: &Path) -> BTreeSet { let mut out = BTreeSet::new(); - for dir in std::iter::once(crate::ci::KERNEL_DIR.to_string()).chain(crate::hostws::host_members(root)) { + let host_tested = crate::hostws::host_members(root) + .into_iter() + .chain(crate::hostws::GUEST_LIBRARIES.map(String::from)); + for dir in std::iter::once(crate::ci::KERNEL_DIR.to_string()).chain(host_tested) { let path = root.join(&dir).join("Cargo.toml"); let text = fs::read_to_string(&path) .unwrap_or_else(|e| panic!("Failed to read {}: {e}", path.display())); diff --git a/build/ci.rs b/build/ci.rs index abf46e1279a..516dd54eee9 100644 --- a/build/ci.rs +++ b/build/ci.rs @@ -450,7 +450,8 @@ pub(crate) const SDK_DIR: &str = "sdk/toyos"; const KERNEL_LOOM: &str = "kernel-loom"; const KERNEL_SIM: &str = "kernel-sim"; const BLOCKRING: &str = "toyos-blockring"; -const TRANSPORT: &str = "toyos-transport"; +/// The SDK package, whose `transport` module carries its own controls. +const SDK: &str = "toyos"; /// `toyos-crypto`, tested and linted in each of [`CRYPTO_FORMS`] rather than /// with the features the workspace's other members unify onto it. @@ -692,20 +693,20 @@ pub(crate) const CONTROLS: &[Control] = &[ red(BLOCKRING, "mutate-no-reissue-after-loss", None, &[ Fails("model::tests::what_a_flush_calls_durable_is_on_the_medium"), ]), - red(TRANSPORT, "publish-relaxed", Some("loom"), &[ + red(SDK, "transport-publish-relaxed", Some("transport_loom"), &[ Fails("a_published_entry_is_read_whole"), Fails("a_published_byte_is_read_as_written"), ]), - red(TRANSPORT, "head-relaxed", Some("loom"), &[Fails("a_published_byte_is_read_as_written")]), - red(TRANSPORT, "no-clamp", Some("loom"), &[Fails( + red(SDK, "transport-head-relaxed", Some("transport_loom"), &[Fails("a_published_byte_is_read_as_written")]), + red(SDK, "transport-no-clamp", Some("transport_loom"), &[Fails( "a_hostile_producer_yields_entries_or_a_violation", )]), - red(TRANSPORT, "no-clamp", None, &[Fails( - "stream::tests::a_hostile_producer_hands_the_consumer_at_most_the_ring", + red(SDK, "transport-no-clamp", None, &[Fails( + "transport::stream::tests::a_hostile_producer_hands_the_consumer_at_most_the_ring", )]), // The stream's lost wake: a sleeper whose exchange read the waker's clear // looks at a cursor from before it, and sleeps with nobody to ring. - red(TRANSPORT, "want-relaxed", Some("loom"), &[ + red(SDK, "transport-want-relaxed", Some("transport_loom"), &[ Fails("a_consumer_that_looked_again_is_rung_for_bytes_it_missed"), Fails("a_producer_that_looked_again_is_rung_for_room_it_missed"), Fails("two_sleepers_each_wake_when_room_is_released_first"), @@ -721,24 +722,24 @@ pub(crate) const CONTROLS: &[Control] = &[ // A session's lost wakes: a reader and a writer on one doorbell, a take // not passed on, a registration that neither arms nor rings, and a reset // a look that arms does not see. - red(TRANSPORT, "one-doorbell", Some("loom"), &[ + red(SDK, "transport-one-doorbell", Some("transport_loom"), &[ Fails("two_sleepers_each_wake_when_room_is_released_first"), Fails("two_sleepers_each_wake_when_data_is_published_first"), ]), - red(TRANSPORT, "no-pass-on", Some("loom"), &[ + red(SDK, "transport-no-pass-on", Some("transport_loom"), &[ Fails("a_poll_beside_a_blocking_read_is_answered_for_the_bytes_it_left"), Fails("a_poll_beside_a_blocking_read_is_answered_for_the_end_it_left"), Fails("a_poll_beside_a_blocking_write_is_answered_for_the_room_it_left"), ]), - red(TRANSPORT, "register-no-arm", Some("loom"), REGISTERED), - red(TRANSPORT, "register-no-ring", Some("loom"), REGISTERED), - red(TRANSPORT, "register-neither", Some("loom"), REGISTERED), - red(TRANSPORT, "head-only", Some("loom"), &[ + red(SDK, "transport-register-no-arm", Some("transport_loom"), REGISTERED), + red(SDK, "transport-register-no-ring", Some("transport_loom"), REGISTERED), + red(SDK, "transport-register-neither", Some("transport_loom"), REGISTERED), + red(SDK, "transport-head-only", Some("transport_loom"), &[ Fails("a_source_registered_over_a_full_ring_after_a_reset_gets_its_first_event"), Fails("a_source_registered_over_a_full_ring_as_a_reset_arrives_gets_its_first_event"), ]), - red(TRANSPORT, "end-keeps-inflight", None, &[Fails( - "inflight::tests::an_end_answers_every_tag_once_and_a_late_completion_nothing", + red(SDK, "transport-end-keeps-inflight", None, &[Fails( + "transport::inflight::tests::an_end_answers_every_tag_once_and_a_late_completion_nothing", )]), ]; diff --git a/build/clippy.rs b/build/clippy.rs index adaf9beefdf..68fbc749018 100644 --- a/build/clippy.rs +++ b/build/clippy.rs @@ -166,10 +166,10 @@ const SHAPES: &[Shape] = &[ before: &["-p", CRYPTO, "--all-targets"], after: &["$ADOPTED", "-D", "warnings"], }, - // `--no-deps` because its dependency `toyos` is a guest crate no shape - // lints. Its own target directory because `--no-deps` checks without clippy - // the host crates the workspace shapes lint, which `toyos-abi`'s shape - // below says costs every run. + // `--no-deps` because its dependency `toyos` is a guest crate, linted by + // the shapes that build it. Its own target directory because `--no-deps` + // checks without clippy the host crates the workspace shapes lint, which + // `toyos-abi`'s shape below says costs every run. Shape { before: &[ "-p", @@ -208,6 +208,13 @@ const SHAPES: &[Shape] = &[ ], after: &["$ADOPTED", "-D", "warnings"], }, + // The transport's loom models: the workspace shapes lint `toyos`'s library + // only as their members' dependency, and its own test targets are not + // clippy-clean on a host but this one. + Shape { + before: &["-p", "toyos", "--test", "transport_loom"], + after: &["$ADOPTED", "-D", "warnings"], + }, // Its own target directory: cargo keeps one check of a unit, so a unit // linted under two sets of lints is checked again by each, every run, and // so is every crate depending on it. diff --git a/build/hostws.rs b/build/hostws.rs index ce1b943a9c9..60a7663287a 100644 --- a/build/hostws.rs +++ b/build/hostws.rs @@ -87,7 +87,7 @@ pub(crate) fn rel(root: &Path, path: &Path) -> String { /// file-picker clients and the two shared crates that link the SDK, whose /// `toyos` is not clippy-clean on a host. Their tests run in a step of their /// own ([`guest_libraries`]). -const GUEST_LIBRARIES: [&str; 6] = [ +pub(crate) const GUEST_LIBRARIES: [&str; 6] = [ crate::ci::SDK_DIR, "sdk/window", "sdk/font", diff --git a/build/sdkversion.rs b/build/sdkversion.rs index 3c9c0a6868b..80ad33b2004 100644 --- a/build/sdkversion.rs +++ b/build/sdkversion.rs @@ -20,9 +20,11 @@ pub struct Crate { } /// The published crates, in the order a publisher must take them. +/// +/// A crate joins only once crates.io holds it with `publish.yml` its trusted +/// publisher: the token that workflow publishes with cannot create a crate. pub const PUBLISHED: &[Crate] = &[ Crate { name: "toyos-abi", dir: "sdk/abi" }, - Crate { name: "toyos-transport", dir: "sdk/transport" }, Crate { name: "toyos-keymap", dir: "sdk/keymap" }, Crate { name: "toyos-font", dir: "sdk/font" }, Crate { name: "toyos", dir: "sdk/toyos" }, diff --git a/build/sysroot.rs b/build/sysroot.rs index 6ec7b64ce54..cf29263b7a9 100644 --- a/build/sysroot.rs +++ b/build/sysroot.rs @@ -65,13 +65,12 @@ use crate::toolchain::{self, host_triple, GuestTarget, Owner, Role, GUEST_TARGET use whole_toolchain::{whole, Whole}; /// The per-worktree sources that end up inside a sysroot: std links the -/// `toyos-abi`, `toyos` and `toyos-transport` [`std_patch`] hands it and -/// compiles its ToyOS backend from `sdk/std`, and `libtoyos_c.a` is `sdk/libc` -/// with `toyos-elf` and `toyos-osrelease`. -pub const SYSROOT_SOURCES: [&str; 8] = [ +/// `toyos-abi` and `toyos` [`std_patch`] hands it and compiles its ToyOS +/// backend from `sdk/std`, and `libtoyos_c.a` is `sdk/libc` with `toyos-elf` +/// and `toyos-osrelease`. +pub const SYSROOT_SOURCES: [&str; 7] = [ "sdk/abi/src", "sdk/toyos/src", - "sdk/transport/src", "sdk/std", "lib/elf/src", "sdk/osrelease/src", @@ -81,10 +80,9 @@ pub const SYSROOT_SOURCES: [&str; 8] = [ /// Their manifests, and the lockfile and cargo configuration libc is built /// under: the features, versions and flags of the same build. -pub(crate) const SYSROOT_MANIFESTS: [&str; 8] = [ +pub(crate) const SYSROOT_MANIFESTS: [&str; 7] = [ "sdk/abi/Cargo.toml", "sdk/toyos/Cargo.toml", - "sdk/transport/Cargo.toml", "lib/elf/Cargo.toml", "sdk/osrelease/Cargo.toml", "sdk/libc/Cargo.toml", @@ -95,7 +93,7 @@ pub(crate) const SYSROOT_MANIFESTS: [&str; 8] = [ /// Of [`SYSROOT_MANIFESTS`], the crates std names by version, which std's /// lockfile resolves with the fork's own through [`std_patch`]: what of a /// worktree can move a freestanding target's dependency versions. -const STD_MANIFESTS: [&str; 3] = ["sdk/abi/Cargo.toml", "sdk/toyos/Cargo.toml", "sdk/transport/Cargo.toml"]; +const STD_MANIFESTS: [&str; 2] = ["sdk/abi/Cargo.toml", "sdk/toyos/Cargo.toml"]; /// One of the crates std names by version, in a worktree. pub(crate) struct StdCrate { @@ -1276,7 +1274,7 @@ pub(crate) mod tests { /// The manifests [`std_crates`] reads, in a worktree at `root` that has /// no other source: what a bootstrap run is handed std's patch from. pub(crate) fn std_manifests(root: &Path) { - for (manifest, name) in STD_MANIFESTS.into_iter().zip(["toyos-abi", "toyos", "toyos-transport"]) { + for (manifest, name) in STD_MANIFESTS.into_iter().zip(["toyos-abi", "toyos"]) { write(&root.join(manifest), &format!("[package]\nname = \"{name}\"\n")); } } @@ -1317,8 +1315,6 @@ pub(crate) mod tests { format!("patch.crates-io.toyos-abi.path=\"{at}/sdk/abi\""), "--config".to_string(), format!("patch.crates-io.toyos.path=\"{at}/sdk/toyos\""), - "--config".to_string(), - format!("patch.crates-io.toyos-transport.path=\"{at}/sdk/transport\""), ], ); for name in ["work tree", "work\"tree", "work\\tree", "work\ttree"] { diff --git a/build/toolchain.rs b/build/toolchain.rs index 25907e1aa84..60a7db0ce6a 100644 --- a/build/toolchain.rs +++ b/build/toolchain.rs @@ -825,9 +825,8 @@ mod tests { let registry = |name: &str, version: &str| { format!("/home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/{name}-{version}/src/lib.rs") }; - let rest = ours("sdk/transport"); let built_from = |abi: &str, toyos: &str| { - fs::write(built.join("dist/libstd.d"), format!("{}/dist/libstd.rlib: {abi} {toyos} {rest}\n", built.display())) + fs::write(built.join("dist/libstd.d"), format!("{}/dist/libstd.rlib: {abi} {toyos}\n", built.display())) .unwrap(); std::panic::catch_unwind(|| assert_std_built_from(&root, &built)) .err() diff --git a/issues/a-compile-fail-case-names-an-error-code-rustdoc-never-reads.md b/issues/a-compile-fail-case-names-an-error-code-rustdoc-never-reads.md index 1effee81e3a..890e89e56d0 100644 --- a/issues/a-compile-fail-case-names-an-error-code-rustdoc-never-reads.md +++ b/issues/a-compile-fail-case-names-an-error-code-rustdoc-never-reads.md @@ -18,7 +18,7 @@ crate's doc-tests green: | case | names | `cargo test -p --doc` under `E0308` | |---|---|---| | `toyos_bootmap::DirectMapEnd` | `E0603` | EXIT=0 | -| `toyos_transport::Place`, three blocks | `E0080` | EXIT=0 | +| `toyos::transport::Place`, three blocks | `E0080` | EXIT=0 | What does hold a case to its reason in this tree is the block beside it that compiles (`system/netstack/wire/src/lib.rs`, `mod compile_fail`). `Place`'s three diff --git a/issues/a-crate-new-to-the-published-set-reds-every-publish-until-someone-puts-it-up-by-hand.md b/issues/a-crate-new-to-the-published-set-reds-every-publish-until-someone-puts-it-up-by-hand.md index 9f35678eda2..82e8c56305a 100644 --- a/issues/a-crate-new-to-the-published-set-reds-every-publish-until-someone-puts-it-up-by-hand.md +++ b/issues/a-crate-new-to-the-published-set-reds-every-publish-until-someone-puts-it-up-by-hand.md @@ -37,13 +37,14 @@ Only an account can create a crate, and only then can it name `publish.yml` the crate's trusted publisher. Nothing before a landing tells that a crate it adds to `PUBLISHED` is not on crates.io. -Owner: the owner's crates.io account for the first versions; `build/sdkversion.rs` +Owner: the orchestrator, for the runs after landing; `build/sdkversion.rs` for the rule. -`toyos-untrusted` has since been removed from the tree and from `PUBLISHED`, -so `toyos-transport` is the one crate still owed. +Neither crate is owed any more: #965 removed `toyos-untrusted`, and the +transport is now the `toyos` SDK's `transport` module, so `PUBLISHED` names +only crates the crates.io index holds (checked 2026-10-21). Its doc comment +says a crate joins only once crates.io holds it with `publish.yml` its trusted +publisher. Nothing yet shows a green run. -**Exit**: `toyos-transport` is on crates.io, naming `publish.yml` its trusted -publisher; a `publish` run at main's tip and the next -nightly's `release` are green; and `PUBLISHED`'s doc comment says a crate joins -it only once crates.io holds it under that publisher. +**Exit**: a `publish` run at main's tip after the transport merge lands, and +the next nightly's `release`, are green. diff --git a/issues/loom-arc-panics-in-its-drop-while-a-failed-model-unwinds.md b/issues/loom-arc-panics-in-its-drop-while-a-failed-model-unwinds.md index e7eae7246fc..2070d45b302 100644 --- a/issues/loom-arc-panics-in-its-drop-while-a-failed-model-unwinds.md +++ b/issues/loom-arc-panics-in-its-drop-while-a-failed-model-unwinds.md @@ -25,7 +25,8 @@ a_consumer_that_looked_again_is_rung_for_bytes_it_missed --exact` kills the test binary with SIGABRT, `panic in a destructor during cleanup`, through ` as Drop>::drop` and `rt::arc::Arc::ref_dec`. On std's `Arc` the same run prints the test's `FAILED` line and loom's -`deadlock; threads = ...`. +`deadlock; threads = ...`. That model is now `sdk/toyos/tests/transport_loom.rs`, +its control `transport-want-relaxed` of `toyos`. **Owner**: the orchestrator. Nobody holds it. diff --git a/issues/netstack-moves-every-byte-through-two-kernel-pipes.md b/issues/netstack-moves-every-byte-through-two-kernel-pipes.md index cfd14216169..495d571287b 100644 --- a/issues/netstack-moves-every-byte-through-two-kernel-pipes.md +++ b/issues/netstack-moves-every-byte-through-two-kernel-pipes.md @@ -52,7 +52,7 @@ The design and its roast are PR #863's body. `DeviceMemory`, and a receiver judges a lent region through `fstat` before it maps it. - Stage 2, done (PR #878): a byte ring with untrusted cursors and want words - in `toyos-transport` (`sdk/transport`), host-tested and modelled + in the SDK's `toyos::transport` (`sdk/toyos/src/transport`), host-tested and modelled in loom. - Stage 3, done (PR #905): a TCP stream, connected or accepted, is one region whose two rings are [tcp]'s buffers and the connection it was opened @@ -112,7 +112,7 @@ The design and its roast are PR #863's body. over a full send ring, each answers a refusal only netstack judges that lands meanwhile; each is red when the look reads `pending` before it arms, red when netstack exchanges the wants before it stores `pending`, and red - under `want-relaxed`, and the sender's is red when netstack rings only + under `transport-want-relaxed`, and the sender's is red when netstack rings only `rx_data`. In the other, [udp]'s queue starts full and a datagram leaves it as its own step, interleaved with netstack's looks, so netstack can find a published record while the queue is full and hold it; a sender that @@ -120,7 +120,7 @@ The design and its roast are PR #863's body. every record sent, in order, none refused. It is red when netstack refuses a record at the full queue, red when it rings `tx_room` on the connection, red when after the leave it waits for the client's next ring without - looking at the send ring again, and red under `want-relaxed`. + looking at the send ring again, and red under `transport-want-relaxed`. Owner: the orchestrator, who stages it. diff --git a/issues/the-transport-heads-orderings-have-no-oracle.md b/issues/the-transport-heads-orderings-have-no-oracle.md index 0bd386bd3b2..87bee5c4bd9 100644 --- a/issues/the-transport-heads-orderings-have-no-oracle.md +++ b/issues/the-transport-heads-orderings-have-no-oracle.md @@ -8,11 +8,11 @@ opened: 2026-09-27 A consumer stores its head `Release` after it has loaded the entries below it, and a producer loads the head `Acquire` before it writes over them -(`sdk/transport/src/queue.rs`, `Consumer::release` and `Producer::space`). +(`sdk/toyos/src/transport/queue.rs`, `Consumer::release` and `Producer::space`). No test reds if either is `Relaxed`: what the pair forbids is load buffering — a consumer's load of an entry reading the producer's later overwrite — which loom does not model, and every other test runs both ends on one thread. The -tail's edge has its control (`publish-relaxed`); the head's has none. +tail's edge has its control (`transport-publish-relaxed`); the head's has none. **Exit condition.** A control that relaxes the head's two orderings, and a model or a run on a weakly ordered CPU that goes red under it. diff --git a/issues/there-is-no-wifi.md b/issues/there-is-no-wifi.md index e81279f9410..be9ef18c6d7 100644 --- a/issues/there-is-no-wifi.md +++ b/issues/there-is-no-wifi.md @@ -110,7 +110,7 @@ and the ACPI read-out in `s1-r2/` alone. **S2, the link hop's cost on the T14.** A scout, never landing: two -processes over `toyos-transport`, one entry per 1,514-byte frame, batches of +processes over `toyos::transport`, one entry per 1,514-byte frame, batches of 1, 8 and 32, both directions, each side copying each frame once. Owner: the orchestrator. Depends on: nothing. Exit: cycles per frame and frames a second on one CPU, reported in P4's design round. Beside them stands the @@ -181,7 +181,7 @@ stage 3 of `issues/the-lan-is-not-yet-production-grade.md`, whole. - **Exit:** that stage's exit, a driver killed and restarted with the stack's connections intact (held in a guest) and an unlisted but matching NIC up with no configuration change; and with it: - - the `link` protocol on `toyos-transport`, adding no transport primitive; + - the `link` protocol on `toyos::transport`, adding no transport primitive; - `Card` gone; - the supervisor binding drivers from a declared match table by vendor, device and class; diff --git a/lib/blockring/Cargo.toml b/lib/blockring/Cargo.toml index f0f65fa972c..47a9b5efbdb 100644 --- a/lib/blockring/Cargo.toml +++ b/lib/blockring/Cargo.toml @@ -1,6 +1,6 @@ # A member of the host workspace (root `Cargo.toml`). What lives here is the # block protocol between a block service and its client — the shared session -# page's layout, where its two `toyos-transport` rings are, the words a request +# page's layout, where its two `toyos::transport` rings are, the words a request # and a completion are, the control frames a session is opened with, and every # decision either end makes about what a completion means — with nothing that # touches a device, a handle or a mapping. `system/diskserver` serves it and its @@ -9,7 +9,7 @@ # Its defects are orders — a completion racing a crash, a flush racing a reset, # a reconnect racing a reissue — so `src/model.rs` enumerates every ordering of # a scripted client against a server, a device and a crash; the rings' -# publication is `toyos-transport`'s, and checked under loom there. +# publication is `toyos::transport`'s, and checked under loom there. [package] name = "toyos-blockring" @@ -39,8 +39,8 @@ mutate-no-reissue-after-loss = [] # the server half's bookkeeping, decided where the kernel's block layer decides # it today. toyos-blockhold = { path = "../blockhold" } -# The rings on the session page. -toyos-transport = { path = "../../sdk/transport" } +# The rings on the session page: `toyos::transport`. +toyos = { path = "../../sdk/toyos" } [lints.rust] warnings = "deny" diff --git a/lib/blockring/src/client.rs b/lib/blockring/src/client.rs index 73c0485f2a1..8d65fec4894 100644 --- a/lib/blockring/src/client.rs +++ b/lib/blockring/src/client.rs @@ -36,7 +36,7 @@ use alloc::collections::{BTreeMap, VecDeque}; use alloc::vec::Vec; -use toyos_transport::{Inflight, Run, Violation}; +use toyos::transport::{Inflight, Run, Violation}; use crate::entry::{Completion, Op, Request, Status}; use crate::layout::DEPTH; diff --git a/lib/blockring/src/entry.rs b/lib/blockring/src/entry.rs index af9ee697dc1..67d29627b45 100644 --- a/lib/blockring/src/entry.rs +++ b/lib/blockring/src/entry.rs @@ -4,7 +4,7 @@ //! request is bounded here against the arena and the partition, and a word //! this protocol does not define is a refusal, never a default. -use toyos_transport::Run; +use toyos::transport::Run; use crate::layout::{ARENA, CQE_WORDS, MAX_REQUEST_BLOCKS, SQE_WORDS}; diff --git a/lib/blockring/src/layout.rs b/lib/blockring/src/layout.rs index 56f65d70163..97e65bd8c64 100644 --- a/lib/blockring/src/layout.rs +++ b/lib/blockring/src/layout.rs @@ -3,7 +3,7 @@ //! The four ring indices sit on cache lines of their own, so the client's //! stores to its two and the server's to its two never share a line. -use toyos_transport::{Consumer, Geometry, Place, Producer, Word}; +use toyos::transport::{Consumer, Geometry, Place, Producer, Word}; /// A session's whole region: the one size shared memory comes in. pub const SESSION_BYTES: usize = Geometry::BYTES as usize; diff --git a/lib/blockring/src/lib.rs b/lib/blockring/src/lib.rs index 6b2beeab035..d307a65aa69 100644 --- a/lib/blockring/src/lib.rs +++ b/lib/blockring/src/lib.rs @@ -28,9 +28,9 @@ //! **Requests in flight at once are unordered**, as on the device: a client //! that needs one to follow another waits for the first's answer. //! -//! Pure: `alloc`, `toyos-blockhold` and `toyos-transport`, no `unsafe`. The +//! Pure: `alloc`, `toyos-blockhold` and `toyos::transport`, no `unsafe`. The //! ends that map the page — `system/diskserver` and its client — hand it the -//! page as words ([`toyos_transport::Word`]) and act on what it answers. +//! page as words ([`toyos::transport::Word`]) and act on what it answers. #![cfg_attr(not(test), no_std)] #![forbid(unsafe_code)] @@ -47,7 +47,7 @@ pub mod wire; mod model; pub use entry::{Completion, Op, Request, Status}; -pub use toyos_transport::Run; +pub use toyos::transport::Run; pub use layout::{BLOCK_BYTES, DEPTH, MAX_REQUEST_BLOCKS, SESSION_BYTES}; /// The name a block service is served under. A connection opens only what its diff --git a/lib/blockring/src/model.rs b/lib/blockring/src/model.rs index 3f431ee1daa..1553703623a 100644 --- a/lib/blockring/src/model.rs +++ b/lib/blockring/src/model.rs @@ -35,7 +35,7 @@ use core::sync::atomic::Ordering; use std::collections::HashSet; use toyos_blockhold::Holds; -use toyos_transport::{Consumer, Place, Producer, Violation, Word}; +use toyos::transport::{Consumer, Place, Producer, Violation, Word}; use crate::client::{Client, Outcome, Ticket, MAX_ATTEMPTS}; use crate::entry::{Completion, Op, Request}; diff --git a/lib/blockring/src/wire.rs b/lib/blockring/src/wire.rs index 0092c1c02f1..cae87dc3ffe 100644 --- a/lib/blockring/src/wire.rs +++ b/lib/blockring/src/wire.rs @@ -18,7 +18,7 @@ //! server's ends and its answer together: nothing else makes the ends, and an //! answer is otherwise only read off the wire ([`Opened::decode`]). -use toyos_transport::Word; +use toyos::transport::Word; use crate::layout::{self, ServerRings, RING_WORDS}; diff --git a/rust b/rust index e1c5e93d342..11e31a52778 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit e1c5e93d34236ee3e57d510920f94c0256c647eb +Subproject commit 11e31a52778f875f3e021db96d35a45fb0f22466 diff --git a/sdk/libc/Cargo.lock b/sdk/libc/Cargo.lock index f3b061534dd..2c169500537 100644 --- a/sdk/libc/Cargo.lock +++ b/sdk/libc/Cargo.lock @@ -30,7 +30,6 @@ name = "toyos" version = "0.18.0" dependencies = [ "toyos-abi", - "toyos-transport", ] [[package]] @@ -56,10 +55,6 @@ dependencies = [ name = "toyos-osrelease" version = "0.1.0" -[[package]] -name = "toyos-transport" -version = "0.1.0" - [[package]] name = "windows-link" version = "0.2.1" diff --git a/sdk/toyos/Cargo.toml b/sdk/toyos/Cargo.toml index ca94156bad5..54256318da2 100644 --- a/sdk/toyos/Cargo.toml +++ b/sdk/toyos/Cargo.toml @@ -3,11 +3,11 @@ name = "toyos" version = "0.18.0" # never bumped; crates.io's is assigned on publish (build/sdkversion.rs) edition = "2021" license = "MIT OR Apache-2.0" -description = "The ToyOS userland SDK: typed handles, IPC, ports, namespaces, surfaces and net." +description = "The ToyOS userland SDK: typed handles, IPC, ports, namespaces, surfaces, net and the transport its sessions run over." repository = "https://github.com/ToyOSOrg/ToyOS" [features] -rustc-dep-of-std = ["core", "toyos-abi/rustc-dep-of-std", "toyos-transport/rustc-dep-of-std"] +rustc-dep-of-std = ["core", "toyos-abi/rustc-dep-of-std"] # The negative control for the log ring's publication. It makes the store that # publishes a record `Relaxed`, and `kernel-loom`'s `log_ring` model must red: # @@ -21,6 +21,49 @@ log-ring-publish-relaxed = [] # swapped. log-ring-tail-relaxed = [] log-ring-loads-swapped = [] +# The transport's controls (`src/transport`), declared, never enabled by any +# build that ships: each reverts one decision so the model that refuses it is +# shown able to red at all. `build/ci.rs`'s `CONTROLS` runs each and demands +# the named test's own FAILED line; `tests/transport_loom.rs` holds the +# publication edge, the wake handshake, a hostile peer and a session's three +# waits. +# +# A producer publishes its tail `Relaxed`, so a consumer can see the index +# before the entry's words, or a stream's tail before its bytes. +transport-publish-relaxed = [] +# A stream's consumer stores its head `Relaxed` and its producer loads it +# `Relaxed`, so the producer can copy into a byte the consumer is still +# copying out. +transport-head-relaxed = [] +# A peer's cursor is believed however far it claims to be, so a hostile +# producer hands the consumer more entries, or bytes, than the ring holds. +transport-no-clamp = [] +# A stream's waker clears the peer's want `Relaxed`, so a sleeper whose +# exchange reads the clear need not see the cursor stored before it, and +# sleeps over bytes or room nobody rings for. +transport-want-relaxed = [] +# `Inflight::end` answers nothing and keeps every tag in flight, so a session's +# requests outlive it unanswered and a late completion answers one. +transport-end-keeps-inflight = [] +# A session's server rings a writer waiting for room on the connection, the +# doorbell a reader waits on, so either can take the other's wake. +transport-one-doorbell = [] +# A thread that took a direction's doorbell leaves it with another waiter +# counted and passes nothing on, so that waiter sleeps over what the take +# announced. +transport-no-pass-on = [] +# A registration looks without arming, so a direction that becomes ready after +# its look rings nobody. +transport-register-no-arm = [] +# A registration arms and looks but rings nobody for a direction it found +# ready, so its first event never comes. +transport-register-no-ring = [] +# Both of the two above. +transport-register-neither = ["transport-register-no-arm", "transport-register-no-ring"] +# A look that arms the send direction, and the server's ring back of it, read +# only the room and not a failure, so a writer over a full ring sleeps through +# a reset. +transport-head-only = [] [lints.rust] # The guest's target: its stream sinks are compiled only for it. @@ -29,4 +72,6 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("toyos") [dependencies] core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } toyos-abi = { path = "../abi", default-features = false } -toyos-transport = { path = "../transport" } + +[dev-dependencies] +loom = "0.7" diff --git a/sdk/toyos/src/lib.rs b/sdk/toyos/src/lib.rs index 785701781e9..3166a3a3d0b 100644 --- a/sdk/toyos/src/lib.rs +++ b/sdk/toyos/src/lib.rs @@ -1,7 +1,8 @@ //! ToyOS userland SDK. //! //! Typed handles, IPC framing, ports and namespaces, shared memory, and -//! ergonomic wrappers over the kernel ABI defined in `toyos-abi`. +//! ergonomic wrappers over the kernel ABI defined in `toyos-abi`, and the +//! [`transport`] client/server sessions run over. // `not(test)` so this crate's own decisions can be unit-tested on the host. // [`net::hangup`] is a total function from a kernel word to a [`net::NetError`] @@ -33,6 +34,7 @@ pub mod spawn; pub mod syscap; pub mod sync; pub mod system; +pub mod transport; pub mod volatile; pub use ipc::Connection; diff --git a/sdk/toyos/src/net/stream.rs b/sdk/toyos/src/net/stream.rs index 2ee3c2fbe4b..be1129cf542 100644 --- a/sdk/toyos/src/net/stream.rs +++ b/sdk/toyos/src/net/stream.rs @@ -26,18 +26,18 @@ use core::sync::atomic::{AtomicU32, Ordering}; use toyos_abi::syscall::{self, SyscallError}; use toyos_abi::RawHandle; -use toyos_transport::session::{self, Bells, Doorbell, Layout, Mode, Polled, Receiving, Refused as Answer, Sending, Took, Waited}; -use toyos_transport::stream::Place; -use toyos_transport::Span; use crate::ipc::Connection; use crate::shm::SharedMemory; use crate::sync::Lock; +use crate::transport::session::{self, Bells, Doorbell, Layout, Mode, Polled, Receiving, Refused as Answer, Sending, Took, Waited}; +use crate::transport::stream::Place; +use crate::transport::Span; use crate::OwnedHandle; use super::{MsgType, NetError, NetstackConn, TcpAcceptRequest, TcpAcceptResponse, TcpConnectRequest, TcpConnectResponse, TcpSocketId}; -pub use toyos_transport::session::Way; +pub use crate::transport::session::Way; // ---- the region ---- diff --git a/sdk/transport/src/arena.rs b/sdk/toyos/src/transport/arena.rs similarity index 99% rename from sdk/transport/src/arena.rs rename to sdk/toyos/src/transport/arena.rs index 63686e3247a..d76e9a6b260 100644 --- a/sdk/transport/src/arena.rs +++ b/sdk/toyos/src/transport/arena.rs @@ -6,7 +6,7 @@ use core::fmt; -use crate::Violation; +use super::Violation; /// Bytes `offset..offset + len` of the region. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] diff --git a/sdk/transport/src/inflight.rs b/sdk/toyos/src/transport/inflight.rs similarity index 97% rename from sdk/transport/src/inflight.rs rename to sdk/toyos/src/transport/inflight.rs index b692dce6097..1f1042009fe 100644 --- a/sdk/transport/src/inflight.rs +++ b/sdk/toyos/src/transport/inflight.rs @@ -12,7 +12,7 @@ use core::fmt; -use crate::Violation; +use super::Violation; #[derive(Clone, PartialEq, Eq, Hash)] struct Slot { @@ -76,9 +76,9 @@ impl Inflight { /// it carried, and none of them is answered again. pub fn end(&mut self, mut each: impl FnMut(u32, T)) { for (index, slot) in (0u32..).zip(self.slots.iter_mut()) { - #[cfg(not(feature = "end-keeps-inflight"))] + #[cfg(not(feature = "transport-end-keeps-inflight"))] let value = slot.value.take(); - #[cfg(feature = "end-keeps-inflight")] + #[cfg(feature = "transport-end-keeps-inflight")] let value = None; if let Some(value) = value { each(Self::tag(slot.seq, index), value); diff --git a/sdk/transport/src/lib.rs b/sdk/toyos/src/transport/mod.rs similarity index 79% rename from sdk/transport/src/lib.rs rename to sdk/toyos/src/transport/mod.rs index 7ba61e6677e..af54c8a1622 100644 --- a/sdk/transport/src/lib.rs +++ b/sdk/toyos/src/transport/mod.rs @@ -5,24 +5,24 @@ //! [`Producer`]/[`Consumer`] queues of fixed-size entries and an arena of //! [`Run`]s, or byte [`stream`]s and the wants that say when to ring, two of //! which with their `end`s are a duplex [`session`]. A protocol says what the -//! entries and bytes mean; this crate says only what is safe. +//! entries and bytes mean; this module says only what is safe. //! -//! **Nothing here holds the region.** An adapter hands every call the `N` -//! [`Word`]s an end was made over, and copies bytes itself, through a run's -//! [`Span`], once: no reference to the peer's bytes is formed. +//! **Nothing here holds the region or makes a syscall.** An adapter, such as +//! [`crate::net::stream`], hands every call the `N` [`Word`]s an end was made +//! over, and copies bytes itself, through a run's [`Span`], once: no reference +//! to the peer's bytes is formed. //! //! **What the peer writes is untrusted until decoded.** An entry comes out as -//! the peer's words, for the protocol's decoder to bound; a peer's cursor is bounded against the ring before it -//! is believed, and the variant of [`Violation`] names what it claimed; a run -//! is bounded against the [`Geometry`], and a tag against the [`Inflight`] -//! table. An end keeps its own cursor locally and only stores the shared one, +//! the peer's words, for the protocol's decoder to bound; a peer's cursor is +//! bounded against the ring before it is believed, and the variant of +//! [`Violation`] names what it claimed; a run is bounded against the +//! [`Geometry`], and a tag against the [`Inflight`] table. An end keeps its own cursor locally and only stores the shared one, //! so nothing the peer writes moves it, and a cursor the peer moves backwards //! within bounds costs only the peer. //! //! **A restart is seen only as a hang-up**, and [`Inflight::end`] answers every //! tag that was in flight, once; a tag from before it answers nothing. -#![cfg_attr(not(test), no_std)] #![forbid(unsafe_code)] #![cfg_attr(not(test), forbid(clippy::arithmetic_side_effects, clippy::unwrap_used, clippy::expect_used, clippy::panic))] #![cfg_attr(not(test), deny(clippy::indexing_slicing, clippy::as_conversions))] @@ -60,9 +60,9 @@ impl Word for AtomicU32 { } /// How an end stores the cursor that hands what it wrote to the peer. -#[cfg(not(feature = "publish-relaxed"))] +#[cfg(not(feature = "transport-publish-relaxed"))] const PUBLISH: Ordering = Ordering::Release; -#[cfg(feature = "publish-relaxed")] +#[cfg(feature = "transport-publish-relaxed")] const PUBLISH: Ordering = Ordering::Relaxed; /// Word `at` of an end's words, and the one index into them: every `at` an end @@ -75,7 +75,7 @@ fn word(page: &[W; N], at: usize) -> &W { /// A distance the peer's cursor claims, believed only up to `cap`. fn clamp(claimed: u32, cap: u32, broken: Violation) -> Result { - let cap = if cfg!(feature = "no-clamp") { u32::MAX } else { cap }; + let cap = if cfg!(feature = "transport-no-clamp") { u32::MAX } else { cap }; if claimed > cap { Err(broken) } else { Ok(claimed) } } diff --git a/sdk/transport/src/queue.rs b/sdk/toyos/src/transport/queue.rs similarity index 98% rename from sdk/transport/src/queue.rs rename to sdk/toyos/src/transport/queue.rs index a9b3afed68a..3bfda212b8c 100644 --- a/sdk/transport/src/queue.rs +++ b/sdk/toyos/src/transport/queue.rs @@ -8,31 +8,31 @@ use core::sync::atomic::Ordering; -use crate::{clamp, word, Violation, Word, PUBLISH}; +use super::{clamp, word, Violation, Word, PUBLISH}; /// Where a queue of `E`-word entries, `D` deep, is among `N` words: the word /// its consumer stores its head in, the word its producer stores its tail in, /// and its first entry. /// /// ``` -/// use toyos_transport::Place; +/// use toyos::transport::Place; /// const QUEUE: Place<2, 4, 10> = Place::new::<0, 1, 2>(); /// ``` /// /// A place with a word at `N` or past it does not compile: /// /// ```compile_fail,E0080 -/// use toyos_transport::Place; +/// use toyos::transport::Place; /// const QUEUE: Place<2, 4, 10> = Place::new::<0, 1, 3>(); /// ``` /// /// ```compile_fail,E0080 -/// use toyos_transport::Place; +/// use toyos::transport::Place; /// const QUEUE: Place<2, 4, 10> = Place::new::<10, 1, 2>(); /// ``` /// /// ```compile_fail,E0080 -/// use toyos_transport::Place; +/// use toyos::transport::Place; /// const QUEUE: Place<2, 4, 10> = Place::new::<0, 10, 2>(); /// ``` #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] diff --git a/sdk/transport/src/session.rs b/sdk/toyos/src/transport/session.rs similarity index 97% rename from sdk/transport/src/session.rs rename to sdk/toyos/src/transport/session.rs index 99a64e0bac6..f717d57af3f 100644 --- a/sdk/transport/src/session.rs +++ b/sdk/toyos/src/transport/session.rs @@ -1,5 +1,6 @@ -//! A duplex byte stream between a client and a server: two [`stream`] rings -//! and two `end` words among `N` words, and two doorbells the server rings. +//! A duplex byte stream between a client and a server: two +//! [`stream`](super::stream) rings and two `end` words among `N` words, and +//! two doorbells the server rings. //! //! **Nothing here is any protocol's.** The receive ring carries the server's //! bytes to the client and the send ring the client's to the server. The @@ -32,8 +33,8 @@ use core::sync::atomic::Ordering; -use crate::stream::{Consumer, Place, Producer, WAKE}; -use crate::{word, Span, Violation, Word}; +use super::stream::{Consumer, Place, Producer, WAKE}; +use super::{word, Span, Violation, Word}; /// An `end` while its ring runs. pub const OPEN: u32 = 0; @@ -67,7 +68,7 @@ pub enum Doorbell { pub const fn doorbell(way: Way) -> Doorbell { match way { Way::Receive => Doorbell::Connection, - Way::Send if cfg!(feature = "one-doorbell") => Doorbell::Connection, + Way::Send if cfg!(feature = "transport-one-doorbell") => Doorbell::Connection, Way::Send => Doorbell::Bell, } } @@ -336,7 +337,7 @@ impl Half for Sending { fn arm(&mut self, page: &[W; N]) -> Result, Violation> { let room = self.ring.arm(page)?; - Ok(self.seen(page, room, !cfg!(feature = "head-only"))) + Ok(self.seen(page, room, !cfg!(feature = "transport-head-only"))) } } @@ -364,7 +365,7 @@ fn leave, W: Word>(half: &mut H, page: &[W; N], count let waiters = half.waiters(); *waiters = waiters.saturating_sub(1); } - let pass_on = !cfg!(feature = "no-pass-on") && took && *half.waiters() > 0; + let pass_on = !cfg!(feature = "transport-no-pass-on") && took && *half.waiters() > 0; pass_on && matches!(half.arm(page), Ok(Some(_))) } @@ -587,7 +588,7 @@ where /// What a registration found of one half. fn registered, W: Word>(half: &mut H, page: &[W; N]) -> Result { - let seen = if cfg!(feature = "register-no-arm") { half.look(page)? } else { half.arm(page)? }; + let seen = if cfg!(feature = "transport-register-no-arm") { half.look(page)? } else { half.arm(page)? }; Ok(seen.is_some()) } @@ -613,7 +614,7 @@ where if let Some(lock) = send { ready |= lock.with(|half| registered(half, page))?; } - if ready && !cfg!(feature = "register-no-ring") { + if ready && !cfg!(feature = "transport-register-no-ring") { bells.ring(); } Ok(()) @@ -732,7 +733,7 @@ impl Server { /// for 0, and the doorbells of those that were set. pub fn rung(&mut self, page: &[W; N]) -> Result { let receive = self.rx.ring_back(page, self.ended != OPEN)?; - let send = self.tx.ring_back(page, fatal(self.ended) && !cfg!(feature = "head-only"))?; + let send = self.tx.ring_back(page, fatal(self.ended) && !cfg!(feature = "transport-head-only"))?; Ok(Rings::of(Way::Receive, receive).and(Rings::of(Way::Send, send))) } } diff --git a/sdk/transport/src/stream.rs b/sdk/toyos/src/transport/stream.rs similarity index 97% rename from sdk/transport/src/stream.rs rename to sdk/toyos/src/transport/stream.rs index 193a2b09ac0..50d9b554093 100644 --- a/sdk/transport/src/stream.rs +++ b/sdk/toyos/src/transport/stream.rs @@ -29,19 +29,19 @@ use core::sync::atomic::Ordering; -use crate::{clamp, word, Span, Violation, Word, PUBLISH}; +use super::{clamp, word, Span, Violation, Word, PUBLISH}; /// A sleeper's exchange: what the waker published before clearing the want is /// seen by the look that follows. const ARM: Ordering = Ordering::Acquire; -#[cfg(not(feature = "want-relaxed"))] -pub(crate) const WAKE: Ordering = Ordering::Release; -#[cfg(feature = "want-relaxed")] -pub(crate) const WAKE: Ordering = Ordering::Relaxed; +#[cfg(not(feature = "transport-want-relaxed"))] +pub(super) const WAKE: Ordering = Ordering::Release; +#[cfg(feature = "transport-want-relaxed")] +pub(super) const WAKE: Ordering = Ordering::Relaxed; /// The head's edge: a producer that loads the head copies into a byte only /// after the consumer's copy out of it, which the consumer's store carries. -const GIVE_BACK: Ordering = if cfg!(feature = "head-relaxed") { Ordering::Relaxed } else { Ordering::Release }; -const TAKE_BACK: Ordering = if cfg!(feature = "head-relaxed") { Ordering::Relaxed } else { Ordering::Acquire }; +const GIVE_BACK: Ordering = if cfg!(feature = "transport-head-relaxed") { Ordering::Relaxed } else { Ordering::Release }; +const TAKE_BACK: Ordering = if cfg!(feature = "transport-head-relaxed") { Ordering::Relaxed } else { Ordering::Acquire }; /// `n` as an offset into the region; `Place::new` holds `usize` to every `u32`. #[allow(clippy::as_conversions)] @@ -53,14 +53,14 @@ const fn bytes(n: u32) -> usize { /// of its first byte. /// /// ``` -/// use toyos_transport::stream::Place; +/// use toyos::transport::stream::Place; /// const RING: Place<4096, 64> = Place::new::<0, 16, 32, 48, 4096>(); /// ``` /// /// A place with a word at `N` or past it does not compile: /// /// ```compile_fail,E0080 -/// use toyos_transport::stream::Place; +/// use toyos::transport::stream::Place; /// const RING: Place<4096, 64> = Place::new::<0, 16, 32, 64, 4096>(); /// ``` #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -94,7 +94,7 @@ impl Place { } /// Its four words: head, tail and the two wants. - pub(crate) const fn words(&self) -> [usize; 4] { + pub(super) const fn words(&self) -> [usize; 4] { [self.head, self.tail, self.data, self.room] } diff --git a/sdk/transport/tests/loom.rs b/sdk/toyos/tests/transport_loom.rs similarity index 94% rename from sdk/transport/tests/loom.rs rename to sdk/toyos/tests/transport_loom.rs index b898f11f0ba..3cb90967482 100644 --- a/sdk/transport/tests/loom.rs +++ b/sdk/toyos/tests/transport_loom.rs @@ -2,16 +2,16 @@ //! runs both ends on one thread can reach. //! //! - **Publication**: a consumer that sees a tail sees every word of the -//! entries below it. `publish-relaxed` takes the edge away. +//! entries below it. `transport-publish-relaxed` takes the edge away. //! - **A hostile peer** leaves the honest end with entries, nothing, or a -//! named violation, and never more entries than the ring holds. `no-clamp` -//! believes the peer. +//! named violation, and never more entries than the ring holds. +//! `transport-no-clamp` believes the peer. //! - **A session's three waits**, each over `session`'s own sequences: a //! reader and a writer asleep at once, a poll beside a blocking call of one //! direction, and a source registered while its direction is ready. Each //! case names the controls that red it. //! -//! cargo test -p toyos-transport --features --test loom +//! cargo test -p toyos --features --test transport_loom use core::sync::atomic::Ordering; use std::rc::Rc; @@ -19,7 +19,7 @@ use std::rc::Rc; use loom::cell::Cell; use loom::sync::atomic::AtomicU32; use loom::sync::{Arc, Notify}; -use toyos_transport::{stream, Consumer, Place, Producer, Violation, Word}; +use toyos::transport::{stream, Consumer, Place, Producer, Violation, Word}; /// A loom atomic as a region word: the trait is this crate's and the type is /// loom's, so the two meet through a wrapper. @@ -207,7 +207,7 @@ fn receive(s: &Stream, rx: &mut stream::Consumer) -> u32 { /// A consumer that polls reads each byte as the producer wrote it, through a /// ring that wraps under it: its copy out follows the producer's copy in, and /// the producer's next copy into that byte follows its copy out. -/// `publish-relaxed` takes the first edge away. +/// `transport-publish-relaxed` takes the first edge away. #[test] fn a_published_byte_is_read_as_written() { loom::model(|| { @@ -234,8 +234,9 @@ fn a_published_byte_is_read_as_written() { } /// A consumer sleeps whenever the look after arming finds the ring empty, and -/// the byte published around its sleep still reaches it. `want-relaxed` lets -/// it miss the tail stored before the want it read cleared. +/// the byte published around its sleep still reaches it. +/// `transport-want-relaxed` lets it miss the tail stored before the want it +/// read cleared. #[test] fn a_consumer_that_looked_again_is_rung_for_bytes_it_missed() { loom::model(|| { @@ -253,8 +254,9 @@ fn a_consumer_that_looked_again_is_rung_for_bytes_it_missed() { } /// A producer sleeps whenever the look after arming finds the ring full, and -/// the room released around its sleep still reaches it. `want-relaxed` lets -/// it miss the head stored before the want it read cleared. +/// the room released around its sleep still reaches it. +/// `transport-want-relaxed` lets it miss the head stored before the want it +/// read cleared. #[test] fn a_producer_that_looked_again_is_rung_for_room_it_missed() { loom::model(|| { @@ -289,7 +291,7 @@ fn a_producer_that_looked_again_is_rung_for_room_it_missed() { use loom::sync::atomic::AtomicBool; use loom::sync::{Condvar, Mutex}; -use toyos_transport::session::{ +use toyos::transport::session::{ self, Bells, Doorbell, Layout, Lock, Mode, Polled, Receiving, Refused, Rings, Sending, Server, Took, Waited, Way, }; @@ -527,8 +529,8 @@ enum First { /// A reader asleep over an empty receive ring and a writer asleep over a full /// send ring, while the server releases room and publishes data in either /// order: each wakes, as each waits on a doorbell of its own. -/// `one-doorbell` lets the reader take the writer's wake, or the writer the -/// reader's. +/// `transport-one-doorbell` lets the reader take the writer's wake, or the +/// writer the reader's. fn two_sleepers(first: First) { bounded(move || { let (s, mut server) = Session::new(); @@ -579,9 +581,10 @@ enum Left { } /// A blocking call and a `poll` of one direction, the server making the -/// direction ready once and then answering each ring: the poll is answered -/// with the direction ready, whichever of them took the doorbell. -/// `no-pass-on` lets the blocking call take the wake the poll sleeps over. +/// direction ready once and then answering each ring: the poll is answered with +/// the direction ready, whichever of them took the doorbell. +/// `transport-no-pass-on` lets the blocking call take the wake the poll sleeps +/// over. fn same_direction(left: Left) { bounded(move || { let (s, mut server) = Session::new(); @@ -661,13 +664,13 @@ enum Ready { } /// A source registered while its direction is ready, or racing the server -/// making it so, gets its first event: its doorbell is watched, as mio's -/// select watches it, and each event leads to the nonblocking operation, -/// until that finds the direction ready. `register-no-arm`, -/// `register-no-ring` and `register-neither` take the registration's arm or -/// ring or both away; `want-relaxed` lets a racing server's clear go unseen; -/// `head-only` makes the reset no readiness to the arm's look or the ring -/// back. +/// making it so, gets its first event: its doorbell is watched, as mio's select +/// watches it, and each event leads to the nonblocking operation, until that +/// finds the direction ready. `transport-register-no-arm`, +/// `transport-register-no-ring` and `transport-register-neither` take the +/// registration's arm or ring or both away; `transport-want-relaxed` lets a +/// racing server's clear go unseen; `transport-head-only` makes the reset no +/// readiness to the arm's look or the ring back. fn registered(ready: Ready, racing: bool) { bounded(move || { let (s, mut server) = Session::new(); diff --git a/sdk/transport/Cargo.toml b/sdk/transport/Cargo.toml deleted file mode 100644 index 8bfca088cb6..00000000000 --- a/sdk/transport/Cargo.toml +++ /dev/null @@ -1,69 +0,0 @@ -# A member of the host workspace (root `Cargo.toml`). The one transport every -# client/server session runs over: the rings, the byte streams and their wants, -# the arena's runs and the tag table, as decisions over words an adapter hands -# in. Nothing here maps, copies or blocks. -# -# Its defects are orders, lost wakes and hostile peers, so `tests/loom.rs` -# holds the publication edge, the wake handshake, a hostile peer and a -# session's three waits. - -[package] -name = "toyos-transport" -version = "0.1.0" # never bumped; crates.io's is assigned on publish (build/sdkversion.rs) -edition = "2021" -description = "The transport every client/server session runs over: entry rings, byte streams, sessions and their wakes, an arena of runs and a tag table, decided over words an adapter hands in." -license = "MIT OR Apache-2.0" -repository = "https://github.com/ToyOSOrg/ToyOS" - -[features] -# std links it through `toyos`, whose stream end is a session's client. -rustc-dep-of-std = ["core"] -# Declared, never enabled by any build that ships: each reverts one decision so -# the model that refuses it is shown able to red at all. `build/ci.rs`'s -# `CONTROLS` runs each and demands the named test's own FAILED line. -# -# A producer publishes its tail `Relaxed`, so a consumer can see the index -# before the entry's words, or a stream's tail before its bytes. -publish-relaxed = [] -# A stream's consumer stores its head `Relaxed` and its producer loads it -# `Relaxed`, so the producer can copy into a byte the consumer is still -# copying out. -head-relaxed = [] -# A peer's cursor is believed however far it claims to be, so a hostile -# producer hands the consumer more entries, or bytes, than the ring holds. -no-clamp = [] -# A stream's waker clears the peer's want `Relaxed`, so a sleeper whose -# exchange reads the clear need not see the cursor stored before it, and -# sleeps over bytes or room nobody rings for. -want-relaxed = [] -# `Inflight::end` answers nothing and keeps every tag in flight, so a session's -# requests outlive it unanswered and a late completion answers one. -end-keeps-inflight = [] -# A session's server rings a writer waiting for room on the connection, the -# doorbell a reader waits on, so either can take the other's wake. -one-doorbell = [] -# A thread that took a direction's doorbell leaves it with another waiter -# counted and passes nothing on, so that waiter sleeps over what the take -# announced. -no-pass-on = [] -# A registration looks without arming, so a direction that becomes ready after -# its look rings nobody. -register-no-arm = [] -# A registration arms and looks but rings nobody for a direction it found -# ready, so its first event never comes. -register-no-ring = [] -# Both of the two above. -register-neither = ["register-no-arm", "register-no-ring"] -# A look that arms the send direction, and the server's ring back of it, read -# only the room and not a failure, so a writer over a full ring sleeps through -# a reset. -head-only = [] - -[dependencies] -core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" } - -[dev-dependencies] -loom = "0.7" - -[lints.rust] -warnings = "deny" diff --git a/system/netstack/Cargo.toml b/system/netstack/Cargo.toml index 70b3399235e..6fb3a3a3b0a 100644 --- a/system/netstack/Cargo.toml +++ b/system/netstack/Cargo.toml @@ -24,7 +24,6 @@ toyos-net-shard = { path = "shard" } toyos-net-tcp = { path = "shard/tcp" } toyos-net-udp = { path = "udp" } toyos-net-wire = { path = "wire" } -toyos-transport = { path = "../../sdk/transport" } [dev-dependencies] toyos-pci-claim = { path = "../../lib/pci-claim", features = ["host-grant"] } diff --git a/system/netstack/node/Cargo.toml b/system/netstack/node/Cargo.toml index bbb656a926a..bfb126b45cd 100644 --- a/system/netstack/node/Cargo.toml +++ b/system/netstack/node/Cargo.toml @@ -20,7 +20,6 @@ toyos-net-udp = { path = "../udp" } toyos-net-wire = { path = "../wire" } # The stream protocol's one declaration, the region's layout, and the session's server end. toyos = { path = "../../../sdk/toyos" } -toyos-transport = { path = "../../../sdk/transport" } [dev-dependencies] # The outside reader of every frame the node emits: a published Ethernet, ARP, diff --git a/system/netstack/node/src/streams.rs b/system/netstack/node/src/streams.rs index ffee6ac25de..fa795965020 100644 --- a/system/netstack/node/src/streams.rs +++ b/system/netstack/node/src/streams.rs @@ -27,8 +27,8 @@ use toyos::net::stream::{Server, Words, LAYOUT, NODELAY, RECEIVE_BYTES, RESET, T use toyos_net_shard::ConnectError; use toyos_net_tcp::{ConnId, Endpoint, Error, Failure, Lent, Options, State, Status}; use toyos_net_wire::{Instant, Port}; -use toyos_transport::session::Rings; -use toyos_transport::Violation; +use toyos::transport::session::Rings; +use toyos::transport::Violation; use crate::lease::Stack; use crate::Node; diff --git a/system/netstack/node/tests/common/client.rs b/system/netstack/node/tests/common/client.rs index a952dbcba0d..0580297df7c 100644 --- a/system/netstack/node/tests/common/client.rs +++ b/system/netstack/node/tests/common/client.rs @@ -1,4 +1,4 @@ -//! A client's end of a stream: `toyos_transport::session`'s own client sequences over a region +//! A client's end of a stream: `toyos::transport::session`'s own client sequences over a region //! on the heap, laid out as `toyos::net::stream` lays one out, and the session the node is lent. //! No call waits: a doorbell is a count, the client's ring of netstack a flag the test reads to //! say which streams a pass is owed. @@ -10,7 +10,7 @@ use std::sync::atomic::{AtomicU32, Ordering}; use toyos::net::stream::{Words, LAYOUT, NODELAY, RECEIVE_BYTES, RECEIVE_RING, REGION_BYTES, SEND_BYTES, SEND_RING}; use toyos_net_node::Session; use toyos_net_tcp::Lent; -use toyos_transport::session::{self, Bells, Doorbell, Lock, Mode, Receiving, Refused, Rings, Sending, Took, Waited}; +use toyos::transport::session::{self, Bells, Doorbell, Lock, Mode, Receiving, Refused, Rings, Sending, Took, Waited}; /// The region and its doorbells, which the client and the node share. pub struct Region { diff --git a/system/netstack/node/tests/listeners.rs b/system/netstack/node/tests/listeners.rs index 8861d4cf57c..d5c640a37df 100644 --- a/system/netstack/node/tests/listeners.rs +++ b/system/netstack/node/tests/listeners.rs @@ -1,5 +1,5 @@ //! Listeners and the node's places, against peers the test scripts, at 192.0.2.2 unless a test -//! puts one elsewhere, and clients that are `toyos_transport::session`'s own client end over a +//! puts one elsewhere, and clients that are `toyos::transport::session`'s own client end over a //! region on the heap (`common::client`). No scenario ids: the specifications' listening //! scenarios are `toyos-net-tcp`'s; these are what the node does between [tcp]'s queues, an //! owner's wakes and its accepts. @@ -24,8 +24,8 @@ use common::client::Client; use common::{arp, batch, terms, Segment, Wire, A, BUDGET, ELSEWHERE, MAC, MAC_R, R}; use etherparse::{ArpOperation, LinkSlice, NetSlice, PacketBuilder, SlicedPacket, TcpOptionElement, TransportSlice}; use toyos_net_node::{AcceptRefused, Accepted, ConnectRefused, ListenRefused, ListenerId, Node, Refused, StreamEvent, StreamId, Wake, WriteRefusal}; -use toyos_transport::session::Refused as Read; -use toyos_transport::Violation; +use toyos::transport::session::Refused as Read; +use toyos::transport::Violation; use toyos_net_tcp::{limits, Counter, Endpoint}; use toyos_net_wire::{Instant, Port}; diff --git a/system/netstack/node/tests/streams.rs b/system/netstack/node/tests/streams.rs index 7e26bf820f2..037066ec350 100644 --- a/system/netstack/node/tests/streams.rs +++ b/system/netstack/node/tests/streams.rs @@ -1,5 +1,5 @@ //! Streams on the node, against peers the test scripts, at 192.0.2.2:80 unless a test puts one -//! elsewhere, and clients that are `toyos_transport::session`'s own client end over a region on +//! elsewhere, and clients that are `toyos::transport::session`'s own client end over a region on //! the heap (`common::client`). No scenario ids: the specifications' TCP scenarios are //! `toyos-net-tcp`'s; these are what the node does between [tcp] and a client's region. //! @@ -24,8 +24,8 @@ use toyos_net_node::{ConnectRefused, Node, StreamEvent, StreamId}; use toyos_net_shard::ConnectError; use toyos_net_tcp::{Counter, Endpoint, Failure}; use toyos_net_wire::{Instant, Port}; -use toyos_transport::session::Refused; -use toyos_transport::Violation; +use toyos::transport::session::Refused; +use toyos::transport::Violation; const B: Ipv4Addr = Ipv4Addr::new(192, 0, 2, 2); /// A second peer's address, and its MAC. diff --git a/system/netstack/src/lent.rs b/system/netstack/src/lent.rs index b8419f9827d..0c0c71ea666 100644 --- a/system/netstack/src/lent.rs +++ b/system/netstack/src/lent.rs @@ -21,7 +21,7 @@ use toyos::shm::{self, SharedMemory}; use toyos::{Connection, Pipe}; use toyos_net_node::Session; use toyos_net_tcp::Lent; -use toyos_transport::session::Rings; +use toyos::transport::session::Rings; /// The region's mapping. struct Mapping(SharedMemory); diff --git a/tests/guest/rust-tests/Cargo.lock b/tests/guest/rust-tests/Cargo.lock index 53fd760422a..070dae5d7c8 100644 --- a/tests/guest/rust-tests/Cargo.lock +++ b/tests/guest/rust-tests/Cargo.lock @@ -890,7 +890,6 @@ name = "toyos" version = "0.18.0" dependencies = [ "toyos-abi", - "toyos-transport", ] [[package]] @@ -994,10 +993,6 @@ dependencies = [ "toyos-abi", ] -[[package]] -name = "toyos-transport" -version = "0.1.0" - [[package]] name = "toyos-virtio" version = "0.1.0" From eddc6dc9cbca02b4e05e842745e395720121e1f4 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 21 Oct 2026 10:38:04 +0200 Subject: [PATCH 2/3] clippy lints every target of the SDK, the transport's tests among them The transport's unit tests and loom models were linted as `toyos-transport`'s targets with warnings denied. As `toyos`'s, no shape reached them: the workspace shapes exclude the SDK and lint its library only as a dependency. `-p toyos --all-targets` takes that shape's place for `transport_loom` alone. The SDK's tests had two findings, both fixed: an array of byte literals (`byte_char_slices`) and `chunks_exact_mut` with a constant size (`chunks_exact_to_as_chunks`). Co-Authored-By: Claude Opus 5.5 --- build/clippy.rs | 8 ++++---- sdk/toyos/src/log/stdio.rs | 6 +++--- sdk/toyos/src/relocate/tests.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/clippy.rs b/build/clippy.rs index 68fbc749018..409571a1153 100644 --- a/build/clippy.rs +++ b/build/clippy.rs @@ -208,11 +208,11 @@ const SHAPES: &[Shape] = &[ ], after: &["$ADOPTED", "-D", "warnings"], }, - // The transport's loom models: the workspace shapes lint `toyos`'s library - // only as their members' dependency, and its own test targets are not - // clippy-clean on a host but this one. + // `toyos`'s tests, its transport's loom models among them: the workspace + // shapes exclude it and lint its library only as their members' + // dependency. Shape { - before: &["-p", "toyos", "--test", "transport_loom"], + before: &["-p", "toyos", "--all-targets"], after: &["$ADOPTED", "-D", "warnings"], }, // Its own target directory: cargo keeps one check of a unit, so a unit diff --git a/sdk/toyos/src/log/stdio.rs b/sdk/toyos/src/log/stdio.rs index b8f3df6ddf6..a71f5863e39 100644 --- a/sdk/toyos/src/log/stdio.rs +++ b/sdk/toyos/src/log/stdio.rs @@ -470,9 +470,9 @@ mod tests { use std::sync::{Arc, Mutex}; let held = Arc::new(Held::new(Stream::Err)); let got = Arc::new(Mutex::new(Vec::new())); - let writers: Vec<_> = [b'a', b'b'] - .into_iter() - .map(|tag| { + let writers: Vec<_> = b"ab" + .iter() + .map(|&tag| { let (held, got) = (Arc::clone(&held), Arc::clone(&got)); std::thread::spawn(move || { for _ in 0..200 { diff --git a/sdk/toyos/src/relocate/tests.rs b/sdk/toyos/src/relocate/tests.rs index f217e6372a0..f4a9a3e6d9a 100644 --- a/sdk/toyos/src/relocate/tests.rs +++ b/sdk/toyos/src/relocate/tests.rs @@ -271,7 +271,7 @@ fn a_header_this_does_not_know_is_refused() { fn image_with(edit: impl Fn(usize, &mut [u8])) -> Result { let header = Header::parse(&X86_64[..HEADER_SIZE]).unwrap(); let mut phdrs = X86_64[header.phoff..header.phoff + header.phlen].to_vec(); - for (i, entry) in phdrs.chunks_exact_mut(PHDR_SIZE).enumerate() { + for (i, entry) in phdrs.as_chunks_mut::().0.iter_mut().enumerate() { edit(i, entry); } Image::new(header, &phdrs).map(|image| image.header_vaddr) From bcd97adacacd47337a8cf2a937f10ee6f70d06c7 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 21 Oct 2026 10:51:24 +0200 Subject: [PATCH 3/3] Comments the transport merge left stale `NOT_A_CONTROL`'s doc names the guest libraries' `ttf` and `host-grant`; `GUEST_LIBRARIES` no longer says the SDK is not clippy-clean, which the `-p toyos --all-targets` shape disproves; the transport header's paragraph is wrapped. Co-Authored-By: Claude Opus 5.5 --- build/build.rs | 8 +++++--- build/hostws.rs | 5 ++--- sdk/toyos/src/transport/mod.rs | 7 ++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/build/build.rs b/build/build.rs index 94170272d77..1d2202bc9ce 100644 --- a/build/build.rs +++ b/build/build.rs @@ -2724,12 +2724,14 @@ mod tests { "test-actuators", ]; - /// Features of a host workspace member that choose a build's world rather + /// Features of a host-tested member that choose a build's world rather /// than revert a decision: loom's atomics, a crate's `std` and its default /// set, the toolchain's `core` and `rustc-dep-of-std`, libc's `std-runtime`, /// the signer's `sign`, `flaws`, which compiles what a simulator's - /// negative gates select at run time, and `toyos-crypto`'s `portable`, - /// `wpa2` and `rustls-provider`, which `--ci host` tests as forms of its own. + /// negative gates select at run time, `toyos-crypto`'s `portable`, `wpa2` + /// and `rustls-provider`, which `--ci host` tests as forms of its own, and + /// of the guest libraries, `toyos-font`'s `ttf`, its TrueType rendering, + /// and `toyos-pci-claim`'s `host-grant`, which netstack's host tests build. const NOT_A_CONTROL: &[&str] = &[ "core", "default", diff --git a/build/hostws.rs b/build/hostws.rs index 60a7663287a..4b8fba024cd 100644 --- a/build/hostws.rs +++ b/build/hostws.rs @@ -84,9 +84,8 @@ pub(crate) fn rel(root: &Path, path: &Path) -> String { } /// The library members built for a guest: the SDK, its window, font and -/// file-picker clients and the two shared crates that link the SDK, whose -/// `toyos` is not clippy-clean on a host. Their tests run in a step of their -/// own ([`guest_libraries`]). +/// file-picker clients and the two shared crates that link the SDK. Their +/// tests run in a step of their own ([`guest_libraries`]). pub(crate) const GUEST_LIBRARIES: [&str; 6] = [ crate::ci::SDK_DIR, "sdk/window", diff --git a/sdk/toyos/src/transport/mod.rs b/sdk/toyos/src/transport/mod.rs index af54c8a1622..3fcab3ffa2f 100644 --- a/sdk/toyos/src/transport/mod.rs +++ b/sdk/toyos/src/transport/mod.rs @@ -16,9 +16,10 @@ //! the peer's words, for the protocol's decoder to bound; a peer's cursor is //! bounded against the ring before it is believed, and the variant of //! [`Violation`] names what it claimed; a run is bounded against the -//! [`Geometry`], and a tag against the [`Inflight`] table. An end keeps its own cursor locally and only stores the shared one, -//! so nothing the peer writes moves it, and a cursor the peer moves backwards -//! within bounds costs only the peer. +//! [`Geometry`], and a tag against the [`Inflight`] table. An end keeps its +//! own cursor locally and only stores the shared one, so nothing the peer +//! writes moves it, and a cursor the peer moves backwards within bounds costs +//! only the peer. //! //! **A restart is seen only as a hang-up**, and [`Inflight::end`] answers every //! tag that was in flight, once; a tag from before it answers nothing.