<feed xmlns='http://www.w3.org/2005/Atom'>
<title>gbos.git/src/sched.asm, branch master</title>
<subtitle>gbos - a tiny Unix-flavored OS for the Game Boy Color (kernel, shell, coreutils in C, RAM filesystem)</subtitle>
<id>https://git.sl0p.foo/gbos.git/atom/src/sched.asm?h=master</id>
<link rel='self' href='https://git.sl0p.foo/gbos.git/atom/src/sched.asm?h=master'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/'/>
<updated>2026-07-18T20:06:35Z</updated>
<entry>
<title>kernel: CGB double-speed mode - 2x everything (1.99x measured)</title>
<updated>2026-07-18T20:06:35Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-18T20:06:35Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=4425150cb6f52d15f513690a75645639358a2030'/>
<id>urn:sha1:4425150cb6f52d15f513690a75645639358a2030</id>
<content type='text'>
KEY1 prepare + STOP at KernelInit (skipped on warm reboot if already
fast). The PPU/LCD keep their normal rate; the timer and DIV double
with the CPU, compensated at the two consumers:
- TimerISR now fires at 128 Hz; a toggle byte keeps wTicks at 64 Hz
  (uptime semantics unchanged)
- sys_sleep halves the DIV-delta accumulator's high byte (256 DIV
  ticks = 1/128 s in double speed) so gsleep/msleep stay real-time

Measured: count 60 (scroll-heavy) 3.77s -&gt; 1.89s wall; wTicks 64 Hz
over 4s; ping's 800ms msleep pacing unchanged (2.77s for 4 echoes).
sl0pboy already emulated KEY1/STOP + per-speed timer/PPU rates.
</content>
</entry>
<entry>
<title>kernel: a real timer source (64 Hz tick IRQ) + uptime(1)</title>
<updated>2026-07-18T08:10:17Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-18T08:10:04Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=0cc9b0a8bdf774ee376937d5a6767ccdced51245'/>
<id>urn:sha1:0cc9b0a8bdf774ee376937d5a6767ccdced51245</id>
<content type='text'>
The kernel had no clock: TimerISR was a reti stub, IEF_TIMER masked, and
IME was never enabled - the vectors were decorative. sys_sleep just polls
DIV deltas per-process; nothing counted globally.

Now: TAC runs the hardware timer at 16384 Hz with TMA=0, so TIMA overflows
at exactly 64 Hz; TimerISR increments a monotonic 32-bit wTicks (wraps
after ~2.1 years). Scheduling stays cooperative - the ISR is transparent.

Enabling IME in a kernel written for zero interrupts needs care wherever
SP points into memory whose bank is being switched (an IRQ pushes onto SP):
  - read_block/write_block map the disk bank over the $A000 window that
    holds the caller's stack -&gt; di/ei around the transfer (~2ms, well under
    the 15.6ms tick period, so no tick is ever lost)
  - hSwitchTo switches SVBK + cart-RAM banks under the outgoing stack -&gt;
    di on entry, ei once the incoming stack is mapped
  - fork already runs on KSTACK_TOP2 (fixed WRAM) - safe as-is
  - term_putc's SVBK switch only remaps $Dxxx, stacks live in $Axxx/$Cxxx

SYS_UPTIME (36) copies the counter (4B LE, di/ei so the read can't tear)
to a user buffer; libc gticks(); usr/uptime.c formats 'up [Nd] H:MM:SS'.
uptime avoids SDCC long div/shift entirely: sm83.lib modules link into
their own areas that land in the $A000 RAM window (latent build.sh trap,
documented there) - bytewise &gt;&gt;6 plus bounded subtraction loops instead.
</content>
</entry>
<entry>
<title>kernel: complete the process lifecycle (exit/wait/reap + bank free list)</title>
<updated>2026-07-15T22:12:43Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-15T22:12:43Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=19a2b63bab71b796ee456b3ae8bec1a2ab297158'/>
<id>urn:sha1:19a2b63bab71b796ee456b3ae8bec1a2ab297158</id>
<content type='text'>
- exit(): zombie + status, reparent orphans to init, wake blocked parent,
  schedule away forever (resources reclaimed by the reaper)
- wait(): scan for a zombie child; reap (free cart-RAM bank + PCB slot) and
  return pid/code; block PS_BLOCKED + yield if children still live; $FF if none
- cart-RAM banks are now a free list (wBankUsed bitmap): AllocRamBank/FreeRamBank
- scheduler: FindNextReady returns carry when nothing runnable; yield idles
  instead of blindly picking slot 0
- helpers: FindPcbByPid, ReparentToInit
- demo: init forks 3 workers -&gt; exec -&gt; exit(pid) -&gt; wait/reap =&gt; wwwR2R3R4!
  verified bank recycling with 6 workers over 3 banks (w2w3w4w5w6w7)
- README: document the lifecycle + syscall status
</content>
</entry>
<entry>
<title>gbos scaffold: working cooperative microkernel (verified ABAB in emulator)</title>
<updated>2026-07-15T21:44:28Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-07-15T21:44:28Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/gbos.git/commit/?id=de725da74db5cba0f9bfd0755269e1683423d87b'/>
<id>urn:sha1:de725da74db5cba0f9bfd0755269e1683423d87b</id>
<content type='text'>
- fix ClearKernelRAM clobbering the kernel stack (only clear $C000-$CBFF)
- fix SyscallTrap clobbering DE (buffer arg) during table dispatch
- README: run via ~/dev/gbc --headless; note bring-up bugs
</content>
</entry>
</feed>
