POSIX Compliance
Makar is not a UNIX system and does not claim SUS/POSIX conformance. It does, however, intentionally use a POSIX-shaped userspace model: Linux i386 syscall numbers where practical, static ELF programs, file descriptors, fork/exec/wait, signals, a small libc, and a shell that can run real scripts.
This page is written for application porters. It answers: what can a small C program rely on today, what is only a compatibility stub, and what still needs kernel work?
Current Headline
Makar currently supports:
- ring-3 ELF programs loaded by
elf_exec fork,execve,wait4,getpid,getppid- per-task file descriptor tables
open,read,write,close,lseek,stat,fstatdup,dup2,pipebrk, userspacemalloc, and anonymousmmap- basic signal delivery and user signal handlers
- UTC time APIs
- x87/SSE FPU state saved/restored per task
- one-slot i386 TLS through
set_thread_area - dynamically-linked PIEs against a shared musl
libc.so, loaded by musl’s own interpreterld-musl-i386.so.1(ET_DYN+PT_INTERP+ full auxv) - a userspace shell with pipes, redirection, list operators, background jobs,
wait, quoting, andsh -c
It does not currently support:
- users, groups, permissions, or credentials
- process groups, sessions, or job-control terminal ownership
- pthreads or clone-style user threads
- networking or sockets
- a supported in-place JIT (
tcc -run-style) execution model — TCC compiles to files andexecs them instead - complete Linux signal-mask semantics
select,poll, or another fd readiness API- a termios-compatible terminal interface
Process Model
| Feature | Status | Notes |
|---|---|---|
fork |
Present | Copy-on-write page-directory clone via task_fork. |
execve |
Present | Replaces the current image with an ELF. envp is accepted but ignored. |
wait4 |
Present | Supports WNOHANG; rusage is ignored. |
exit |
Present | Terminates the current task. |
exit_group |
Stub | Same as exit; Makar has one userspace thread per process. |
getpid, getppid |
Present | Expose task_t.pid and task_t.parent_pid. |
set_tid_address |
Stub | Returns the task pid for hosted libc startup. |
vfork, posix_spawn |
Absent | Native COW fork exists, so these are not currently needed. |
clone, pthreads |
Absent | No userspace thread groups. |
PIDs are monotonic for the boot session. The idle task is pid 1. Task slots are
reused internally after a task becomes TASK_DEAD, but pid values keep
advancing.
File Descriptors and VFS
| Feature | Status | Notes |
|---|---|---|
| fd table | Present | Each task has its own fd table. |
| stdin/stdout/stderr | Present | fd 0 = keyboard/stdin, fd 1 = terminal/stdout, fd 2 = terminal + serial/stderr. |
open |
Present | Supports common read/write/create/truncate/append flags; mode is ignored. |
read, write |
Present | File, pipe, terminal, and keyboard paths. |
close |
Present | Flushes dirty file buffers. |
lseek |
Present | SEEK_SET, SEEK_CUR, SEEK_END. |
dup |
Present | Allocates the lowest free fd. |
dup2 |
Present | Duplicates onto a requested fd, closing it first. |
pipe |
Present | 4 KiB ring with reader/writer refcounts. |
fcntl |
Partial | F_GETFL and F_SETFL; only documented bits are meaningful. |
stat, fstat |
Partial | Linux-shaped struct stat, limited fields, no permission enforcement. |
readdir |
Present | Makar-indexed syscall backing libc DIR * wrappers. |
The VFS supports ISO9660, FAT32, ext2, tmpfs, devfs, procfs, and logfs. Not
every filesystem supports every mutation. /tmp is the reliable scratch
location during live boots. On a live-CD boot the elected rootfs is the
read-only ISO9660, so the kernel overlays tmpfs at the home directories
(/root, /home, /home/user) too — home writes (~/.mxrc etc.) succeed in
RAM for the session, Ubuntu-live style; on an installed ext2/FAT32 root the real,
persistent home is used. tmpfs is multi-instance (one namespace per mount), so
these overlays never alias /tmp.
Memory APIs
| Feature | Status | Notes |
|---|---|---|
brk |
Present | Main heap-growth mechanism for the userspace malloc shim. |
mmap2 |
Anonymous + file-backed (RO shared) | Anon non-fixed = demand-paged bump window at 0x90000000. A read-only file map shares frames from the page cache (pagecache_acquire), so libc.so’s text/rodata is one copy in RAM across all mappers; writable/tmpfs file maps and anon-fixed take a private frame. Backs musl ld.so’s library maps. |
munmap |
Present | Unmaps the range and releases each frame (vmm_unmap_and_free, refcount-decrement — shared cache frames survive while others map them). Address reuse within the bump window is not implemented. |
MAP_FIXED |
Present | Maps at the caller’s exact address, replacing any existing mapping in that window. |
mprotect |
Present | SYS_MPROTECT (125) rewrites PTE R/W/USER over the range (ld.so RELRO). i386 non-PAE has no NX, so X is implicit. |
| executable mmap/JIT | Unsupported | TCC compiles to files and execs them; tcc -run is not the supported model. |
Anonymous mmap exists because hosted libc allocators, including musl paths,
expect it for larger allocations. The implementation is intentionally simple:
zero-filled frames are mapped into a bump region and are not reused during the
process lifetime.
Signals
| Feature | Status | Notes |
|---|---|---|
kill |
Present | Sends a signal to a pid. |
signal |
Present | Installs a simple handler or disposition. |
| user handlers | Present | Delivered through a userspace sigframe and sigreturn. |
| default termination | Present | Fatal default signals mark the task dead. |
sigreturn |
Present | Internal trampoline syscall. |
rt_sigprocmask |
Stub | Returns success for hosted libc startup; real masking is not complete. |
sigaction |
Absent | Use signal for now. |
sigsuspend, pause |
Absent | No blocking signal-wait API. |
| process groups | Absent | No job-control signal model. |
Signal support is good enough for current apps and tests (sigtest.elf) but
not yet a complete POSIX signal subsystem.
Time
| Feature | Status | Notes |
|---|---|---|
gettimeofday |
Present | Seconds from CMOS RTC; microseconds are PIT-derived at 10 ms resolution. |
clock_gettime |
Present | CLOCK_REALTIME and CLOCK_MONOTONIC. |
time |
Present | Userspace libc wrapper. |
gmtime, gmtime_r |
Present | Integer-only UTC conversion. |
localtime, localtime_r |
Present | Alias UTC; no timezone database. |
mktime |
Present | UTC interpretation. |
strftime |
Partial | Common numeric/date specifiers. |
nanosleep |
Absent | sleep/usleep spin-yield on the 250 Hz tick. |
There is no locale or timezone database. Treat all broken-down time as UTC.
Floating Point
The kernel initializes the x87 FPU and enables FXSAVE/FXRSTOR where available. Each task has a 512-byte FPU state area, and the scheduler saves/restores it around context switches. Floating-point state is therefore multitask-safe.
What is still missing is the userspace libc surface: there is no shipped
<math.h> implementation and no complete floating-point formatting/parsing
library.
TLS and Hosted libc Startup
Both static and dynamically-linked i386 musl startup need a small Linux-compatible substrate. Makar now provides:
- a full System-V i386 ELF auxv:
AT_PHDR,AT_PHENT,AT_PHNUM,AT_BASE,AT_ENTRY,AT_EXECFN,AT_RANDOM,AT_PAGESZ,AT_NULL set_thread_area(243)using one GDT TLS slot at selector0x33%gspreservation across interrupts- scheduler TLS restore for TLS-active tasks
writev(musl’s buffered stdio writes through it)exit_groupset_tid_addressrt_sigprocmaskstubioctlreturning-ENOTTYfutexstub for the current single-threaded bring-up assumption
For dynamic linking the loader additionally honours PT_INTERP
(/lib/ld-musl-i386.so.1, == libc.so), enters at the interpreter, and the
kernel services musl’s ld.so runtime: file-backed/MAP_FIXED mmap2,
mprotect (RELRO), and open returning -ENOENT so the library search walks.
These are compatibility pieces, not full Linux implementations. They exist to get hosted binaries through early libc initialization and dynamic relocation.
Userspace libc Headers
| Header | Current coverage | Important gaps |
|---|---|---|
<stdio.h> |
FILE * I/O, printf family subset, fd-backed reads/writes |
no wide char, no popen, incomplete buffering controls |
<stdlib.h> |
allocation, conversions, qsort, bsearch, env table, system, sscanf |
env does not cross execve; no locale/multibyte family |
<string.h> |
memory/string basics, strtok, strtok_r, strerror |
no collation/locale transforms |
<unistd.h> |
common declarations and thin wrappers: fd I/O, dup, pipe, pids, cwd, sleep |
no alarm, pause; no POSIX fork/exec wrappers yet |
<dirent.h> |
opendir, readdir, closedir |
backed by indexed syscall rather than Linux getdents |
<errno.h> |
common errno constants and global errno |
not every syscall wrapper sets errno yet |
<time.h> |
UTC broken-down time and strftime subset |
no timezone, no ctime/asctime/difftime |
<setjmp.h> |
i386 setjmp/longjmp |
no signal-mask variants |
<ctype.h> |
ASCII C-locale classifiers | no locale |
<math.h> |
absent | FPU substrate exists, library does not |
<pthread.h> |
absent | no user threading |
Shell Compatibility
The default interactive shell is /apps/sh.elf. It supports:
- variables and
$? - quoting with quote removal
sh -cif,while,for[ ... ]- pipelines
- redirection
&&,||- background
& wait
The in-kernel script interpreter is smaller. It is used for boot/test scripts
and intentionally does not support pipes, redirection, list operators, or
background jobs. Use /apps/sh.elf for scripts that need those features.
Known shell deviations:
- no command substitution
- no shell functions
- no
case - no subshell syntax
- no true job control
$expansion currently happens before tokenization, so single quotes do not fully suppress variable expansion
Terminal Model
Makar does not have a POSIX termios layer. Programs use Makar-specific
syscalls for terminal size, cursor position, drawing, raw keyboard mode, and
caret style. Virtual terminals and app tabs are managed through Makar VT
extensions and makmux.
The tty command prints Linux-shaped names:
/dev/consolefor the root console/dev/ttyNfor VT slotsnot a ttyfor unbound tasks
App-Porter Checklist
When porting a small C program:
- Prefer static builds.
- Avoid threads.
- Avoid file-backed mmap and
mprotect. - Use
/tmpfor scratch writes during live boots. - Expect all local time to be UTC.
- Avoid termios; use Makar terminal syscalls or simple stdio.
- Prefer
/apps/sh.elfif the program shells out throughsystem. - Check both return values and
errno; errno coverage is improving but not universal. - Run
alloctest.elf,libc-tcc.sh, andshell-smoke.shwhen adding libc surface. - Run
kbtestwhen changing keyboard, VT, makmux, shell focus, or app-tab behavior.