diff options
| author | user <user@clank> | 2026-09-22 17:12:32 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-22 17:12:32 +0200 |
| commit | bb55479e693a04df0da8320adfa10a6b8188b8da (patch) | |
| tree | 9b3736cff55112982d1722bc4c1a9630785aeda9 /src/kdata.asm | |
| parent | fs: bounds-check direct blocks - a file over 2 KiB ate the next inode (diff) | |
| download | gbos-bb55479e693a04df0da8320adfa10a6b8188b8da.tar.gz gbos-bb55479e693a04df0da8320adfa10a6b8188b8da.tar.xz gbos-bb55479e693a04df0da8320adfa10a6b8188b8da.zip | |
kernel: per-process sleep - two sleepers used to deadlock each other
sys_sleep kept its entire state in three globals (wSleepTarget, wSleepAcc,
wSleepLastDiv) and yielded inside its own loop. With two processes sleeping
at once, each zeroed the other's accumulator on entry, so neither ever
reached its target: both slept ~forever.
Nothing hit it while only one program at a time paced itself. `httpd &`
(polling accept) plus a foreground `ping` is enough: ping wedged with its
echo reply already sitting in the socket buffer, unread.
Now the deadline lives in registers - i.e. on the caller's own stack across
SchedYield, which makes it per-process by construction - and it counts the
64 Hz tick (wTicks, via TimerISR) instead of accumulating DIV deltas.
ticks16 re-reads the counter until the high byte is stable, so a carry
between the two byte reads can't report a 256-unit jump.
Diffstat (limited to 'src/kdata.asm')
| -rw-r--r-- | src/kdata.asm | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/src/kdata.asm b/src/kdata.asm index c2316b8..7a6aab9 100644 --- a/src/kdata.asm +++ b/src/kdata.asm @@ -56,9 +56,10 @@ wFsPath:: DS 40 ; kernel-side copy of a path argument wFsSlashPtr::DS 2 ; last '/' seen while splitting a path wListDir:: DS 1 ; directory sys_list enumerates wKChar:: DS 1 ; scratch for KPutc -wSleepTarget::DS 1 ; sys_sleep: target in 1/64-second units -wSleepAcc:: DS 2 ; sys_sleep: accumulated DIV ticks -wSleepLastDiv::DS 1 ; sys_sleep: previous DIV reading + ; (sys_sleep used to keep its accumulator in three + ; globals here - see syscall.asm: shared state plus a + ; yield inside the loop meant two concurrent sleepers + ; never woke. Its state is per-process now.) wKillParent::DS 1 ; scratch for sys_kill wPsBuf:: DS 2 ; scratch for sys_ps wPnStart:: DS 2 ; scratch for sys_progname |
