include: one folder per subsystem, and includes that name it

Sixty-five headers sat side by side in include/, so `#include "irq.h"`
said nothing about where irq.h was or what it belonged to, and errno.h,
stat.h and fcntl.h at the top shadowed the system's for any host tool
built with -I./include. They are in folders now -- arch/ core/ fs/
dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and
every include names the folder, as Linux's do: "core/proc.h".

Done mechanically and checked the hard way: the kernel built from this
tree disassembles identically to the one built from the tree before
it. The full image boots, and userland is the same set of programs.
Paths in docs and comments follow; docs/guides/layout.md has a table
of what is where, and tools/fix-includes.py rewrites old-style
includes from the folders in the tree, for code written before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-23 15:05:12 +02:00
commit a1c965da1e
267 changed files with 1560 additions and 1440 deletions

View file

@ -1,58 +0,0 @@
// Small-object allocation.
//
// `kalloc()` hands out one 4096-byte page and nothing smaller, so every
// subsystem written on top of it has had to invent a fixed-size table to avoid
// asking: NPROC, NSOCK, NDEVICE, NFILE, NINODE, NBUF. Each one is a compile-
// time ceiling that fails as a refusal ("no more sockets") rather than as
// memory pressure, each one is sized by guess, and each one costs its full
// size in BSS whether the machine ever uses it or not.
//
// This is the thing they were all working around. Two interfaces over it:
//
// kmem_cache_create() a named cache of one object size, for a subsystem
// with one kind of thing. Shows up in /proc/slab under
// its own name, which is most of why it is worth
// naming.
//
// kmalloc()/kmfree() the general case, for code that does not have a
// type to build a cache around. Backed by power-of-two
// caches; kmfree() finds the right one from the
// object's own page.
//
// **Everything is backed by kalloc().** A slab is exactly one page with a
// header at the front, so freeing needs no per-object header and no search:
// the page's base address holds the slab, and the slab knows its cache. That
// is the whole trick, and it is why an object may not be larger than a page.
#ifndef KMEM_H
#define KMEM_H
// The host harness (tools/kmemtest.c) defines its own uint/uint64 before it
// gets here, and types.h collides with glibc's -- same reason kernel/dev/ttf.c
// guards its includes.
#ifndef KMEM_HOST
#include "types.h"
#endif
struct kmem_cache;
struct sbuf;
// The largest object a cache can hold: a page, less the slab header. Asking
// for more returns 0 rather than silently falling back to kalloc(), because a
// caller that wants whole pages should say so.
uint kmem_max_obj(void);
// A named cache. `size` is rounded up to the alignment; the name is kept by
// pointer and must outlive the cache, which in practice means a literal.
struct kmem_cache *kmem_cache_create(const char *name, uint size);
void *kmem_cache_alloc(struct kmem_cache *c);
void kmem_cache_free(struct kmem_cache *c, void *obj);
// The general case. kmalloc(0) is a null return, not a zero-size object.
void *kmalloc(uint n);
void kmfree(void *p);
// /proc/slab.
void kmem_stats(struct sbuf *out);
#endif /* KMEM_H */