// Moved from docs/src/platform-integration/PLATFORM_ABSTRACTION.adoc to docs/working/scratch/src/platform-integration/PLATFORM_ABSTRACTION.adoc on 2026-06-16 (docs reorg Phase 2) == StarForth Platform Abstraction Layer :toc: left :toc-title: Contents :toclevels: 3 xref:../README.adoc[← Back to Documentation Index] StarForth now includes a clean platform abstraction layer that allows building for multiple platforms with a simple Makefile switch. === Overview The platform abstraction provides portable timing/clock functionality across: * *POSIX* systems (Linux, macOS, BSD, etc.) * *L4Re/StarshipOS* microkernel === Architecture Similar to the `+blkio+` subsystem, the platform layer uses a *vtable pattern* for zero runtime overhead while maintaining clean separation between core VM logic and platform-specific code. .... StarForth Core (platform-agnostic) ↓ include/platform_time.h (abstraction API) ↓ Runtime platform selection (compile-time) ├── src/platform/time_posix.c (POSIX: clock_gettime) └── src/platform/time_l4re.c (L4Re: RTC server + KIP clock) .... === Usage ==== Building for Different Platforms [source,bash] ---- # POSIX build (default - Linux/macOS/BSD) make # L4Re/StarshipOS build make L4RE=1 # Minimal embedded build (no platform layer) make MINIMAL=1 ---- ==== API Reference All timing functions are accessed through `+include/platform_time.h+`: [source,c] ---- #include "platform_time.h" // Initialize platform (call once at startup) sf_time_init(); // Get monotonic time (for performance measurement) sf_time_ns_t uptime = sf_monotonic_ns(); // nanoseconds since boot // Get wall-clock time (Unix epoch) sf_time_ns_t now = sf_realtime_ns(); // nanoseconds since 1970-01-01 // Set system time (requires privileges on most platforms) sf_set_realtime_ns(new_time_ns); // Format timestamp as human-readable string char buf[SF_TIME_STAMP_SIZE]; sf_format_timestamp(now, buf, 1); // 1 = 24-hour format printf("Current time: %s\n", buf); // Check if RTC is available if (sf_has_rtc()) { printf("RTC available\n"); } ---- ==== Helper Functions [source,c] ---- // Time conversion helpers uint64_t seconds = 1234567890; sf_time_ns_t ns = sf_seconds_to_ns(seconds); uint64_t secs = sf_ns_to_seconds(ns); uint64_t ms = sf_ns_to_ms(ns); uint64_t us = sf_ns_to_us(ns); ---- === Implementation Details ==== POSIX Backend (`+time_posix.c+`) * Uses `+clock_gettime(CLOCK_MONOTONIC)+` for high-precision monotonic time * Uses `+clock_gettime(CLOCK_REALTIME)+` for wall-clock time * Provides `+localtime()+` and `+strftime()+` for timestamp formatting * Always reports RTC as available (standard POSIX behavior) ==== L4Re Backend (`+time_l4re.c+`) * *Monotonic time*: L4Re KIP (Kernel Info Page) clock - microsecond counter since boot + [source,c] ---- l4_kip_clock_ns(l4re_kip()) // Direct CPU timestamp counter access ---- * *Real time*: RTC server offset + KIP clock + [source,c] ---- rtc_offset + l4_kip_clock_ns(l4re_kip()) ---- * *RTC server integration*: ** Attempts to get `+"rtc"+` capability from L4Re environment ** Queries offset via `+get_timer_offset()+` RPC ** Falls back gracefully if RTC server unavailable (reports epoch time) * *Time setting*: Updates RTC offset via `+set_timer_offset()+` RPC (requires write capability) ==== Platform Selection (`+platform_init.c+`) Compile-time platform selection based on `+__l4__+` define: [source,c] ---- void sf_time_init(void) { #ifdef __l4__ sf_time_init_l4re(); // L4Re-specific init sf_time_backend = &sf_time_backend_l4re; #else sf_time_backend = &sf_time_backend_posix; #endif } ---- === Porting to L4Re/StarshipOS When copying StarForth to `+StarshipOS/l4/pkg/starforth+`, the build system automatically uses the L4Re backend: ==== StarshipOS Makefile Integration [source,makefile] ---- # In StarshipOS/l4/pkg/starforth/server/src/Makefile SRC_C = main.c vm.c log.c profiler.c \ platform/time_l4re.c platform/platform_init.c REQUIRES_LIBS = libc_be_l4re libc l4re l4re_c l4sys librtc CPPFLAGS += -D__l4__=1 ---- ==== Loader Configuration [source,lua] ---- -- Start RTC server first ld:start({ caps = { vbus = vbus_l4re, }, }, "rom/rtc"); -- StarForth with RTC capability ld:start({ caps = { rtc = ld:wait("rtc", 1000), -- Wait for RTC server }, }, "rom/starforth"); ---- === Migration from Old Code The platform abstraction *replaces* direct POSIX calls: ==== Before (POSIX-only): [source,c] ---- // profiler.c static uint64_t get_time_ns(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec * 1000000000ULL + ts.tv_nsec; } // log.c static void get_timestamp(char *buffer, size_t size) { time_t now = time(NULL); struct tm *tm_info = localtime(&now); strftime(buffer, size, "%H:%M:%S", tm_info); } ---- ==== After (Platform-agnostic): [source,c] ---- // profiler.c #include "platform_time.h" static uint64_t get_time_ns(void) { return sf_monotonic_ns(); // Works on both POSIX and L4Re } // log.c #include "platform_time.h" static void get_timestamp(char *buffer, size_t size) { sf_time_ns_t now = sf_realtime_ns(); sf_format_timestamp(now, buffer, 1); } ---- === Benefits [arabic] . *Single codebase*: No more `+#ifdef+` spaghetti in core files . *Zero overhead*: Inline functions compile to direct calls . *Type safety*: Strong typing via vtable pattern . *Extensibility*: Easy to add new platforms (WASM, baremetal, etc.) . *Testability*: Mock implementations possible via vtable swapping === Future Platforms The abstraction is designed to support: * *Baremetal* (direct hardware timer access) * *WASM* (performance.now() emulation) * *RTOS* (FreeRTOS, Zephyr, etc.) * *Custom microkernels* (seL4, etc.) Adding a new platform requires: [arabic] . Create `+src/platform/time_.c+` . Implement `+sf_time_backend_+` vtable . Add platform detection to `+platform_init.c+` . Update Makefile with new platform flag === Testing [source,bash] ---- # Test POSIX build make clean && make ./build/starforth --run-tests # Test profiler timing ./build/starforth --profile 2 --run-tests --profile-report # Test logging timestamps ./build/starforth --log-debug ---- === See Also * `+include/platform_time.h+` - Platform API documentation * `+src/platform/time_posix.c+` - POSIX implementation * `+src/platform/time_l4re.c+` - L4Re implementation * `+src/platform/platform_init.c+` - Platform selector * StarshipOS CLAUDE.md - L4Re RTC architecture details