mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-06 11:54:11 +00:00
Merge pull request #7873 from ehmry/GenodeEnv
Native access to Genode environment
This commit is contained in:
@@ -1035,14 +1035,19 @@ proc genMainProc(m: BModule) =
|
||||
"}$N$N"
|
||||
|
||||
GenodeNimMain =
|
||||
"Libc::Env *genodeEnv;$N" &
|
||||
"extern Genode::Env *nim_runtime_env;$N" &
|
||||
"extern void nim_component_construct(Genode::Env*);$N$N" &
|
||||
NimMainBody
|
||||
|
||||
ComponentConstruct =
|
||||
"void Libc::Component::construct(Libc::Env &env) {$N" &
|
||||
"\tgenodeEnv = &env;$N" &
|
||||
"\t// Set Env used during runtime initialization$N" &
|
||||
"\tnim_runtime_env = &env;$N" &
|
||||
"\tLibc::with_libc([&] () {$N\t" &
|
||||
"\t// Initialize runtime and globals$N" &
|
||||
MainProcs &
|
||||
"\t// Call application construct$N" &
|
||||
"\t\tnim_component_construct(&env);$N" &
|
||||
"\t});$N" &
|
||||
"}$N$N"
|
||||
|
||||
@@ -1059,6 +1064,7 @@ proc genMainProc(m: BModule) =
|
||||
elif platform.targetOS == osGenode:
|
||||
nimMain = GenodeNimMain
|
||||
otherMain = ComponentConstruct
|
||||
m.includeHeader("<libc/component.h>")
|
||||
elif optGenDynLib in m.config.globalOptions:
|
||||
nimMain = PosixNimDllMain
|
||||
otherMain = PosixCDllMain
|
||||
|
||||
@@ -8,10 +8,15 @@
|
||||
#
|
||||
|
||||
# Low level dataspace allocator for Genode.
|
||||
# For interacting with dataspaces outside of the
|
||||
# standard library see the Genode Nimble package.
|
||||
|
||||
when not defined(genode):
|
||||
{.error: "Genode only module".}
|
||||
|
||||
when not declared(GenodeEnv):
|
||||
include genode/env
|
||||
|
||||
type DataspaceCapability {.
|
||||
importcpp: "Genode::Dataspace_capability", pure.} = object
|
||||
|
||||
@@ -31,35 +36,35 @@ type
|
||||
|
||||
const SlabBackendSize = 4096
|
||||
|
||||
proc ramAvail(): int {.
|
||||
importcpp: "genodeEnv->pd().avail_ram().value".}
|
||||
proc ramAvail(env: GenodeEnv): int {.
|
||||
importcpp: "#->pd().avail_ram().value".}
|
||||
## Return number of bytes available for allocation.
|
||||
|
||||
proc capsAvail(): int {.
|
||||
importcpp: "genodeEnv->pd().avail_caps().value".}
|
||||
proc capsAvail(env: GenodeEnv): int {.
|
||||
importcpp: "#->pd().avail_caps().value".}
|
||||
## Return the number of available capabilities.
|
||||
## Each dataspace allocation consumes a capability.
|
||||
|
||||
proc allocDataspace(size: int): DataspaceCapability {.
|
||||
importcpp: "genodeEnv->pd().alloc(@)".}
|
||||
proc allocDataspace(env: GenodeEnv; size: int): DataspaceCapability {.
|
||||
importcpp: "#->pd().alloc(@)".}
|
||||
## Allocate a dataspace and its capability.
|
||||
|
||||
proc attachDataspace(ds: DataspaceCapability): pointer {.
|
||||
importcpp: "genodeEnv->rm().attach(@)".}
|
||||
proc attachDataspace(env: GenodeEnv; ds: DataspaceCapability): pointer {.
|
||||
importcpp: "#->rm().attach(@)".}
|
||||
## Attach a dataspace into the component address-space.
|
||||
|
||||
proc detachAddress(p: pointer) {.
|
||||
importcpp: "genodeEnv->rm().detach(@)".}
|
||||
proc detachAddress(env: GenodeEnv; p: pointer) {.
|
||||
importcpp: "#->rm().detach(@)".}
|
||||
## Detach a dataspace from the component address-space.
|
||||
|
||||
proc freeDataspace(ds: DataspaceCapability) {.
|
||||
importcpp: "genodeEnv->pd().free(@)".}
|
||||
proc freeDataspace(env: GenodeEnv; ds: DataspaceCapability) {.
|
||||
importcpp: "#->pd().free(@)".}
|
||||
## Free a dataspace.
|
||||
|
||||
proc newMapSlab(): ptr MapSlab =
|
||||
let
|
||||
ds = allocDataspace SlabBackendSize
|
||||
p = attachDataspace ds
|
||||
ds = runtimeEnv.allocDataspace SlabBackendSize
|
||||
p = runtimeEnv.attachDataspace ds
|
||||
result = cast[ptr MapSlab](p)
|
||||
result.meta.ds = ds
|
||||
|
||||
@@ -89,13 +94,13 @@ proc osAllocPages(size: int): pointer =
|
||||
# tack a new slab on the tail
|
||||
slab = slab.meta.next
|
||||
# move to next slab in linked list
|
||||
map.ds = allocDataspace size
|
||||
map.ds = runtimeEnv.allocDataspace size
|
||||
map.size = size
|
||||
map.attachment = attachDataspace map.ds
|
||||
map.attachment = runtimeEnv.attachDataspace map.ds
|
||||
result = map.attachment
|
||||
|
||||
proc osTryAllocPages(size: int): pointer =
|
||||
if ramAvail() >= size and capsAvail() > 1:
|
||||
if runtimeEnv.ramAvail() >= size and runtimeEnv.capsAvail() > 4:
|
||||
result = osAllocPages size
|
||||
|
||||
proc osDeallocPages(p: pointer; size: int) =
|
||||
@@ -107,8 +112,8 @@ proc osDeallocPages(p: pointer; size: int) =
|
||||
if m.size != size:
|
||||
echo "cannot partially detach dataspace"
|
||||
quit -1
|
||||
detachAddress m.attachment
|
||||
freeDataspace m.ds
|
||||
runtimeEnv.detachAddress m.attachment
|
||||
runtimeEnv.freeDataspace m.ds
|
||||
m[] = Map()
|
||||
return
|
||||
slab = slab.meta.next
|
||||
29
lib/genode/env.nim
Normal file
29
lib/genode/env.nim
Normal file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
#
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2018 Emery Hemingway
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
#
|
||||
# This file contains the minimum required definitions
|
||||
# for interacting with the initial Genode environment.
|
||||
# It is reserved for use only within the standard
|
||||
# library. See ``componentConstructHook`` in the system
|
||||
# module for accessing the Genode environment after the
|
||||
# standard library has finished initializating.
|
||||
#
|
||||
|
||||
when not defined(genode):
|
||||
{.error: "Genode only include".}
|
||||
|
||||
type
|
||||
GenodeEnvObj {.importcpp: "Genode::Env", header: "<base/env.h>", pure.} = object
|
||||
GenodeEnvPtr = ptr GenodeEnvObj
|
||||
|
||||
const runtimeEnvSym = "nim_runtime_env"
|
||||
|
||||
when not defined(nimscript):
|
||||
var runtimeEnv {.importcpp: runtimeEnvSym.}: GenodeEnvPtr
|
||||
@@ -13,6 +13,7 @@
|
||||
#define _GENODE_CPP__THREAD_H_
|
||||
|
||||
#include <base/thread.h>
|
||||
#include <base/env.h>
|
||||
#include <util/reconstructible.h>
|
||||
|
||||
namespace Nim { struct SysThread; }
|
||||
|
||||
@@ -502,11 +502,6 @@ typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == siz
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(__GENODE__)
|
||||
#include <libc/component.h>
|
||||
extern Libc::Env *genodeEnv;
|
||||
#endif
|
||||
|
||||
/* Compile with -d:checkAbi and a sufficiently C11:ish compiler to enable */
|
||||
#define NIM_CHECK_SIZE(typ, sz) \
|
||||
_Static_assert(sizeof(typ) == sz, "Nim & C disagree on type size")
|
||||
|
||||
@@ -38,8 +38,10 @@ when defined(macosx) or defined(bsd):
|
||||
importc: "sysctl", nodecl.}
|
||||
|
||||
when defined(genode):
|
||||
proc affinitySpaceTotal(): cuint {.
|
||||
importcpp: "genodeEnv->cpu().affinity_space().total()".}
|
||||
include genode/env
|
||||
|
||||
proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {.
|
||||
importcpp: "@->cpu().affinity_space().total()".}
|
||||
|
||||
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
|
||||
## returns the numer of the processors/cores the machine has.
|
||||
@@ -83,7 +85,7 @@ proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
|
||||
var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "<unistd.h>".}: cint
|
||||
result = sysconf(SC_NPROC_ONLN)
|
||||
elif defined(genode):
|
||||
result = affinitySpaceTotal().int
|
||||
result = runtimeEnv.affinitySpaceTotal().int
|
||||
else:
|
||||
result = sysconf(SC_NPROCESSORS_ONLN)
|
||||
if result <= 0: result = 0
|
||||
|
||||
@@ -1440,7 +1440,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
|
||||
elif defined(solaris):
|
||||
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
|
||||
elif defined(genode):
|
||||
raiseOSError("POSIX command line not supported")
|
||||
raiseOSError(OSErrorCode(-1), "POSIX command line not supported")
|
||||
elif defined(freebsd) or defined(dragonfly):
|
||||
result = getApplFreebsd()
|
||||
# little heuristic that may work on other POSIX-like systems:
|
||||
|
||||
@@ -1498,11 +1498,21 @@ when defined(nimdoc):
|
||||
## macro, use the `error <manual.html#error-pragma>`_ or `fatal
|
||||
## <manual.html#fatal-pragma>`_ pragmas.
|
||||
|
||||
|
||||
elif defined(genode):
|
||||
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn,
|
||||
importcpp: "genodeEnv->parent().exit(@); Genode::sleep_forever()",
|
||||
header: "<base/sleep.h>".}
|
||||
include genode/env
|
||||
|
||||
var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr
|
||||
|
||||
type GenodeEnv* = GenodeEnvPtr
|
||||
## Opaque type representing Genode environment.
|
||||
|
||||
proc quit*(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn,
|
||||
importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "<base/sleep.h>".}
|
||||
|
||||
proc quit*(errorcode: int = QuitSuccess) =
|
||||
systemEnv.quit(errorCode)
|
||||
|
||||
|
||||
|
||||
elif defined(nodejs):
|
||||
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit",
|
||||
@@ -4215,3 +4225,22 @@ when not defined(js):
|
||||
type
|
||||
ForLoopStmt* {.compilerProc.} = object ## special type that marks a macro
|
||||
## as a `for-loop macro`:idx:
|
||||
|
||||
when defined(genode):
|
||||
var componentConstructHook*: proc (env: GenodeEnv) {.nimcall.}
|
||||
## Hook into the Genode component bootstrap process.
|
||||
## This hook is called after all globals are initialized.
|
||||
## When this hook is set the component will not automatically exit,
|
||||
## call ``quit`` explicitly to do so. This is the only available method
|
||||
## of accessing the initial Genode environment.
|
||||
|
||||
proc nim_component_construct(env: GenodeEnv) {.exportc.} =
|
||||
## Procedure called during ``Component::construct`` by the loader.
|
||||
if componentConstructHook.isNil:
|
||||
env.quit(programResult)
|
||||
# No native Genode application initialization,
|
||||
# exit as would POSIX.
|
||||
else:
|
||||
componentConstructHook(env)
|
||||
# Perform application initialization
|
||||
# and return to thread entrypoint.
|
||||
|
||||
@@ -78,7 +78,7 @@ when defined(emscripten):
|
||||
munmap(mmapDescr.realPointer, mmapDescr.realSize)
|
||||
|
||||
elif defined(genode):
|
||||
include genodealloc # osAllocPages, osTryAllocPages, osDeallocPages
|
||||
include genode/alloc # osAllocPages, osTryAllocPages, osDeallocPages
|
||||
|
||||
elif defined(posix):
|
||||
const
|
||||
|
||||
@@ -116,6 +116,7 @@ when defined(windows):
|
||||
importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
|
||||
|
||||
elif defined(genode):
|
||||
import genode/env
|
||||
const
|
||||
GenodeHeader = "genode_cpp/threads.h"
|
||||
type
|
||||
@@ -125,11 +126,12 @@ elif defined(genode):
|
||||
ThreadVarSlot = int
|
||||
|
||||
proc initThread(s: var SysThread,
|
||||
env: GenodeEnv,
|
||||
stackSize: culonglong,
|
||||
entry: GenodeThreadProc,
|
||||
arg: pointer,
|
||||
affinity: cuint) {.
|
||||
importcpp: "#.initThread(genodeEnv, @)".}
|
||||
importcpp: "#.initThread(@)".}
|
||||
|
||||
proc threadVarAlloc(): ThreadVarSlot = 0
|
||||
|
||||
@@ -569,7 +571,7 @@ when hostOS == "windows":
|
||||
|
||||
elif defined(genode):
|
||||
var affinityOffset: cuint = 1
|
||||
# CPU affinity offset for next thread, safe to roll-over
|
||||
## CPU affinity offset for next thread, safe to roll-over
|
||||
|
||||
proc createThread*[TArg](t: var Thread[TArg],
|
||||
tp: proc (arg: TArg) {.thread, nimcall.},
|
||||
@@ -580,6 +582,7 @@ elif defined(genode):
|
||||
t.dataFn = tp
|
||||
when hasSharedHeap: t.stackSize = ThreadStackSize
|
||||
t.sys.initThread(
|
||||
runtimeEnv,
|
||||
ThreadStackSize.culonglong,
|
||||
threadProcWrapper[TArg], addr(t), affinityOffset)
|
||||
inc affinityOffset
|
||||
|
||||
@@ -44,6 +44,10 @@ else:
|
||||
const
|
||||
DLLSSLName* = "libssl" & versions & ".dylib"
|
||||
DLLUtilName* = "libcrypto" & versions & ".dylib"
|
||||
elif defined(genode):
|
||||
const
|
||||
DLLSSLName* = "libssl.lib.so"
|
||||
DLLUtilName* = "libcrypto.lib.so"
|
||||
else:
|
||||
const
|
||||
DLLSSLName* = "libssl.so" & versions
|
||||
|
||||
Reference in New Issue
Block a user