Repository navigation
Conversation
A counters read within JOIN (10 ms) of the last round's issue used to be served that round, so a reader could get a reading taken up to 10 ms before it asked, and two reads 5 ms apart one reading twice. #1073's group-start diagnostic lost 13 of its 17 clock windows to it. Now a read joins only a round issued after its call began. Inside JOIN of the last issue it rests until JOIN has passed and then issues its own; readers resting together wake at the same instant, the first issues and the rest join. The wait is the round rate limit with a known end, not a delay standing in for an event, and toyos_abi::counters says a read may wait up to 10 ms. The kick rate per CPU is unchanged: one per JOIN at most. Consumers follow: - osbench_rules::window is strict: a window lies between the row less its reads' cost and the row; JOIN_NS is gone. - counters_read requires the read straight after an answered one to give every CPU a new stamp, where it used to loop until a stamp moved. - acpi_mediated's Counted, which read until the boot processor's stamp was one it had not seen, is a plain function. Counter::DeepIdleNanos is deleted with its kernel accounting: the kernel credits a period's time only when it ends, so its time is no fraction of a window, and no consumer read it. DeepIdles stays. Closes issues/a-counters-read-within-10-ms-of-another-returns-the-older-reading-as-new.md. The idle track records D1-D3's findings, with mem's 3789 open and the fixed counters as the instrument to read it next. The AMD deflate record compares MPERF against MPERF on the same machine (APM Vol. 2 §17.3: MPERF counts only in C0), not against the TSC. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hitect The wake-storm and sleep-lateness costs were recorded as accepted on ratios alone. The track now gives them in microseconds, controlled: two A* boots (every idle CPU in C1) against two B3 boots at f6510de, one session a bench, with B7 at 18fe4e1 beside them. On the T14 a 10 ms sleep lands 10 us later and a 4- or 16-thread storm drains 52 to 91 us later; on the AMD a 1 ms sleep lands 27 us sooner and nothing else moves (its storm reads 107 or 306 us either way). Their consequences for interactive, audio (soundserver's hold, half of a 2.9 ms period, admits the T14's 1048 us exit) and normal workloads are stated as inference and labelled a tradeoff to bring to the architect, not accepted. cpu.clock's ratio 42 at group starts is a diagnostic of the turbo grant, not the product target; the exit is worded so, with single-thread rows at Linux's on the same T14 in its place, and no idle predictor is tuned before the fixed counters have read mem's window. acpiserver's processor _OSC commit: a commit that fails, is refused or masks bits gates nothing, because _CST is read either way and each state is checked on its own terms (cst.rs: FFH bus-master avoidance, SW-coordinated _CSD and type-3 SystemIO withheld; SystemIO not used on Intel). The bits are statements of what OSPM does (302223-007 §2.1), and the firmware's answer to them is the _CST it returns. osc.rs states that invariant; no code changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r1: PR #1084 at 74c60afArchitectureThe fix belongs in the kernel's
Net change is +149 / −161. The code part is small: the kernel gains about 20 lines, and the tests and ABI lose more than that. Correctness of the wait and the join (checked independently)
Records
FindingsBLOCKER
SUGGESTION
Evidence
SEND BACK |
B2: with every reading now taken after its call, an osbench counters read within 10 ms of its previous one sleeps out the kernel's round interval. The crunch loop reads after one workload and before the next a few prints apart, and tail's diary run reads straight after the 60 s run's last read, so on ToyOS alone a measured slice would begin straight after a sleep of up to 10 ms. Since #1079 the comparison measures the systems, not the setup. around::read now gives this process's last reading again where a fresh read would fall inside the interval: one reading bounds both rows beside it, nothing sleeps, and the window rule still holds, since a row's span runs from its first reading's call. The interval is one constant, toyos_abi::counters::INTERVAL_NS, which the kernel's round rate (JOIN, renamed INTERVAL: joining no longer depends on it) and osbench both name. B1: around.rs no longer justifies printing periods by the period time this branch deleted. The track's deltas are the same-build pairs (w16 +68 to +87 with B7 +52, 10 ms sleep +10.5 to +10.6, AMD 10 ms 0 to +1), the history clause is gone, and the crunch.single criterion is dropped from the exit: it was not the architect's wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review r1 response (head 7c9cf91):
|
Review r2: PR #1084 at 7c9cf91This round covers r1's two blockers and the one new commit, 7c9cf91: +37/−23 over the kernel, the ABI, osbench and the idle track. I did not reopen points r1 settled. Architecture
Is the reuse sound? (checked independently)
B1 and B2
Records
FindingsBLOCKER None. SUGGESTION
For the orchestrator (PR body; required for truth, not a code blocker)
Evidence
LAND |
…query #1084's T14 testcases boot at 7c9cf91 judged FAIL counters: the EC's query 0x4f was taken for the first time 0.87 s into counters_metal's idle second. counters_metal starts the second at the first query, and here the first was 0x40 (12.520 s), not 0x4f, which every earlier testcases readback on hand took first. Independent of #1084: the read before the second took 22 us, and the line is the embedded controller's, which the branch does not touch. The same boot's counters_read and the shared-debug counters_silent passed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two of the 32 earlier testcases boots also took 0x40 first; what kept them green was that their idle second began after both queries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed; the CPUID identity is named - Rebased onto main, which dropped `Counter::DeepIdleNanos` (#1084): `idle_entered` prints and its judge reads deep periods alone. - The `idle_entered` judge runs on the AMD bench only, against `AMD_KEPT_STATES`; the T14 has not run it and joins in a later change. Its doc says what the count shows: 0x415 requested by the chooser, not what the core entered. - BM_RLD is recorded beside BM_STS, in `cst.rs`'s header and the idle track: left as firmware set it, and spoken to only by PPR 55901 Vol. 5 for 19h M11h. - The `_LPI` paragraph states the one real gap, that ACPI defines the context-loss flags for Intel alone; the claimed lack of an x86 OS-initiated mechanism was no reason, since platform-coordinated mode needs none. - The Family 1Ah second-C1-sub-state sentence goes: no firmware is known to declare such a hint. - `toyos_abi::ProcessorId { vendor, signature }` names the pair `processor_id` returns. - `acpi_tables_on_metal` reads the census through `acpiserver_api::IDLE_CENSUS`; the osc test's two `intel`s are `on_intel` and `intel`. - The idle track marks its AMD exit-cost figures as 0x414's alone, to be replaced with 0x415's once the AMD's osbench has run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem
A
SYS_COUNTERSread issued within 10 ms of the last round's issue was served that round. It could therefore get a reading taken up to 10 ms before it asked, and two reads 5 ms apart got one reading twice. #1073's group-start diagnostic lost 13 of its 17 clock windows to it.Behavior now
kernel/src/counters.rs).INTERVALof the last issue, a read rests until the interval has passed and then issues its own round. Readers resting together wake at the same deadline: the first issues the round and the rest join it.toyos_abi::counters::INTERVAL_NSis the one constant both the kernel and osbench name. The ABI header says a read may wait up to 10 ms.JOINis renamedINTERVAL, since joining no longer depends on it.around::readhands back this process's last reading when a fresh read would fall inside the interval.osbench_rules::windowis strict. A window must lie between the row less its reads' cost and the row itself.JOIN_NSis gone.Counter::DeepIdleNanosis deleted, along with its kernel accounting. Its only reader was inspect's rendering,kernel.cpu.N.deep_idle_nanos. The kernel credited a period's time only when the period ended, so that time was no fraction of any window.DeepIdlesstays.counters_readnow requires the very next read after an answered one to give every CPU a new stamp.acpi_mediated'sCountedis now a plain function.issues/a-counters-read-within-10-ms-of-another-returns-the-older-reading-as-new.mdis closed. Its rule now lives in thecounters.rsheader and intoyos_abi::counters.Records
f6510defd, with B7 beside them.cpu.clockat ratio 42 is described as a diagnostic, not the product target.crunch.singlecriterion, so the one I added in r1 is dropped._OSCcommit is correct as written. A commit that fails, is refused or comes back with bits masked gates nothing.cst::declaretakes nothing from the negotiation, and each_CSTstate is checked on its own terms.osc.rsnow states this.Decisions
time::Instant, which deliberately has none, or mintingInstants outsideclock.rs.counters_readruns:virt_smp(EL2, SMC) andvirt_el1_smp(EL1, HVC, TCG).Checks
Evidence: r3 https://github.com/ToyOSOrg/evidence/tree/14c6006c49c0b9480d3bfce30cb8eb4d479d0a65/r3, r1 https://github.com/ToyOSOrg/evidence/tree/73830f45f7c3dcc3d71a836c97238e26054a82d2/r1, r2 https://github.com/ToyOSOrg/evidence/tree/06e8ebcd59d365cfcc43a7e17738fdea0170682c/r2
cargo run -- --ci hostcargo test --test toyos-build -- virt_smp virt_el1_smp osbench_capability_groups_exit_0 acpi_mediated_accesscounters_readmarker in both SMP bootsrestore-join(rejoin a round within the interval),virt_smpThe head, be8e971, adds only issue records after 7c9cf91, so every check above still applies.
Metal: one T14 session at 7c9cf91 (the orchestrator ran it; all three boots rc=0). Judged with
cargo test --test toyos-build -- --metal --metal-readback <dir> osbench counters counters_read counters_silent, from one directory holding all three readbacks: exit 1, 3 passed, 1 failed (r3).c7e4ef785b257dc36e67c8e9d5fd3b87a00f3a62320e317aac9647dfd9fe66dbec2dbdb8c56dfc90e23cf9356d50da98bbfac9beb3e2e0aebe469f889b780864counters_read(x86-64). FAILcounters, unrelated, see below1d5405fbe1adeeff1c4f066fe3e2e77f195d8c026599dddcc9dc9c60999966f6counters_silentreads_usis 129 to 261 µs per row, so no read waited before a slice.countersred is independent of this branch.counters_metal's idle second. The EC took query 0x4f for the first time at 13.538 s, 0.87 s into that second.counters_metalstarts the second once the EC's first query is said. Here the first was 0x40 at 12.520 s, and this two-job image's log settled 152 ms later.issues/the-counters-rows-idle-second-can-hold-the-ecs-second-boot-query.md.counterswould otherwise have checked of this branch, a read per CPU fresh and in place,counters_readestablishes on the same boot.Risks
counters_metal's loaded phase. Each of its rounds is now new, so no round's kick lateness is counted twice.counters_read's many-readers phase: 50 reads on each of twice as many threads as CPUs.🤖 Generated with Claude Code