rumpk/libs/membrane/libc.nim

188 lines
5.5 KiB
Nim

import socket
import ../../core/ion/memory
import ion_client
proc console_write(p: pointer, len: csize_t) {.importc, cdecl.}
proc membrane_init*() {.importc, cdecl.}
proc pump_membrane_stack*() {.importc, cdecl.}
# --- SYSCALL PRIMITIVE ---
proc syscall*(nr: int, a0: int = 0, a1: int = 0, a2: int = 0): int {.inline.} =
var res: int
asm """
mv a7, %1
mv a0, %2
mv a1, %3
mv a2, %4
ecall
mv %0, a0
: "=r"(`res`)
: "r"(`nr`), "r"(`a0`), "r"(`a1`), "r"(`a2`)
: "a0", "a7", "memory"
"""
return res
# --- POSIX SOCKET API SHIMS ---
type
SockAddrIn = object
sin_family: uint16
sin_port: uint16
sin_addr: uint32
sin_zero: array[8, char]
proc socket*(domain, sock_type, protocol: int): int {.exportc, cdecl.} =
return new_socket()
proc connect*(fd: int, sock_addr: pointer, len: int): int {.exportc, cdecl.} =
if sock_addr == nil: return -1
let sin = cast[ptr SockAddrIn](sock_addr)
return connect_flow(fd, sin.sin_addr, sin.sin_port)
proc send*(fd: cint, buf: pointer, count: csize_t, flags: cint): int {.exportc, cdecl.} =
return send_flow(int(fd), buf, int(count))
proc recv*(fd: cint, buf: pointer, count: csize_t, flags: cint): int {.exportc, cdecl.} =
return recv_flow(int(fd), buf, int(count))
# --- LIBC IO SHIMS ---
proc write*(fd: cint, buf: pointer, count: csize_t): int {.exportc, cdecl.} =
if fd == 1 or fd == 2:
when defined(is_kernel):
return -1
else:
console_write(buf, count)
return int(count)
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
if sys.fn_vfs_write != nil:
let f = cast[proc(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.}](
sys.fn_vfs_write)
return int(f(int32(fd), buf, uint64(count)))
if fd >= 100:
return send_flow(int(fd), buf, int(count))
# File Write (Syscall 0x204)
return syscall(0x204, int(fd), cast[int](buf), int(count))
# Stdin buffer for input packets
var stdin_buf: array[128, byte]
var stdin_len: int = 0
var stdin_pos: int = 0
proc read*(fd: cint, buf: pointer, count: csize_t): int {.exportc, cdecl.} =
if fd == 0:
if stdin_pos < stdin_len:
let remaining = stdin_len - stdin_pos
let to_copy = if remaining > int(count): int(count) else: remaining
copyMem(buf, addr stdin_buf[stdin_pos], to_copy)
stdin_pos += to_copy
if stdin_pos >= stdin_len:
stdin_len = 0
stdin_pos = 0
return to_copy
# Poll input ring
var pkt: IonPacket
if ion_user_input(addr pkt):
let len = min(int(pkt.len), 128)
copyMem(addr stdin_buf[0], pkt.data, len)
stdin_len = len
stdin_pos = 0
ion_user_return(pkt.id)
let to_copy = if stdin_len > int(count): int(count) else: stdin_len
copyMem(buf, addr stdin_buf[0], to_copy)
stdin_pos += to_copy
return to_copy
return 0
if fd >= 100: return recv(fd, buf, count, 0)
# Try SysTable first
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
if sys.fn_vfs_read != nil:
let f = cast[proc(fd: int32, buf: pointer, count: uint64): int64 {.cdecl.}](
sys.fn_vfs_read)
return int(f(int32(fd), buf, uint64(count)))
return syscall(0x203, int(fd), cast[int](buf), int(count))
proc exit*(status: cint) {.exportc, cdecl.} =
discard syscall(0, 0)
while true: discard
proc open*(pathname: cstring, flags: cint): cint {.exportc, cdecl.} =
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
if sys.fn_vfs_open != nil:
return cint(sys.fn_vfs_open(pathname, int32(flags)))
return cint(syscall(0x200, cast[int](pathname), int(flags)))
proc close*(fd: cint): cint {.exportc, cdecl.} =
if fd >= 100: return 0
# Try SysTable first
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
if sys.fn_vfs_close != nil:
let f = cast[proc(fd: int32): int32 {.cdecl.}](sys.fn_vfs_close)
return cint(f(int32(fd)))
return cint(syscall(0x201, int(fd)))
proc nexus_list*(buf: pointer, len: int): int {.exportc, cdecl.} =
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
if sys.fn_vfs_list != nil:
let f = cast[proc(buf: pointer, max_len: uint64): int64 {.cdecl.}](
sys.fn_vfs_list)
return int(f(buf, uint64(len)))
return syscall(0x202, cast[int](buf), len)
# moved to top
proc sleep*(seconds: uint32) {.exportc, cdecl.} =
var i: int = 0
let limit = int(seconds) * 50_000_000
while i < limit:
i += 1
# --- PHASE 29: WORKER MODEL (THE HIVE) ---
proc spawn*(entry: proc(arg: uint64) {.cdecl.}, arg: uint64 = 0): int {.exportc, cdecl.} =
## Spawn a new worker fiber
## Returns: Fiber ID on success, -1 on failure
return syscall(0x500, cast[int](entry), int(arg))
proc join*(fid: int): int {.exportc, cdecl.} =
## Wait for worker fiber to complete
## Returns: 0 on success, -1 on failure
return syscall(0x501, fid)
# --- PHASE 28: PLEDGE ---
proc pledge*(promises: uint64): int {.exportc, cdecl.} =
## Reduce capabilities (one-way ratchet)
## Returns: 0 on success, -1 on failure
let sys = cast[ptr SysTable](SYS_TABLE_ADDR)
if sys.fn_pledge != nil:
return int(sys.fn_pledge(promises))
return -1
return -1
proc upgrade*(target_fid: uint64, path: cstring): int {.exportc, cdecl.} =
## Live Upgrade System (The Phoenix)
## Returns: 0 on success, -error on failure
return syscall(0x502, int(target_fid), cast[int](path))
# --- HIGH LEVEL HELPERS ---
import strutils, sequtils
proc get_vfs_listing*(): seq[string] =
var buf = newString(4096)
let n = nexus_list(addr buf[0], 4096)
if n > 0:
buf.setLen(n)
return buf.splitLines().filterIt(it.strip().len > 0)
return @[]