Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,45 @@ the 60 000 ms list bound and 120 000 ms deadline of a boot no member rides:
|---|---|---|---|
| no member | 60.0 s | 120.0 s | 420 s |
| `shared-debug` | 62.1 s | 124.2 s | 425 s |
| `ccorpus` | 73.7 s | 147.4 s | 448 s |
| `shared` | 86.4 s | 172.8 s | 473 s |
| `testcases` | 100.1 s | 200.2 s | 501 s |

**It grows with every member and has no ceiling**: 0.6 s of deadline a Rust
member and 0.2 s a C case. The 88 Rust members and 137 C cases on one boot,
which is what joining `shared` and `ccorpus` to `testcases` makes, arm a list
bound of 100 100 ms and a deadline of 200 200 ms, waited 501 s. A clamp is no
answer: a ceiling under the derived bound ends a healthy list.
member and 0.2 s a C case. The 88 Rust members and 137 C cases the readings
above took on `shared` and `ccorpus` ride `testcases` behind its rows' jobs,
and those two boots are gone. A clamp is no answer: a ceiling under the
derived bound ends a healthy list.

## The merged list

The T14 ran the merged `testcases` once, at `2c7e1be1a`, armed 200 200 and
100 100 ms by the kernel's own lines; each part between its own markers, the
kernel's clock counted from its `Boot: complete (1135ms)` line. Beside it, the
sum of the three boots it was, three readings each: `testcases` at
`9e70cd2e3`, `473efea22` and `accbd79dd`, `shared` and `ccorpus` at
`eff8b20ee`, `d6d008e88` and `49e12f23b`.

| part | merged, `2c7e1be1a` | its parts apart | its share of the bound |
|---|---|---|---|
| the boot, to its first job | 1 191 ms | 1 190 to 1 196 ms | |
| the rows' ten jobs | 41 924 ms | 41 913 to 41 983 ms | 60 000 ms |
| the 225 members | 9 253 ms | 8 735 to 9 298 ms | 40 100 ms |
| the list's last record | 52 352 ms | 51 838 to 52 477 ms | 100 100 ms |

**The two shares are wide by different factors, and the rows' is the
tighter.** The members took 9 253 ms of the 40 100 ms they add: the
allowances stand at about 4.3 times their work. The rows' jobs ended
43 115 ms into the kernel's clock, of the 60 000 ms `toyos_tco::JOB_BOUND_MS`
gives them: about 1.4 times theirs, `counters_metal` alone 32.7 s of it. That
constant is the same for a boot of no job and for this boot of ten, and no
allowance widens it. The list's last record left 47.7 s of its bound, and
nothing reads that margin.

**A late expiry adds to the longer bound.**
`issues/a-120000-ms-boot-deadline-fired-132859-ms-late-on-the-t14.md` is open:
that deadline was reached at 252 859 ms, and the same lateness on `shared` is
305 659 ms. The wait moves with the deadline, so what is left of it after such
an expiry is the same 167 s; the machine is held 52.8 s longer.
that deadline was reached at 252 859 ms, and the same lateness on `testcases`
is 333 059 ms. The wait moves with the deadline, so what is left of it after
such an expiry is 167 s there and 168 s here; the machine is held 80.2 s
longer.

## Owner

Expand All @@ -85,13 +110,18 @@ The metal suite: `tests/common/metal.rs`, which derives the bounds, and

## Exit

Both, on the T14:

- Each allowance is derived at its declaration from what the T14 measures of a
list's total over its members, by one stated factor: a factor over a
per-member mean says nothing of a list of slow members. And the judge reds a
shared boot whose list's last record came past half its bound, which today
is a line a reader reads.
- The boot that carries `shared`, `ccorpus` and `testcases` together reads its
list's last record within half its list bound, with the pair read from the
kernel's own `boot deadline:` and `hard lockup:` lines.
Three parts, each on the T14. None is built.

1. **The members.** Each allowance is derived at its declaration from the
members' sum between their own markers, by one stated factor: a factor over
a per-member mean says nothing of a list of slow members. And the judge
reds a boot whose members' sum is past the share they add, which today is a
line a reader reads.
2. **The rows' jobs.** What a boot's rows' jobs are given is derived the same
way from what they take, where today it is one constant,
`toyos_tco::JOB_BOUND_MS`, for a boot of no job and a boot of ten, one of
them 32.7 s. And the judge reds a boot whose rows' jobs end past their
share, which today nothing reads.
3. **`testcases` reads both inside their shares**, with the armed pair read
from the kernel's own `boot deadline:` and `hard lockup:` lines and the
margin from the list's last record to its list bound stated beside them.
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,11 @@ count line is there at 42.579 s (`28 SCIs; embedded controller queries taken:
in seconds 36 to 47.

`acpi_server_events` and `acpi_tables_loaded` ride `testcases` again, with
`test_rs_acpi_hold` its last job, and `testcases-hold` is deleted. The job
waits on the `log` port for the server's count line, bounded by the runner's
bound less a tenth, and exits non-zero without it. That readback judged
`test_rs_acpi_hold` the last of its rows' jobs and the shared members behind
it, and `testcases-hold` is deleted. The job waits on the `log` port for the
server's count line until 54 000 ms after boot
(`issues/acpi-hold-gives-up-at-a-time-counted-from-boot-whatever-its-runner-was-given.md`),
and exits non-zero without it. That readback judged
offline by this harness reds by name: `testcases's own log is missing its
parts 2 to 26; no row is judged on it`.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
status: open
kind: tooling
opened: 2026-10-09
---

# `acpi_hold` gives up at a time counted from boot, whatever its runner was given

`tests/toyos-rust-tests/src/bin/acpi_hold.rs` holds `testcases` open until
`/system/bin/acpiserver` has logged its count, which `acpi_server_events`
judges. Its wait ends at `UNTIL_MS`, `toyos_tco::JOB_BOUND_MS` less a tenth:
54 000 ms, counted from the kernel's zero and not from the hold's own start.
Two things follow.

**What the hold is given shrinks with every job before it.** It is the last of
its boot's rows' jobs. On the T14 at `accbd79dd` it started 43 161 ms in, with
10.8 s left; on the merged `testcases` at `2c7e1be1a`, 43 095 ms in, with
10.9 s left. A rows' job that adds 10.8 s to that list leaves it nothing:
`served_log::Log::until` then panics before it reads a line, with `the log did
not show … within 0ns`, and `acpi_server_events` reds over a count line that
was written some 20 s earlier and is in the log. The red names the server's
count, not the list that grew.

**The constant is not the bound its runner was given.** `UNTIL_MS` is written
as "the runner's bound less a tenth", and `testcases`' runner is given
`--bound-ms=100100`: the 60 000 ms and what its 225 members add. The members
were ordered behind the hold for this reason and no other. Behind them it
would start 51.8 to 52.5 s in by the readings on record, with 1.5 to 2.2 s
left.

## Owner

The harness: `tests/toyos-rust-tests/src/bin/acpi_hold.rs`, and
`TESTCASES_HELD` in `tests/toyos.rs`, which places it.

## Exit

The hold is bounded from its own start, or by the bound its runner was given,
and a job added before it cannot red `acpi_server_events` over a line the log
holds.
6 changes: 3 additions & 3 deletions issues/the-t14-reboots-through-ubuntu-for-every-test.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ metal rows.
Every stage below has the host drive a T14 that runs ToyOS, so the track is
blocked on `issues/the-host-cannot-reach-the-t14-while-it-runs-toyos.md`.

**Next: two sessions in place of five boots.** `shared`, `ccorpus`,
`testcases`, `testcases-mkdir` and `testcases-readdir` share a config, a
parameter line and the shipping kernel. The session image is `tests/testcases`
**Next: two sessions in place of three boots.** `testcases`, which every
shipping-kernel member rides, `testcases-mkdir` and `testcases-readdir` share
a config, a parameter line and the shipping kernel. The session image is `tests/testcases`
with the netd, sshd and streaming `logd` of `tests/lantalkcase`, which is
deleted (`issues/the-host-cannot-reach-the-t14-while-it-runs-toyos.md`),
under a `boot-deadline=` derived as a metal boot's is: twice its list's bound
Expand Down
47 changes: 29 additions & 18 deletions tests/checks/metal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,10 @@ pub fn a_run_under_another_bios_fails_and_records_nothing() {
assert_eq!(judged_against(&lacking(&bios)), (false, committed(&bios, 1165)));
}

fn member(job: &str, adds_ms: u64) -> metal::Member {
metal::Member { job: job.to_string(), adds_ms }
}

/// **A failing shared member fails itself alone**: the run is red, and the
/// boot it rode records its own numbers as the boot whose members all passed
/// does.
Expand All @@ -391,8 +395,7 @@ pub fn a_failing_shared_member_fails_itself_alone() {
config: "tests/testcases",
params: &[],
features: &[],
member_ms: toyos_tco::RUST_MEMBER_MS,
jobs: Vec::from(jobs.map(String::from)),
members: jobs.iter().map(|job| member(job, toyos_tco::RUST_MEMBER_MS)).collect(),
files: Vec::new(),
links: Vec::new(),
};
Expand Down Expand Up @@ -436,12 +439,13 @@ pub fn a_boots_last_job_is_behind_every_other() {
assert!(refused.contains("other ends the boot \"own\" on later and another row ends it on hold"), "{refused}");
}

/// **A boot's rows' jobs run before its members, its last job behind both,
/// and its bounds follow from who rides it**: the runner's bound over the list
/// is the rows' and what each member adds, the kernel's over the boot twice
/// that, and a boot no member rides keeps the bounds a row's boot had. A
/// **A boot's rows' jobs run before its members, the rows' last job among
/// them, and its bounds follow from who rides it**: the runner's bound over
/// the list is the rows' and what each member adds, the kernel's over the boot
/// twice that, and a boot no member rides keeps the bounds a row's boot had. A
/// shared boot that disagrees with a row about the image is refused, and so
/// are two under one name.
/// are two under one name, and two jobs of one boot the kernel records under
/// one name.
pub fn rows_run_before_members_under_a_bound_the_members_widen() {
static EARLY: Metal =
Metal { arms: &[metal::once("shared", "tests/testcases", &[], &["tone", "cost"])], judge: |_| Ok(()) };
Expand All @@ -456,23 +460,25 @@ pub fn rows_run_before_members_under_a_bound_the_members_widen() {
arms: &[metal::once("wedge", "tests/jobcase", &[toyos_build::metal::WEDGE_ARM], &[])],
judge: |_| Ok(()),
};
let members = |boot: &str, member_ms: u64, jobs: &[&str]| metal::SharedBoot {
let members = |boot: &str, members: &[(&str, u64)]| metal::SharedBoot {
boot: boot.to_string(),
config: "tests/testcases",
params: &[],
features: &[],
member_ms,
jobs: jobs.iter().map(ToString::to_string).collect(),
files: vec![(format!("expect/{}", jobs[0]), Vec::new())],
members: members.iter().map(|(job, adds_ms)| member(job, *adds_ms)).collect(),
files: vec![(format!("expect/{}", members[0].0), Vec::new())],
links: Vec::new(),
};
let rows = [("early", &EARLY), ("held", &HELD), ("wedges", &WEDGES)];
let shared = [members("shared", 860, &["m1", "m2", "m3"]), members("corpus", 260, &["c1", "c2"])];
let shared = [
members("shared", &[("m1", 860), ("c1", 260), ("m2", 860)]),
members("corpus", &[("c2", 260), ("c3", 260)]),
];
let boots = metal::batches(&rows, &shared).expect("one image a boot");
let bounds = |boot: &str| (boots[boot].bound_ms(), boots[boot].deadline_ms());
assert_eq!(boots["shared"].jobs, ["tone", "cost", "late", "m1", "m2", "m3", "hold"]);
assert_eq!(bounds("shared"), (62_580, 125_160));
assert_eq!(boots["corpus"].jobs, ["c1", "c2"]);
assert_eq!(boots["shared"].jobs, ["tone", "cost", "late", "hold", "m1", "c1", "m2"]);
assert_eq!(bounds("shared"), (61_980, 123_960));
assert_eq!(boots["corpus"].jobs, ["c2", "c3"]);
assert_eq!(bounds("corpus"), (60_520, 121_040));
// No member: the bounds every row's boot had before a list could widen.
assert_eq!(bounds("own"), (60_000, 120_000));
Expand All @@ -488,6 +494,11 @@ pub fn rows_run_before_members_under_a_bound_the_members_widen() {
panic!("two shared boots under one name were batched");
};
assert!(refused.contains("two shared boots are both named \"shared\""), "{refused}");
let long = members("shared", &[("test_rs_a_name_past_what_is_kept", 860), ("test_rs_a_name_past_what_is_lost", 860)]);
let Err(refused) = metal::batches(&rows, &[long]) else {
panic!("two jobs the kernel records under one name were batched");
};
assert!(refused.contains("the kernel records both as \"test_rs_a_name_past_what_is\""), "{refused}");
}

/// **What a run's words take**: no word the whole profile; a name word every
Expand All @@ -505,20 +516,20 @@ pub fn words_take_rows_members_and_whole_boots() {
config: "tests/testcases",
params: &[],
features: &[],
member_ms: toyos_tco::RUST_MEMBER_MS,
jobs: jobs.iter().map(ToString::to_string).collect(),
members: jobs.iter().map(|job| member(job, toyos_tco::RUST_MEMBER_MS)).collect(),
files: jobs
.iter()
.flat_map(|job| [(format!("expect/{job}"), Vec::new()), (format!("bin/test_c_{job}"), Vec::new())])
.collect(),
links: jobs.iter().map(|job| (format!("bin/{job}"), "/system/bin/test_rs_ccheck".to_string())).collect(),
};
let profile = [boot("shared", &["test_rs_a1", "test_rs_a2", "test_rs_b1"]), boot("ccorpus", &["c1", "c2"])];
let jobs_of = |boot: &metal::SharedBoot| boot.members.iter().map(|m| m.job.clone()).collect::<Vec<_>>();
let taken = |names: &[&str], boots: &[&str]| {
metal::select(names, boots, &ROWS, &profile).map(|(rows, shared)| {
let rows: Vec<&str> = rows.iter().map(|(name, _)| *name).collect();
let shared: Vec<String> =
shared.iter().map(|boot| format!("{}={}", boot.boot, boot.jobs.join("+"))).collect();
shared.iter().map(|boot| format!("{}={}", boot.boot, jobs_of(boot).join("+"))).collect();
(rows.join(","), shared.join(","))
})
};
Expand Down
Loading
Loading