diff options
Diffstat (limited to 'src/syscall.asm')
| -rw-r--r-- | src/syscall.asm | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/syscall.asm b/src/syscall.asm index 04e9661..1051a4d 100644 --- a/src/syscall.asm +++ b/src/syscall.asm @@ -68,6 +68,7 @@ SyscallTable: dw sys_srecv_nb ; 31 SRECVNB dw sys_pollin ; 32 POLLIN dw sys_net ; 33 NET + dw sys_sleep ; 34 SLEEP ; ----------------------------------------------------------------------------- sys_nosys: @@ -279,6 +280,46 @@ sys_yield: ret ; ----------------------------------------------------------------------------- +; sys_sleep(B = 1/64-second units) - cooperative delay driven by the DIV timer. +; DIV (FF04) free-runs at 16384 Hz, so 256 ticks = 1/64 s. We accumulate DIV +; deltas across SchedYields (other procs run) until enough units have elapsed. +; ----------------------------------------------------------------------------- +sys_sleep: + ld a, b + or a + ret z ; sleep 0 = no-op + ld [wSleepTarget], a + xor a + ld [wSleepAcc], a + ld [wSleepAcc+1], a + ld a, [rDIV] + ld [wSleepLastDiv], a +.loop + call SchedYield + ld a, [rDIV] + ld c, a ; current DIV + ld a, [wSleepLastDiv] + ld b, a ; previous DIV + ld a, c + ld [wSleepLastDiv], a + sub b ; A = DIV delta (mod 256) + ld e, a + ld a, [wSleepAcc] ; acc += delta + add e + ld [wSleepAcc], a + ld a, [wSleepAcc+1] + adc 0 + ld [wSleepAcc+1], a ; acc high byte = elapsed 1/64-second units + ld b, a + ld a, [wSleepTarget] + cp b + jr z, .done ; elapsed == target + jr c, .done ; elapsed > target + jr .loop +.done + ret + +; ----------------------------------------------------------------------------- ; sys_exit(code=B) -- become a zombie awaiting reap; never returns. ; - store exit code, set PS_ZOMBIE ; - reparent any children to init (so they can still be waited on) |
