# PikeOS POSIX Implementation Deep Audit ## Architecture Overview PikeOS implements POSIX (PSE51 profile) via a **3-layer architecture**: 1. **PikeOS Microkernel** (`sources/ukernel-x86_amd64/`) — Raw syscall interface (119 syscalls), IPC, thread/task/memory management 2. **P4EXT / PSSW** (`sources/p4ext/`, `sources/ssw/`) — Process extension layer: heap, vmem, threads, stack management, ELF loading 3. **POSIX Personality Library** (`target/x86/amd64/posix/`) — PSE51-compliant POSIX API (pthread, signal, mq, sem, mmap, file I/O, time) **Key Design:** PikeOS has NO fork/exec/wait/exit in the traditional Unix sense. POSIX processes are **PikeOS tasks** (statically partitioned at system configuration time). Threads are PikeOS threads. The POSIX personality is a library that wraps PikeOS kernel primitives. --- ## 1. PROCESS LIFECYCLE (fork/exec/wait/exit) ### ❌ NOT IMPLEMENTED (by design) - `fork()`, `exec()`, `wait()`, `waitpid()`, `posix_spawn()` — **DO NOT EXIST** in PikeOS POSIX - PikeOS is a **statically partitioned** RTOS. Processes (partitions) are defined at configuration time - `_POSIX_SPAWN = -1` (explicitly disabled) - `_POSIX_JOB_CONTROL = -1` (explicitly disabled) ### ✅ What exists instead: - **Task activation**: `p4_task_activate()` → `P4_SYSCALL_TASK_ACTIVATE` (syscall #4) - **Task start**: `p4_task_start()` → `P4_SYSCALL_TASK_START` (syscall #5) - **Task terminate**: `p4_task_terminate()` → `P4_SYSCALL_TASK_TERMINATE` (syscall #6) - **ELF loading**: `sources/ssw/src/app.c` — `app_load()` loads ELF executables from ROM FS - **Process entry**: `sources/p4ext/src/entry.c` — `_p4_entry()` initializes: proc, diag, config, heap, vmem, stack, malloc, threads, args, then calls `main()` ### Files: | File | Purpose | |------|---------| | `sources/ukernel-x86_amd64/include/kernel/p4task_user.h` | Task API (activate, start, terminate, donate) | | `sources/p4ext/src/entry.c` | Process entry point (`_p4_entry()`) | | `sources/ssw/src/app.c` | ELF loader (`app_load()`) | | `target/x86/amd64/posix/src/posix_config.c` | POSIX process configuration | --- ## 2. THREADING (pthread) ### ✅ FULLY IMPLEMENTED PikeOS POSIX provides complete PSE51 threading: **Header:** `target/x86/amd64/posix/include/pthread.h` **Functions declared:** - `pthread_create()`, `pthread_join()`, `pthread_detach()`, `pthread_exit()` - `pthread_self()`, `pthread_equal()`, `pthread_cancel()` - `pthread_setcancelstate()`, `pthread_setcanceltype()`, `pthread_testcancel()` - `pthread_cleanup_push()`, `pthread_cleanup_pop()` - `pthread_atfork()` (stub — no fork support) **Attributes:** - `pthread_attr_init/destroy/get*/set*()` — detachstate, guardsize, inheritsched, schedparam, schedpolicy, scope, stack, stackaddr, stacksize - `pthread_attr_getname_np()`, `pthread_attr_getschedquantum_np()` — PikeOS extensions **Scheduling policies:** - `SCHED_RR` (0), `SCHED_FIFO` (1), `SCHED_OTHER` (2) - `PTHREAD_SCOPE_PROCESS` only (no `PTHREAD_SCOPE_SYSTEM`) **Cancellation:** - `PTHREAD_CANCEL_ENABLE/DISABLE`, `PTHREAD_CANCEL_DEFERRED/ASYNCHRONOUS` - `PTHREAD_CANCELED` = `0x777` ### Kernel Integration: - Thread creation: `p4ext_thr_create()` → `p4_thread_create_syscall()` → `P4_SYSCALL_THR_CREATE` (syscall #9) - Thread deletion: `P4_SYSCALL_THR_DELETE` (syscall #10) - Thread yield: `P4_SYSCALL_THR_YIELD` (syscall #11) - Thread register exchange: `P4_SYSCALL_THR_EX_REGS` (syscall #12) - Thread scheduling exchange: `P4_SYSCALL_THR_EX_SCHED` (syscall #14) - Thread stop/resume: `P4_SYSCALL_THR_STOP/RESUME` (syscalls #17/#18) - Thread affinity: `P4_SYSCALL_THR_EX_AFFINITY` (syscall #67) ### Implementation files: | File | Purpose | |------|---------| | `sources/p4ext/src/thr_create.c` | `p4ext_thr_create()` — thread creation with stack allocation | | `sources/p4ext/src/threads.c` | Thread descriptor management, TLS init | | `sources/p4ext/src/thr_exit.c` | Thread exit | | `sources/p4ext/src/thr_tls.c` | Thread-local storage | | `sources/p4ext/src/thr_num.c` | Thread number allocation | | `sources/p4ext/src/thr_reclaim.c` | Thread resource reclamation | | `sources/p4ext/src/stack.c` / `stack_create.c` | Stack pool management | | `sources/ukernel-x86_amd64/lib/stubs/p4_thread_create_syscall.S` | Syscall stub | --- ## 3. SYNCHRONIZATION (Mutex, Cond, Sem, RWLock) ### ✅ FULLY IMPLEMENTED **Mutex** (`P4_MUTEX_*`): - Kernel: `p4_mutex_init()`, `p4_mutex_lock()`, `p4_mutex_trylock()`, `p4_mutex_unlock()` - Flags: `P4_MUTEX_SHARED`, `P4_MUTEX_RECURSIVE`, `P4_MUTEX_CANCELABLE`, `P4_MUTEX_ROBUST` - Priority protocols: `PTHREAD_PRIO_NONE`, `PTHREAD_PRIO_INHERIT`, `PTHREAD_PRIO_PROTECT` - Types: `PTHREAD_MUTEX_NORMAL`, `PTHREAD_MUTEX_ERRORCHECK`, `PTHREAD_MUTEX_RECURSIVE` - Static init: `PTHREAD_MUTEX_INITIALIZER`, `PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP` **Condition Variables** (`P4_COND_*`): - Kernel: `p4_cond_init()`, `p4_cond_wait()`, `p4_cond_wake()` - Flags: `P4_COND_SHARED`, `P4_COND_PRIO`, `P4_COND_WAKE_ALL` - Static init: `PTHREAD_COND_INITIALIZER` **Read-Write Locks:** - `pthread_rwlock_init/destroy/rdlock/wrlock/tryrdlock/trywrlock/unlock()` - Static init: `PTHREAD_RWLOCK_INITIALIZER` **Semaphores** (`sem_*`): - `sem_init()`, `sem_destroy()`, `sem_open()`, `sem_close()`, `sem_unlink()` - `sem_wait()`, `sem_trywait()`, `sem_timedwait()`, `sem_post()`, `sem_getvalue()` - Kernel: `P4_sem_t` with `p4_sem_init()`, `p4_sem_lock()`, `p4_sem_trylock()`, `p4_sem_unlock()` - Max count: `P4_SEM_MAX_COUNT = 0x7fff` **Wait Queues** (kernel-level): - `p4_waitq_init()`, `p4_waitq_wait()`, `p4_waitq_wake()` — `P4_SYSCALL_WAITQ_*` (syscalls #105-108) **ULock** (low-level): - `P4_SYSCALL_ULOCK_WAIT` (#72), `P4_SYSCALL_ULOCK_WAKE` (#73) — futex-like primitives ### Kernel stubs: | File | Syscall | |------|---------| | `sources/ukernel-x86_amd64/include/kernel/p4mutex_user.h` | Mutex API | | `sources/ukernel-x86_amd64/include/kernel/p4cond_user.h` | Condvar API | | `sources/ukernel-x86_amd64/include/kernel/p4sem_user.h` | Semaphore API | | `sources/ukernel-x86_amd64/include/kernel/p4ulock_user.h` | ULock (futex) API | | `sources/ukernel-x86_amd64/include/kernel/p4waitq_user.h` | Wait queue API | --- ## 4. SIGNAL HANDLING ### ✅ IMPLEMENTED (PSE51 subset) **Header:** `target/x86/amd64/posix/include/signal.h` **Signals defined (32 standard + 32 realtime):** - Standard: SIGHUP(1), SIGINT(2), SIGQUIT(3), SIGILL(4), SIGTRAP(5), SIGABRT(6), SIGBUS(7), SIGFPE(8), SIGKILL(9), SIGUSR1(10), SIGSEGV(11), SIGUSR2(12), SIGALRM(14), SIGTERM(15), SIGSYS(31) - Extensions: SIGPIPE, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGIO, SIGPOLL (only when `__BSD_VISIBLE`) - Realtime: `SIGRTMIN=33`, `SIGRTMAX=64` **Functions declared:** - `sigaction()`, `signal()` — signal handler installation - `sigprocmask()`, `pthread_sigmask()` — signal mask manipulation (SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK) - `sigpending()`, `sigsuspend()` — signal set operations - `sigwait()`, `sigwaitinfo()`, `sigtimedwait()` — synchronous signal waiting - `sigqueue()` — realtime signal queuing - `kill()`, `pthread_kill()` — signal sending - `sigemptyset()`, `sigfillset()`, `sigaddset()`, `sigdelset()`, `sigismember()` — signal set manipulation **Signal info:** - `SI_NOINFO` (0x10000), `SI_USER` (0x10001), `SI_QUEUE` (0x10002), `SI_TIMER` (0x10003), `SI_ASYNCIO` (0x10004), `SI_MESGQ` (0x10005) - `siginfo_t`: si_signo, si_code, si_value, si_addr (extension) **Configuration:** - `max_sig_entries = 32` — max simultaneous signal handlers - `sig_stack_size = 4 * PAGE_SIZE` — separate signal handler stack - `sigqueue_max = 64` — max queued signals --- ## 5. MEMORY MANAGEMENT (mmap/munmap/mprotect/brk) ### ⚠️ PARTIALLY IMPLEMENTED **Header:** `target/x86/amd64/posix/include/sys/mman.h` **Implemented:** - `mmap()` — maps shared memory from configured pools - `munmap()` — unmaps memory - `mlock()`, `munlock()`, `mlockall()`, `munlockall()` — **no-ops** (memory locked by design, no demand paging) - `msync()` — **no-op** - `shm_open()`, `shm_unlink()` — shared memory objects (statically configured) - `PROT_NONE/READ/WRITE/EXEC`, `MAP_SHARED/FIXED` **NOT Implemented:** - `mprotect()` — `_POSIX_MEMORY_PROTECTION = 200112L` but "Function mprotect() not implemented" - `MAP_PRIVATE` — "unsupported on PikeOS" - `brk()`, `sbrk()` — replaced by heap pool management **Kernel memory syscalls:** - `P4_SYSCALL_MEM_MAP` (#32), `P4_SYSCALL_MEM_UNMAP` (#33), `P4_SYSCALL_MEM_SET_ATTR` (#34) - `P4_SYSCALL_MEM_CREATE` (#36), `P4_SYSCALL_MEM_CLEAR` (#66) - `P4_SYSCALL_ALLOC_PHYS` (#47), `P4_SYSCALL_ALLOC_ALIGNED` (#48) **Heap management (P4EXT):** - `sources/p4ext/src/heap.c` — `_heap_init()`, `sbrk()` implementation using SSW memory pools - `sources/p4ext/src/vmem.c` — `_vmem_init()`, `p4ext_vmem_alloc()` — page-aligned virtual memory allocation - `sources/p4ext/src/region.c` — Region allocator for virtual address space - `sources/p4ext/src/malloc_impl.c` — malloc/free implementation on top of heap - `sources/ssw/src/mem.c` — PSSW memory configuration and mapping **Configuration (`posix_config.c`):** - `stack_pool_addr/size` — thread stack memory pool - `shm_pool_addr/size` — shared memory pool (for mmap) - `heap_pool_addr/size` — heap memory pool (for malloc) - `heap_pool_chunk` — allocation granularity --- ## 6. IPC MECHANISMS ### 6a. Message Queues ✅ IMPLEMENTED **Header:** `target/x86/amd64/posix/include/mqueue.h` **Functions:** `mq_open()`, `mq_close()`, `mq_unlink()`, `mq_send()`, `mq_receive()`, `mq_timedsend()`, `mq_timedreceive()`, `mq_getattr()`, `mq_setattr()`, `mq_notify()` **Configuration:** `mq_max_msgs=32`, `mq_max_msg_len=256`, `num_mq=8` (static allocation) **File type:** `LCL_MQ` (in `dev_type_t` enum) ### 6b. Shared Memory ✅ IMPLEMENTED (static) - `shm_open()`, `shm_unlink()` — declared in `sys/mman.h` - `_POSIX_SHARED_MEMORY_OBJECTS = 200112L` - "Shared memory objects can not be dynamically created or destroyed" - File type: `RMT_SHM` (remote shared memory segments) ### 6c. Pipes ✅ IMPLEMENTED (local) - File type: `LCL_PIPE` in `dev_type_t` - `pipe()` function available - Used internally for console I/O buffering ### 6d. PikeOS Native IPC (kernel-level) **Header:** `sources/ukernel-x86_amd64/include/kernel/p4ipc_user.h` - `p4_ipc()` — combined send/receive IPC (`P4_SYSCALL_IPC` #23) - Supports: copied data (`buf`/`buf_size`) + memory mappings (`map`/`map_size`) - `P4_SYSCALL_COMM_GRANT` (#20) — grant communication rights - `P4_SYSCALL_COMM_LINK` (#21) — link communication - `P4_SYSCALL_IPC_MASK` (#22) — set IPC mask - `P4_SYSCALL_EV_WAIT/SIGNAL/MASK` (#25-26, #24) — event notification ### 6e. Semaphores — See Section 3 --- ## 7. FILE OPERATIONS ### ✅ IMPLEMENTED (via VFS layer) **File description structure:** `sources/ssw/include/vm_se_file.h` / `target/x86/amd64/posix/include/sys/fs_file.h` **`struct _file`** — open file description with: - `f_ops` (method table), `f_provider`, `f_pos`, `f_flags`, `f_type`, `f_count` - Reference counting via `_fs_fref()`, `_fs_frele()` - File types: `NULL_DEV`, `LCL_DEV`, `LCL_FILE`, `LCL_PIPE`, `LCL_SOCKET`, `LCL_MQ`, `LCL_SEM`, `RMT_DEV`, `RMT_FILE`, `RMT_SOCKET`, `RMT_PROP`, `RMT_SHM` **Kernel device syscalls (KDEV):** - `P4_SYSCALL_KDEV_OPEN` (#80), `P4_SYSCALL_KDEV_CLOSE` (#86) - `P4_SYSCALL_KDEV_READ` (#88), `P4_SYSCALL_KDEV_WRITE` (#89) - `P4_SYSCALL_KDEV_LSEEK` (#111), `P4_SYSCALL_KDEV_STATVFS` (#116) - `P4_SYSCALL_KDEV_UNLINK` (#112), `P4_SYSCALL_KDEV_RENAME` (#113) - `P4_SYSCALL_KDEV_DIR_CREATE` (#114), `P4_SYSCALL_KDEV_DIR_READ` (#115) - `P4_SYSCALL_KDEV_DUP` (#79), `P4_SYSCALL_KDEV_CONTROL` (#91) (ioctl) - `P4_SYSCALL_KDEV_PSTAT` (#87), `P4_SYSCALL_KDEV_PSYNC` (#93) **PSSW file operations:** `sources/ssw/libvm/` - `vm_open.c`, `vm_open_at.c`, `vm_close.c`, `vm_read.c`, `vm_read_at.c` - `vm_lseek.c`, `vm_fstat.c`, `vm_fsync.c`, `vm_ftruncate.c` - `vm_ioctl.c`, `vm_rename.c`, `vm_unlink.c`, `vm_stat.c`, `vm_statvfs.c` - `vm_dir_open.c`, `vm_dir_close.c`, `vm_dir_read_at.c`, `vm_dir_create.c`, `vm_dir_rewind.c`, `vm_dir_sync.c` --- ## 8. TIME FUNCTIONS ### ✅ IMPLEMENTED **Header:** `target/x86/amd64/posix/include/time.h` **Clocks:** - `CLOCK_REALTIME` (0) — supported - `CLOCK_THREAD_CPUTIME_ID` (0x80000000) — "does not support timers" - `CLOCK_PROCESS_CPUTIME_ID` (0x40000000) — "does not support timers" **Functions declared:** - `clock_gettime()`, `clock_settime()`, `clock_getres()` - `timer_create()`, `timer_delete()`, `timer_settime()`, `timer_gettime()`, `timer_getoverrun()` - `nanosleep()`, `clock_nanosleep()` - `clock()` — `CLOCKS_PER_SEC = 1000000` - `time()`, `difftime()`, `mktime()`, `asctime()`, `ctime()`, `gmtime()`, `localtime()`, `strftime()` **Timer configuration:** `num_of_timers = 64` **Kernel time syscall:** - `P4_SYSCALL_GET_TIME` (#55) - `P4_SYSCALL_GET_TS` (#74) - `P4_SYSCALL_SLEEP` (#2) - `P4_SYSCALL_THR_ALARM` (#77) --- ## 9. SCHEDULING ### ✅ IMPLEMENTED **Header:** `target/x86/amd64/posix/include/sched.h` **Policies:** `SCHED_RR` (0), `SCHED_FIFO` (1), `SCHED_OTHER` (2) **Functions:** `sched_yield()`, `sched_get_priority_max()`, `sched_get_priority_min()`, `sched_rr_get_interval()` **Configuration:** - `sched_rr_quantum_ticks = 1`, `sched_tick_duration = 20ms` - `sched_other_quantum_ticks = 1` - `base_prio = 1`, `base_prio_mcp_off = 32` - `_POSIX_PRIORITY_SCHEDULING = 200112L` --- ## 10. POSIX CONFIGURATION (`_configurables` structure) **File:** `target/x86/amd64/posix/include/sys/posix_config.h` + `target/x86/amd64/posix/src/posix_config.c` **Key parameters:** | Parameter | Default | Purpose | |-----------|---------|---------| | `pthread_default_priority` | 10 | Default thread priority | | `pthread_default_stack_size` | 4*PAGE_SIZE | Default stack size | | `pthread_default_guard_size` | PAGE_SIZE | Stack guard size | | `pthread_stack_min` | PAGE_SIZE | Minimum stack size | | `sched_tick_duration` | 20ms | Scheduler tick | | `mq_max_msgs` | 32 | Default MQ messages | | `mq_max_msg_len` | 256 | Default MQ message size | | `num_of_timers` | 64 | Max timers | | `num_of_semaphores` | 256 | Max semaphores | | `max_sig_entries` | 32 | Max simultaneous signal handlers | | `sig_stack_size` | 4*PAGE_SIZE | Signal handler stack | | `sigqueue_max` | 64 | Max queued signals | | `proc_nfiles` | 64 | Max open files | | `num_mq` | 8 | Max message queues | | `num_fs_io_threads` | 4 | FS I/O threads | --- ## 11. SYSCALL TABLE (Complete) **File:** `sources/ukernel-x86_amd64/arch/common/include/syscalls.h` 119 syscalls total (P4_SYSCALL_NUM = 119): | # | Name | Category | |---|------|----------| | 0 | FAST_GET_UID | Identity | | 1 | KERNEL_CONTROL | System | | 2 | SLEEP | Time | | 3 | FAST_GET_CPUID | Identity | | 4-8 | TASK_* | Task management | | 9-19 | THR_* | Thread management | | 20-22 | COMM_*/IPC_MASK | Communication rights | | 23 | IPC | Inter-process communication | | 24-26 | EV_* | Events | | 27-29 | INT_* | Interrupts | | 30-31 | FAST_GET/SET_PRIO | Priority | | 32-36 | MEM_* | Memory management | | 37-39 | IOPORT_* | I/O ports | | 40-46 | TRACE_* | Tracing | | 47-48 | ALLOC_* | Physical memory | | 49 | MON_MEM_LIST | Monitor | | 50-53 | TP_* | Time partitions | | 54 | THR_GET_REGS | Thread registers | | 55 | GET_TIME | Time | | 56-57 | MEM_READ/WRITE | Memory access | | 58-59 | DEV_* | Devices | | 60-65 | MON_* | Monitoring | | 66 | MEM_CLEAR | Memory | | 67 | THR_EX_AFFINITY | Thread affinity | | 68 | TP_WIN_GET_ATTR | Time partition | | 69 | SYSEMU_ENTER | System emulation | | 70 | THR_PREEMPT | Thread preemption | | 71 | TLS_REGISTER | TLS | | 72-73 | ULOCK_WAIT/WAKE | User locks (futex) | | 74 | GET_TS | Timestamp | | 75-76 | RESPART_* | Resource partitions | | 77 | THR_ALARM | Thread alarm | | 78-96 | KDEV_* | Kernel device I/O | | 97 | TLS_SYNC_PRIO | TLS priority sync | | 98-104 | HM_* | Health monitoring | | 105-108 | WAITQ_* | Wait queues | | 109 | CACHE | Cache control | | 110 | FAST_GET_TIMEPART | Time partition | | 111-116 | KDEV_* | More device I/O | | 117 | KDEV_DISCOVER_GATE | Device discovery | | 118 | MON_MEMREG_GET_ATTR | Memory region monitor | **Syscall mechanism (x86_64):** ```asm mov $SYSCALL_NUM, %eax syscall ; x86-64 SYSCALL instruction ret ``` --- ## 12. POSIX COMPLIANCE MATRIX (PSE51) | Feature | Status | Notes | |---------|--------|-------| | Threads | ✅ Full | pthread_create/join/detach/cancel | | Mutexes | ✅ Full | Including priority inheritance/ceiling | | Condition Variables | ✅ Full | Including timedwait | | RW Locks | ✅ Full | | | Semaphores | ✅ Full | Named + unnamed | | Message Queues | ✅ Full | mq_open/send/receive/timed | | Signals | ✅ Full | Including realtime signals, sigqueue | | Timers | ✅ Full | timer_create/settime, clock_gettime | | Clocks | ✅ Partial | CLOCK_REALTIME only | | File I/O | ✅ Full | open/read/write/close/lseek/fstat | | mmap | ⚠️ Partial | MAP_SHARED only, no mprotect | | Shared Memory | ⚠️ Static | shm_open, no dynamic creation | | Pipes | ✅ Full | Local pipes | | Scheduling | ✅ Full | SCHED_FIFO/RR/OTHER | | fork/exec | ❌ N/A | Not in PSE51 scope | | Process spawn | ❌ Disabled | _POSIX_SPAWN = -1 | | Job control | ❌ Disabled | _POSIX_JOB_CONTROL = -1 | | Barriers | ❌ Disabled | _POSIX_BARRIERS = -1 | | Spin locks | ❌ Disabled | _POSIX_SPIN_LOCKS = -1 | | Async I/O | ❌ Disabled | _POSIX_ASYNCHRONOUS_IO = -1 | | Process-shared sync | ❌ Disabled | _POSIX_THREAD_PROCESS_SHARED = -1 | --- ## 13. KEY DESIGN PATTERNS FOR UNIVERSALISOS PARITY ### Pattern 1: POSIX → PikeOS Kernel Bridge ``` POSIX API (pthread_create) → POSIX library (internal implementation) → p4ext (thread creation: stack alloc, TLS init) → p4_thread_create_syscall (ASM stub) → SYSCALL instruction → PikeOS kernel ``` ### Pattern 2: File System Provider Model ``` struct _file → f_ops → _fileops (read/write/close/ioctl/lseek/fstat) ↓ _fs_provider (LCL_DEV, LCL_FILE, LCL_PIPE, LCL_MQ, etc.) ``` ### Pattern 3: Memory Pool Architecture - Stack pool: fixed virtual region for thread stacks - SHM pool: fixed virtual region for mmap/shm_open - Heap pool: fixed virtual region for malloc/sbrk - All backed by PSSW memory requirements configured at partition time ### Pattern 4: Configuration-Driven - `struct _configurables` defines ALL tunable parameters - Can be overridden via application property section - Version-controlled structure for backward compatibility