Take a device's line down when its status port is read
A device raises a line and something has to take it down. Two things did: being interrupted, and being woken from WAIT with the Interrupt Flag down - the second because a masked program has nowhere to dispatch to, so nobody else would. There was a third way to learn a device had finished and nothing answered it. The documented idiom reads the status, branches out if the device is already done, and only WAITs otherwise; on a disk quick enough to finish before the first look, which is every disk here, the WAIT is unreachable. The line then stood for the rest of the machine's life. The program that leaves it standing never pays for it - it was masked throughout. The bill arrives at whoever next sets the Interrupt Flag. The boot chain reads the disk to load a program, leaves the line up, and hands over; the loaded program is then interrupted on behalf of a read that finished before it existed, through a vector table with no entry for a device it never touched, and faults on the instruction after its SIF. Found by running Examples/tune.asm through Once. It set up its whole sound and died four bytes before its first note, which is why it was silent rather than wrong - and why it looked like a sound bug for a while. So reading the port that answers a device takes its line down, the same way taking the byte already took the console's down. Disk and screen do it on their status port. And a reset now clears every line, which is the sentence the manual already makes about the vector table: a handler left behind aims an interrupt into a program that is no longer running, and so does a line. testPrograms/diskLineTest.asm pins it - the racy idiom, then SIF with no handler installed anywhere. It faults without the fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
62a657f1a7
commit
85329f13c3
@@ -0,0 +1,3 @@
|
||||
no line
|
||||
Execution halted.
|
||||
[exit 0]
|
||||
@@ -750,6 +750,13 @@ runOffTest | testPrograms/runOffTest.asm | run | -
|
||||
# that never woke would hang, and a hang is what this catches. Whether it slept or spun is
|
||||
# a question about cycle counts, which settle() strips, so Tests/terminal.sh asks that one.
|
||||
waitTest | testPrograms/waitTest.asm | run | - | 5000000 | disks/sbfs.img@10000
|
||||
# The other half of what WAIT is for, and the half that was missing. waitTest checks that a
|
||||
# masked program which SLEEPS on a device is woken and does not leave the line up; this checks
|
||||
# the program that never sleeps at all, because the disk finished before the first look. The
|
||||
# WAIT is unreachable, so nothing but the status read can take the line down. It then sets the
|
||||
# Interrupt Flag with no handler installed anywhere: a standing line faults there, which is
|
||||
# how a program loaded by CosmOS used to die on the instruction after its SIF.
|
||||
diskLineTest | testPrograms/diskLineTest.asm | run | - | 1000000 | disks/sbfs.img
|
||||
printDecimalTest | testPrograms/printDecimalTest.asm | xfail | - | -
|
||||
printDigitTest | testPrograms/printDigitTest.asm | xfail | - | -
|
||||
printHexTest | testPrograms/printHexTest.asm | xfail | - | -
|
||||
|
||||
Reference in New Issue
Block a user