Master the fundamental concepts of build a mini kernel through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksYour mini-kernel switches between tasks using the same callee-saved register contract as userspace schedulers, but on kernel stacks allocated per task. Save rsp, switch page tables if processes differ, restore and return into the next task.
Switch steps:
rsp in task structrsp, pop registers, iret or ret depending on modelFor example, task A stack top at 0xC0401000, task B at 0xC0402000; only rsp and CR3 change between them.
The pusha/popa register save-and-restore sequence you're simulating here is exactly what xv6's swtch.S and every real x86 kernel's context switch does to move the CPU from one task's stack to another's. Forgetting to save ESP separately (pusha doesn't cover it) is a classic bug that corrupts a task's entire stack the moment it resumes, wiping out every local variable it had in flight.
Before you call the implementation done, walk failure modes on purpose. Test empty structures, single-element edge cases, maximum concurrency, and errno paths that must not crash the program. OS code usually fails in production when happy-path tests pass but invariants break under contention or memory pressure.
Keep structures small and name fields after kernel counterparts when possible. That lets you read man pages and kernel source side by side while you work. Print observable events during development; remove noisy logs once tests pass reliably.
You will write switch_to in assembly integrated with your scheduler queue. This exercise requires verifying that FPU/SSE state policy is documented (lazy vs eager).
Trace the 32-bit x86 context switch that every kernel scheduler ends up calling:
asmLoading…
The caller-saved registers are already saved by the caller, so the switch only has to save the four callee-saved ones. It then swaps stacks, and ret "returns" into the other task. A task that has never run gets a fake frame on its stack, so the same pop/ret sequence launches it at its entry point.
cLoading…
At start, task boot is running with eip 0x7c00, esp 0x9000, and all four registers zero.
STACKTOP-4 and four zero words below it, and sets the saved esp to STACKTOP-20.call), then pushes ebp, ebx, esi and edi. It saves esp into the old task, loads the new task's saved esp, pops edi, esi, ebx and ebp, and finally ret pops eip. Every push decrements esp by 4 before storing. Memory that was never written reads as 0.switch N -> N: already running, nothing to do. An unknown name prints switch N: no such task.stack N: running (esp 0x...).set on any other register prints set R: only ebp, ebx, esi and edi can be set. A duplicate spawn prints spawn N: name taken or too many tasks (the limit is 8 tasks).cLoading…
Every value is printed as 0x followed by 8 hex digits. The columns match the example exactly.
Input:
cLoading…
Output:
cLoading…
Hidden tests cover three tasks switching round-robin with different register values, a task resuming at the return address of its last call, the saved frames of sleeping tasks, switching to the running task, unknown task names, setting a caller-saved register, duplicate spawns, and stack on the running task.