// 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_<platform>.c+`
. Implement `+sf_time_backend_<platform>+` 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
