kernel
v0.0.43Platform abstraction layer for Riot
riot add kernel kernel = "0.0.43" - Last release
- May 15, 2026
- License
- Apache-2.0
- Dependencies
- 0
- Dependents
- 6
- Installs
- 151
- Published versions
- 33
- Owner
-
@leostera
README Expand Collapse
kernel-new
kernel-new is Riot's new platform abstraction layer.
It is intentionally narrow:
- portable public contracts over platform-specific implementations
- just enough foundational types for
stdto build on top of it - Riot-authored native shims under
native/
Current backend status:
- Unix only
Current public surface:
- foundational:
Bool,Char,Int,Int32,Int64,Float,String,Bytes,Array,Option,Result,SystemError,Error - runtime/platform:
Effect,Async,Path,IO.Iovec,Fs.File,Fs.ReadDir,Net.Addr,Net,Time,Env,Process
Not in kernel-new:
Reader/Writer- public raw file descriptors or socket handles
- iterators, regex, crypto, compression, unicode, vectors, maps
Error Model
Each public module owns a small typed error type.
Examples:
Fs.File.errorFs.ReadDir.errorNet.Addr.errorNet.TcpStream.errorNet.UdpSocket.errorTime.SystemTime.errorTime.Monotonic.error
Kernel_new.Error wraps those module-local errors into one shared sum type for package boundaries and test helpers. Kernel_new.SystemError owns the shared errno-like system cases used by native shims.
Kernel_new.Error is only the typed envelope. The invariant-violation escape hatch stays in Kernel_new.SystemError.panic, not in the package error sum.
Kernel_new.SystemError is intentionally symbolic. Numeric error-code bridges stay internal to native-facing modules and do not belong in the portable public contract.
Rules
- Do not depend on
Unix.*orStdlib.*inkernel-newimplementation code. - Keep native code in
native/. - Keep public APIs portable even when the backend is Unix-only today.
- Prefer structured errors over stringly errors or native exceptions.
- If an operation has a real async/readiness path, prefer exposing that path instead of a blocking helper. Fast metadata-style syscalls are still fine when they are inherently synchronous.
- Keep source-layout and code-hygiene checks out of unit tests. Those rules belong in docs or separate tooling because tests may run without source access.
- Do not add
Backend.mlshim modules. Use local backend files likeenv/unix.mlwhere the planner supports them; otherwise keep the implementation in the public module until the nested-backend layout is supported cleanly.
Backend Layout
Platform-backed public modules should prefer a local backend layout:
fs/file/file.mlre-exports the selected backend withinclude Unixfs/file/unix.mlholds the Unix implementation- future backends should live beside it, such as
windows.mlorwasi.ml
Use the same pattern for other platform-backed directory modules:
async/adapter/adapter.mlandasync/adapter/unix.mlenv/env.mlandenv/unix.mlprocess/process.mlandprocess/unix.mltime/system_time/system_time.mlandtime/system_time/unix.mltime/monotonic/monotonic.mlandtime/monotonic/unix.mlnet/tcp_listener/tcp_listener.mlandnet/tcp_listener/unix.mlnet/tcp_stream/tcp_stream.mlandnet/tcp_stream/unix.mlnet/udp_socket/udp_socket.mlandnet/udp_socket/unix.ml
Keep pure modules pure. Do not add backend files where the code is platform-free today:
IO.IovecNet.SocketAddr
Net.IpAddr currently uses a Riot-owned native validator, so it follows the local backend pattern even though its public surface stays small and pure-looking.
Public Surface Notes
- Keep public handles abstract.
Fs.File.t,Net.TcpStream.t,Net.UdpSocket.t,Process.t, and the clock/timer handles should stay opaque. - Keep the package error story layered: local module error first,
SystemError.tfor shared native/system failures, andKernel_new.Error.tfor package boundaries. IOis intentionally small. Its public role isIO.Iovec; generic catch-all I/O error aliases do not belong there.Async.AdapterandAsync.Source.makeare backend-facing seams used bykernel-newitself. Consumers should preferAsync.Pollplusto_sourcevalues from public modules.- Readiness-backed and intentionally synchronous behavior notes should live in the relevant
.mlinext to the APIs they describe, not only in package-level docs. - If a capability has a
to_source, do not add a separate blocking wait helper for it. - Any new external should be documented in code as either readiness-backed or intentionally synchronous.
Review Checklist
- no public raw file descriptors, socket handles, timer ids, or process-owned native handles
- no blocking helper where readiness plus
to_sourcealready exists - local backend modules use
file.mlormodule.mlas the public re-export and keep backend code in sibling files likeunix.ml - public errors stay typed and structured; string messages are for
to_stringoutput, not API contracts
For std
std should treat kernel-new as the portability substrate, not as a complete user-facing I/O library.
The intended seams are:
Fs.File.to_source,Net.*.to_source, andProcess.to_sourcefor actor-friendly waitingFs.ReadDirfor incremental directory iteration without raw OS handlesNet.Addrfor hostname-to-SocketAddrresolution above raw IP parsingtry_waitinstead of a blocking process waitIO.Iovecfor vectored file and socket operationsSystemTimeandMonotonicas raw clock primitives, with richer time APIs above
Validate
timeout 30 riot build kernel-new
timeout 180 riot test -p kernel-new
timeout 180 riot bench -p kernel-new --json
Benchmarks
See bench/README.md for the current benchmark set and baseline medians.
kernel-new
kernel-new is Riot's new platform abstraction layer.
It is intentionally narrow:
- portable public contracts over platform-specific implementations
- just enough foundational types for
stdto build on top of it - Riot-authored native shims under
native/
Current backend status:
- Unix only
Current public surface:
- foundational:
Bool,Char,Int,Int32,Int64,Float,String,Bytes,Array,Option,Result,SystemError,Error - runtime/platform:
Effect,Async,Path,IO.Iovec,Fs.File,Fs.ReadDir,Net.Addr,Net,Time,Env,Process
Not in kernel-new:
Reader/Writer- public raw file descriptors or socket handles
- iterators, regex, crypto, compression, unicode, vectors, maps
Error Model
Each public module owns a small typed error type.
Examples:
Fs.File.errorFs.ReadDir.errorNet.Addr.errorNet.TcpStream.errorNet.UdpSocket.errorTime.SystemTime.errorTime.Monotonic.error
Kernel_new.Error wraps those module-local errors into one shared sum type for package boundaries and test helpers. Kernel_new.SystemError owns the shared errno-like system cases used by native shims.
Kernel_new.Error is only the typed envelope. The invariant-violation escape hatch stays in Kernel_new.SystemError.panic, not in the package error sum.
Kernel_new.SystemError is intentionally symbolic. Numeric error-code bridges stay internal to native-facing modules and do not belong in the portable public contract.
Rules
- Do not depend on
Unix.*orStdlib.*inkernel-newimplementation code. - Keep native code in
native/. - Keep public APIs portable even when the backend is Unix-only today.
- Prefer structured errors over stringly errors or native exceptions.
- If an operation has a real async/readiness path, prefer exposing that path instead of a blocking helper. Fast metadata-style syscalls are still fine when they are inherently synchronous.
- Keep source-layout and code-hygiene checks out of unit tests. Those rules belong in docs or separate tooling because tests may run without source access.
- Do not add
Backend.mlshim modules. Use local backend files likeenv/unix.mlwhere the planner supports them; otherwise keep the implementation in the public module until the nested-backend layout is supported cleanly.
Backend Layout
Platform-backed public modules should prefer a local backend layout:
fs/file/file.mlre-exports the selected backend withinclude Unixfs/file/unix.mlholds the Unix implementation- future backends should live beside it, such as
windows.mlorwasi.ml
Use the same pattern for other platform-backed directory modules:
async/adapter/adapter.mlandasync/adapter/unix.mlenv/env.mlandenv/unix.mlprocess/process.mlandprocess/unix.mltime/system_time/system_time.mlandtime/system_time/unix.mltime/monotonic/monotonic.mlandtime/monotonic/unix.mlnet/tcp_listener/tcp_listener.mlandnet/tcp_listener/unix.mlnet/tcp_stream/tcp_stream.mlandnet/tcp_stream/unix.mlnet/udp_socket/udp_socket.mlandnet/udp_socket/unix.ml
Keep pure modules pure. Do not add backend files where the code is platform-free today:
IO.IovecNet.SocketAddr
Net.IpAddr currently uses a Riot-owned native validator, so it follows the local backend pattern even though its public surface stays small and pure-looking.
Public Surface Notes
- Keep public handles abstract.
Fs.File.t,Net.TcpStream.t,Net.UdpSocket.t,Process.t, and the clock/timer handles should stay opaque. - Keep the package error story layered: local module error first,
SystemError.tfor shared native/system failures, andKernel_new.Error.tfor package boundaries. IOis intentionally small. Its public role isIO.Iovec; generic catch-all I/O error aliases do not belong there.Async.AdapterandAsync.Source.makeare backend-facing seams used bykernel-newitself. Consumers should preferAsync.Pollplusto_sourcevalues from public modules.- Readiness-backed and intentionally synchronous behavior notes should live in the relevant
.mlinext to the APIs they describe, not only in package-level docs. - If a capability has a
to_source, do not add a separate blocking wait helper for it. - Any new external should be documented in code as either readiness-backed or intentionally synchronous.
Review Checklist
- no public raw file descriptors, socket handles, timer ids, or process-owned native handles
- no blocking helper where readiness plus
to_sourcealready exists - local backend modules use
file.mlormodule.mlas the public re-export and keep backend code in sibling files likeunix.ml - public errors stay typed and structured; string messages are for
to_stringoutput, not API contracts
For std
std should treat kernel-new as the portability substrate, not as a complete user-facing I/O library.
The intended seams are:
Fs.File.to_source,Net.*.to_source, andProcess.to_sourcefor actor-friendly waitingFs.ReadDirfor incremental directory iteration without raw OS handlesNet.Addrfor hostname-to-SocketAddrresolution above raw IP parsingtry_waitinstead of a blocking process waitIO.Iovecfor vectored file and socket operationsSystemTimeandMonotonicas raw clock primitives, with richer time APIs above
Validate
timeout 30 riot build kernel-new
timeout 180 riot test -p kernel-new
timeout 180 riot bench -p kernel-new --json
Benchmarks
See bench/README.md for the current benchmark set and baseline medians.