docs/ was ten files where a plan, a description, a guide and a bug report all
sat next to each other. It is now architecture/ (what SchOS is), plan/ (what it
will be), guides/ (how to work on it) and history/ (why it is like this), with
an index that states the one rule holding it together: when something is
finished it moves from plan/ to architecture/ and is rewritten as a description
of the thing rather than a record of building it.
A ticked checkbox says the work happened. It does not say what the work
*produced*, and six months later the checkbox is all that is left. The network
stack proved the point: finished, verified end to end, and for a month the only
description of it anywhere was a checkbox four levels of indentation deep.
So roadmap.md went from 534 lines to 181 -- nothing deleted, the done work
graduated. Seven subsystems that were finished and undescribed now have
descriptions: boot, kernel, syscalls, filesystem, networking, graphics, usb,
init. Every one ends with "What it does not do", which is the section that pays;
a document listing only strengths is marketing, and the reader who needs it most
is the one about to trip over a limitation nobody wrote down.
schfs.md still opened with "phases 1 through 3 1/2 are done, phase 4 is next"
long after all five had landed. It is a description now, with the phase record
and the hard-won bugs moved to history/.
Three corrections found on the way, all load-bearing:
* projects/schcom/README.md claimed SCM_RIGHTS was done. There is no
sendmsg/recvmsg in the kernel at all, and an entire GUI plan rested on it.
* The root README said "No TCP/IP" months after the stack landed.
* history/kernel.md sec.7 was marked "in progress" on a problem that process
groups solved.
Also adds plan/1.0.md, which draws a finish line so the open list stops being
infinite, and marks schwm/ and schde/ superseded: in Wayland the compositor is
the window manager, so that split dissolves rather than being abandoned.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
102 lines
5.4 KiB
Markdown
102 lines
5.4 KiB
Markdown
# The system, layer by layer
|
|
|
|
What SchOS is today. Everything in this directory is built and running; what is
|
|
merely intended lives in [../plan/](../plan/).
|
|
|
|
---
|
|
|
|
## The names, and what each one covers
|
|
|
|
`uname -s` reports `SchIFT`, the way every Unix reports its kernel rather than
|
|
its distribution.
|
|
|
|
| Layer | Name | What it is |
|
|
|---|---|---|
|
|
| System | **SchOS** | The distribution — kernel, userland, tooling |
|
|
| Kernel | **SchIFT** | Multi-core x86-64 kernel with a modular VFS |
|
|
| Filesystem | **SchFS** | Transactional, copy-on-write, the root filesystem |
|
|
| API | **SchAPI** | The native programming interface — *designed, not built* |
|
|
| Compositor | **Schcom** | Owns the display; v0 runs |
|
|
|
|
---
|
|
|
|
## The stack, bottom to top
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────┐
|
|
│ toybox mksh musl first-party cmd/ │ userland
|
|
├─────────────────────────────────────────────────┤
|
|
│ schinit — PID 1, job manifests, supervision │
|
|
├─────────────────────────────────────────────────┤
|
|
│ syscall table — Linux numbering, one .inc file │ ← the ABI seam
|
|
╞═════════════════════════════════════════════════╡
|
|
│ VFS │ sockets │ signals │ mmap │ poll │ procfs │
|
|
├──────┴─────────┴─────────┴──────┴──────┴────────┤
|
|
│ SchFS │ lwIP │ text/gfx │ buffer cache │
|
|
├─────────┴────────┴────────────┴─────────────────┤
|
|
│ device model — class vtables, bus binding │
|
|
├─────────────────────────────────────────────────┤
|
|
│ drivers: xHCI e1000 virtio-gpu VBE IDE PS/2│
|
|
├─────────────────────────────────────────────────┤
|
|
│ scheduler │ paging │ traps │ IRQ │ SMP │ DMA │ SchIFT core
|
|
└─────────────────────────────────────────────────┘
|
|
▲
|
|
UEFI loader (boot/uefi)
|
|
```
|
|
|
|
The two seams that matter are the syscall table and the device model. Above the
|
|
first, software is ordinary and portable — musl and toybox are unmodified.
|
|
Below the second, a driver never names its consumer and a consumer never names a
|
|
driver.
|
|
|
|
---
|
|
|
|
## Where it came from
|
|
|
|
SchOS began as [xv6](https://github.com/mit-pdos/xv6-public) and is now mostly
|
|
something else. What survives from xv6 is the *shape* of the process table, the
|
|
sleep/wakeup discipline, and the buffer cache. What has been replaced: the
|
|
scheduler and trap path (rewritten for x86-64 and for more than one processor),
|
|
the memory manager, the entire filesystem, the syscall layer, and every driver.
|
|
|
|
That inheritance is worth knowing when reading the code, because the parts that
|
|
still look like xv6 follow xv6's conventions and the parts that do not, do not.
|
|
|
|
---
|
|
|
|
## The documents
|
|
|
|
Read in this order if you are new:
|
|
|
|
| | |
|
|
|---|---|
|
|
| [boot.md](boot.md) | Firmware to the first userspace process. The shortest path through the whole system. |
|
|
| [kernel.md](kernel.md) | Memory, processes, scheduling, traps, signals, SMP. |
|
|
| [syscalls.md](syscalls.md) | The one table everything is generated from, and how a musl binary runs unmodified. |
|
|
| [filesystem.md](filesystem.md) | The VFS, the buffer cache, mounts, procfs. |
|
|
| [schfs.md](schfs.md) | The copy-on-write root filesystem. |
|
|
| [devices.md](devices.md) | Buses, classes, binding, and the vtables consumers talk to. |
|
|
| [usb.md](usb.md) | xHCI, the USB core, and the three class drivers. |
|
|
| [graphics.md](graphics.md) | Framebuffer, text rendering, the console, and PSOGM. |
|
|
| [networking.md](networking.md) | NIC drivers, lwIP, and both socket families. |
|
|
| [init.md](init.md) | `schinit` and the job manifests. |
|
|
|
|
---
|
|
|
|
## Three rules that hold across all of it
|
|
|
|
**The kernel and the host tools compile the same SchFS source.** `mkschfs`
|
|
cannot disagree with the kernel about the on-disk format, because there is only
|
|
one implementation. Format bugs are found on the host, where a test takes a
|
|
second instead of a boot.
|
|
|
|
**Syscalls are declared in exactly one place.** `kernel/sys/table.inc`.
|
|
The constants, the dispatch table and the Linux translation map are all
|
|
generated from it, so a syscall cannot be half-registered.
|
|
|
|
**A list you can read beats a list assembled by side effects.** Drivers are
|
|
written out by hand in `kernel/drivers/registry.c` rather than collected by a
|
|
linker section, and platform devices are registered in one function rather than
|
|
inside each driver's init. The tradeoff is deliberate: self-registration is
|
|
nicer to write, and it means the list of what is in your kernel is not written
|
|
down anywhere you can read.
|