Rename Schunix to SchOS; the kernel becomes SchIFT

Removes the "-unix" element and with it any trademark exposure to The
Open Group.

The split follows the ecosystem layout: SchOS is the system, and the
kernel has its own name. Kernel-identity strings are the only places
that take SchIFT -- uname(2) sysname, /proc/version, and the two licence
sentences that say "kernel" outright. That is what every Unix does here:
`uname -s` on Linux reports the kernel, not the distribution. Everything
a user reads as the product -- panic screen, boot menu, error prefixes,
docs, LICENSE, NOTICE -- is SchOS.

schunix.img is schos.img, the logo assets and the musl TLS patch are
renamed, and __SCHUNIX__ is __SCHOS__ (the define and the patch that
consumes it moved together).

Two things the rename broke, both found by the bootcheck suite:

  - shmtest wrote "SCHUNIX-MMAP-OK" with a hardcoded length of 15 and
    compared it back by hand-counted offsets (m[3]=='U', m[14]=='K').
    The shorter marker left the write running two bytes past the literal
    and the compare reading past the data, failing a file-backed mmap
    that was working correctly. Now written and compared through one
    constant with sizeof.
  - bootcheck asserted a 31-byte file after appending to
    "hello-from-schunix"; the shorter string makes it 29.

Both are the same mistake: a string literal whose length is written out
somewhere else. Full suite green -- base, Tty, Ps, Sock, Fb, Usb, Evdev.
This commit is contained in:
Nexoniarz 2026-08-09 14:09:59 +02:00
commit e04ca28812
83 changed files with 520 additions and 601 deletions

View file

@ -1,5 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Schunix ports — third-party software, one directory per port.
# SchOS ports — third-party software, one directory per port.
# All ports are permissive-licensed (MIT, BSD, 0BSD, Apache 2.0).
#
# ports/musl/ libc — installs headers/libs to build/ports/musl/prefix
@ -15,7 +15,7 @@
# Ports that live in this directory but are deliberately not built by `make`.
# Empty for now; the filter stays because the reason it existed will recur --
# a port whose licence cannot be combined with Apache-2.0 can be kept here for
# local testing but must never be built into a Schunix image.
# local testing but must never be built into a SchOS image.
NOTPORTS :=
PORTS := $(filter-out $(NOTPORTS), \
$(patsubst %/,%,$(sort $(dir $(wildcard */Makefile)))))

View file

@ -1,5 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
# Shared definitions for all Schunix ports.
# Shared definitions for all SchOS ports.
# Include this at the top of each port's Makefile: include ../mk/port.mk
#
# Layout contract — a port directory contains ONLY hand-written files:

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: Apache-2.0
# mksh (MirBSD Korn Shell) — permissive: https://www.mirbsd.org/mksh.htm
# Installed as /bin/sh — Schunix standardizes on "sh" as the one shell name;
# Installed as /bin/sh — SchOS standardizes on "sh" as the one shell name;
# no ksh/dash/other aliases are installed or looked up by init.
include ../mk/port.mk
@ -10,7 +10,7 @@ MKSH_URL := http://www.mirbsd.org/MirOS/dist/mir/mksh/mksh-$(MKSH_VERSION).t
TARBALL := $(DISTDIR)/mksh-$(MKSH_VERSION).tgz
CFLAGS := -static -D__SCHUNIX__ -I$(MUSL)/include -fno-stack-protector
CFLAGS := -static -D__SCHOS__ -I$(MUSL)/include -fno-stack-protector
LDFLAGS := -static -L$(MUSL)/lib -lc
$(TARBALL): | $(DISTDIR)

View file

@ -27,8 +27,8 @@ $(SRCDIR): $(TARBALL)
# so creating it bumps that directory's mtime — making the directory forever
# newer than the stamp it contains, and re-running this rule on every single
# build. The second run then fails, because the patch does not apply twice.
$(SRCDIR)/.patched: patches/0001-schunix-tls.patch | $(SRCDIR)
cd $(SRCDIR) && patch -p1 < $(CURDIR)/patches/0001-schunix-tls.patch
$(SRCDIR)/.patched: patches/0001-schos-tls.patch | $(SRCDIR)
cd $(SRCDIR) && patch -p1 < $(CURDIR)/patches/0001-schos-tls.patch
touch $@
$(BUILDDIR)/config.mak: $(SRCDIR)/.patched
@ -37,7 +37,7 @@ $(BUILDDIR)/config.mak: $(SRCDIR)/.patched
--prefix=$(PREFIX) \
--disable-shared \
CC=$(CC) \
CFLAGS="-D__SCHUNIX__ -fno-stack-protector"
CFLAGS="-D__SCHOS__ -fno-stack-protector"
$(BUILDDIR)/lib/libc.a: $(BUILDDIR)/config.mak
$(MAKE) -C $(BUILDDIR)

View file

@ -1,13 +1,13 @@
From: Schunix Project <kernel@schunix.org>
Subject: [PATCH] schunix: TLS via global, mallocng decls, optional malloc tracing
From: SchOS Project <kernel@schos.org>
Subject: [PATCH] schos: TLS via global, mallocng decls, optional malloc tracing
Three local changes to musl 1.2.5, kept in one patch because they are all
"make musl work on Schunix" and share a lifetime.
"make musl work on SchOS" and share a lifetime.
1. arch/x86_64/pthread_arch.h, src/env/__init_tls.c - TLS.
Schunix's kernel saves/restores FS_BASE at the syscall boundary, so
SchOS's kernel saves/restores FS_BASE at the syscall boundary, so
arch_prctl(ARCH_SET_FS) is safe from userspace. __get_tp() is redirected
through a global uintptr_t (__schunix_tp) set at the START of __init_tp(),
through a global uintptr_t (__schos_tp) set at the START of __init_tp(),
before __set_thread_area() is called. The rest of __init_tp() runs
normally so td->locale and the other pthread fields still initialise.
@ -20,17 +20,17 @@ Three local changes to musl 1.2.5, kept in one patch because they are all
3. src/malloc/mallocng/meta.h, malloc.c - diagnostics, inert by default.
get_meta()/alloc_group() tracing that dumps group/meta pointers to fd 2,
entirely inside #ifdef SCHUNIX_MALLOC_DEBUG, which nothing defines. Kept
entirely inside #ifdef SCHOS_MALLOC_DEBUG, which nothing defines. Kept
because this is the instrumentation that resolved the boot-crash
investigation in docs/architecture/kernel-history.md section 1; build
with -DSCHUNIX_MALLOC_DEBUG to re-enable.
with -DSCHOS_MALLOC_DEBUG to re-enable.
--- a/arch/x86_64/pthread_arch.h 2024-03-01 03:07:33.000000000 +0100
+++ b/arch/x86_64/pthread_arch.h 2026-08-01 19:11:51.533102649 +0200
@@ -1,8 +1,13 @@
+#ifdef __SCHUNIX__
+extern uintptr_t __schunix_tp;
+static inline uintptr_t __get_tp() { return __schunix_tp; }
+#ifdef __SCHOS__
+extern uintptr_t __schos_tp;
+static inline uintptr_t __get_tp() { return __schos_tp; }
+#else
static inline uintptr_t __get_tp()
{
@ -47,18 +47,18 @@ Three local changes to musl 1.2.5, kept in one patch because they are all
volatile int __thread_list_lock;
+#ifdef __SCHUNIX__
+uintptr_t __schunix_tp;
+#ifdef __SCHOS__
+uintptr_t __schos_tp;
+#endif
+
int __init_tp(void *p)
{
pthread_t td = p;
td->self = td;
+ // Set __schunix_tp for __get_tp() before calling __set_thread_area.
+ // Set __schos_tp for __get_tp() before calling __set_thread_area.
+ // The kernel now correctly saves/restores FS_BASE at the syscall boundary.
+#ifdef __SCHUNIX__
+ __schunix_tp = (uintptr_t)TP_ADJ(p);
+#ifdef __SCHOS__
+ __schos_tp = (uintptr_t)TP_ADJ(p);
+#endif
int r = __set_thread_area(TP_ADJ(p));
if (r < 0) return -1;
@ -82,20 +82,20 @@ Three local changes to musl 1.2.5, kept in one patch because they are all
#include <limits.h>
#include "glue.h"
+#ifdef SCHUNIX_MALLOC_DEBUG
+static void schunix_hex(char *out, uint64_t v) {
+#ifdef SCHOS_MALLOC_DEBUG
+static void schos_hex(char *out, uint64_t v) {
+ static const char digits[] = "0123456789abcdef";
+ for (int i = 15; i >= 0; i--) { out[i] = digits[v & 0xf]; v >>= 4; }
+}
+static void schunix_dbg(const char *tag, uint64_t a, uint64_t b, uint64_t c) {
+static void schos_dbg(const char *tag, uint64_t a, uint64_t b, uint64_t c) {
+ char buf[128];
+ int n = 0;
+ buf[n++]='['; buf[n++]='D'; buf[n++]='B'; buf[n++]='G'; buf[n++]=']'; buf[n++]=' ';
+ for (const char *p = tag; *p; p++) buf[n++] = *p;
+ buf[n++]=' ';
+ schunix_hex(buf+n, a); n += 16; buf[n++]=' ';
+ schunix_hex(buf+n, b); n += 16; buf[n++]=' ';
+ schunix_hex(buf+n, c); n += 16; buf[n++]='\n';
+ schos_hex(buf+n, a); n += 16; buf[n++]=' ';
+ schos_hex(buf+n, b); n += 16; buf[n++]=' ';
+ schos_hex(buf+n, c); n += 16; buf[n++]='\n';
+ __syscall(SYS_write, 2, buf, n);
+}
+#endif
@ -107,13 +107,13 @@ Three local changes to musl 1.2.5, kept in one patch because they are all
}
const struct group *base = (const void *)(p - UNIT*offset - UNIT);
const struct meta *meta = base->meta;
+#ifdef SCHUNIX_MALLOC_DEBUG
+ schunix_dbg("get_meta p", (uint64_t)p, (uint64_t)offset, (uint64_t)index);
+#ifdef SCHOS_MALLOC_DEBUG
+ schos_dbg("get_meta p", (uint64_t)p, (uint64_t)offset, (uint64_t)index);
+ {
+ volatile uint64_t *rawbase = (volatile uint64_t *)base;
+ schunix_dbg("get_meta RAW reread base[0..2]", rawbase[0], rawbase[1], rawbase[2]);
+ schos_dbg("get_meta RAW reread base[0..2]", rawbase[0], rawbase[1], rawbase[2]);
+ }
+ schunix_dbg("get_meta base/meta/meta->mem", (uint64_t)base, (uint64_t)meta, (uint64_t)meta->mem);
+ schos_dbg("get_meta base/meta/meta->mem", (uint64_t)base, (uint64_t)meta, (uint64_t)meta->mem);
+#endif
assert(meta->mem == base);
assert(index <= meta->last_idx);
@ -124,9 +124,9 @@ Three local changes to musl 1.2.5, kept in one patch because they are all
m->last_idx = cnt-1;
m->freeable = 1;
m->sizeclass = sc;
+#ifdef SCHUNIX_MALLOC_DEBUG
+ schunix_dbg("alloc_group p/m/cnt", (uint64_t)p, (uint64_t)m, (uint64_t)cnt);
+ schunix_dbg("alloc_group readback mem->meta", (uint64_t)m->mem, (uint64_t)m->mem->meta, (uint64_t)sc);
+#ifdef SCHOS_MALLOC_DEBUG
+ schos_dbg("alloc_group p/m/cnt", (uint64_t)p, (uint64_t)m, (uint64_t)cnt);
+ schos_dbg("alloc_group readback mem->meta", (uint64_t)m->mem, (uint64_t)m->mem->meta, (uint64_t)sc);
+#endif
return m;
}

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: Apache-2.0
# toybox — 0BSD-licensed: https://landley.net/toybox/
# Provides Schunix's core utilities (ls, cat, cp, mv, rm, mkdir, ...) as a
# Provides SchOS's core utilities (ls, cat, cp, mv, rm, mkdir, ...) as a
# single multicall binary, installed under sysroot/bin/ once per applet name.
#
# mkfs (tools/mkfs.c) doesn't understand symlinks or hardlink dedup — each
@ -16,7 +16,7 @@ TOYBOX_SHA256 := ad88a921133ae2231d9f2df875ec0bd42af4429145caea7d7db9e02208a6fd
TARBALL := $(DISTDIR)/toybox-$(TOYBOX_VERSION).tar.gz
CFLAGS := -static -D__SCHUNIX__ -I$(MUSL)/include -fno-stack-protector
CFLAGS := -static -D__SCHOS__ -I$(MUSL)/include -fno-stack-protector
LDFLAGS := -static -L$(MUSL)/lib -lc
# The applet list is not hard-coded any more: `toybox` with no arguments prints