%% SCRAP: hardware/platform-integration/PLATFORM_ABSTRACTION
%% SOURCE: docs/working/hardware/platform-integration/PLATFORM_ABSTRACTION.adoc
%% STATUS: CURRENT
%% FITS: dev-guide/ch-platform
%% EDITORIAL: lifted — prose rewritten to press voice

\section{The Platform Abstraction Layer}

StarForth's platform abstraction layer provides portable timing and clock
functionality across POSIX systems (Linux, macOS, BSD) and the L4Re/StarshipOS
microkernel, selected by a single Makefile switch. Following the same vtable
pattern as the block I/O subsystem, it achieves zero runtime overhead while
keeping platform-specific code cleanly separated from the core VM.

\subsection{Structure}

The core VM is platform-agnostic and speaks only to
\texttt{include/platform\_time.h}. Behind that header, compile-time selection
routes to one of two backends: \texttt{src/platform/time\_posix.c} using
\texttt{clock\_gettime}, or \texttt{src/platform/time\_l4re.c} using the RTC
server and KIP clock. Builds choose the path explicitly:

\begin{lstlisting}[language=bash]
make            # POSIX (default)
make L4RE=1     # L4Re/StarshipOS
make MINIMAL=1  # minimal embedded, no platform layer
\end{lstlisting}

\subsection{API}

All timing flows through \texttt{platform\_time.h}. The host calls
\texttt{sf\_time\_init()} once at startup, then reads
\texttt{sf\_monotonic\_ns()} for performance measurement (nanoseconds since
boot) and \texttt{sf\_realtime\_ns()} for wall-clock time (nanoseconds since the
Unix epoch). \texttt{sf\_set\_realtime\_ns()} sets the clock where privileges
allow, \texttt{sf\_format\_timestamp()} renders a human-readable string, and
\texttt{sf\_has\_rtc()} reports RTC availability. Helper conversions
(\texttt{sf\_seconds\_to\_ns}, \texttt{sf\_ns\_to\_seconds},
\texttt{sf\_ns\_to\_ms}, \texttt{sf\_ns\_to\_us}) round out the interface.

\subsection{Backends}

The POSIX backend uses \texttt{CLOCK\_MONOTONIC} for high-precision monotonic
time, \texttt{CLOCK\_REALTIME} for wall-clock time, and
\texttt{localtime}/\texttt{strftime} for formatting; it always reports an RTC
as available. The L4Re backend draws monotonic time directly from the Kernel
Info Page clock (\texttt{l4\_kip\_clock\_ns(l4re\_kip())}) and real time from
the RTC server offset added to that clock. It obtains the \texttt{"rtc"}
capability from the L4Re environment, queries the offset over RPC, and degrades
gracefully to epoch time when no RTC server is present; setting time updates the
offset over RPC and requires a write capability. The selector chooses at
compile time on the \texttt{\_\_l4\_\_} define:

\begin{lstlisting}[language=C]
void sf_time_init(void) {
#ifdef __l4__
    sf_time_init_l4re();
    sf_time_backend = &sf_time_backend_l4re;
#else
    sf_time_backend = &sf_time_backend_posix;
#endif
}
\end{lstlisting}

\subsection{Migration from Direct POSIX Calls}

The abstraction replaces scattered platform calls in the core. Where the
profiler once called \texttt{clock\_gettime(CLOCK\_MONOTONIC, ...)} directly, it
now calls \texttt{sf\_monotonic\_ns()}; where the logger called \texttt{time},
\texttt{localtime}, and \texttt{strftime}, it now calls
\texttt{sf\_realtime\_ns()} and \texttt{sf\_format\_timestamp()}. The same
source compiles unchanged on both platforms.

\subsection{Benefits}

The layer keeps the core free of \texttt{\#ifdef} clutter; inline functions
compile to direct calls for zero overhead; the vtable gives strong typing; new
platforms are easy to add; and the vtable can be swapped for mocks in testing.

\subsection{StarshipOS Integration and Future Platforms}

Copied into \texttt{StarshipOS/l4/pkg/starforth}, the build automatically
selects the L4Re backend by compiling \texttt{time\_l4re.c} and
\texttt{platform\_init.c}, linking \texttt{librtc}, and defining
\texttt{\_\_l4\_\_=1}; the loader starts the RTC server first and grants the VM
the \texttt{rtc} capability. The design anticipates further backends ---
bare-metal hardware timers, WebAssembly via \texttt{performance.now()}, RTOSes
such as FreeRTOS and Zephyr, and other microkernels such as seL4. Adding one
requires a new \texttt{time\_<platform>.c}, its backend vtable, a detection
branch in \texttt{platform\_init.c}, and a Makefile flag.
