Merge pull request #7873 from ehmry/GenodeEnv

Native access to Genode environment
This commit is contained in:
Andreas Rumpf 2018-06-09 09:38:53 +02:00 • committed by GitHub
commit e00e7fec54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 111 additions and 37 deletions

View file

@ -1035,14 +1035,19 @@ proc genMainProc(m: BModule) =
"}$N$N" "}$N$N"
GenodeNimMain = GenodeNimMain =
"Libc::Env *genodeEnv;$N" & "extern Genode::Env *nim_runtime_env;$N" &
"extern void nim_component_construct(Genode::Env*);$N$N" &
NimMainBody NimMainBody
ComponentConstruct = ComponentConstruct =
"void Libc::Component::construct(Libc::Env &env) {$N" & "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" & "\tLibc::with_libc([&] () {$N\t" &
"\t// Initialize runtime and globals$N" &
MainProcs & MainProcs &
"\t// Call application construct$N" &
"\t\tnim_component_construct(&env);$N" &
"\t});$N" & "\t});$N" &
"}$N$N" "}$N$N"
@ -1059,6 +1064,7 @@ proc genMainProc(m: BModule) =
elif platform.targetOS == osGenode: elif platform.targetOS == osGenode:
nimMain = GenodeNimMain nimMain = GenodeNimMain
otherMain = ComponentConstruct otherMain = ComponentConstruct
m.includeHeader("<libc/component.h>")
elif optGenDynLib in m.config.globalOptions: elif optGenDynLib in m.config.globalOptions:
nimMain = PosixNimDllMain nimMain = PosixNimDllMain
otherMain = PosixCDllMain otherMain = PosixCDllMain

View file

@ -8,10 +8,15 @@
# #
# Low level dataspace allocator for Genode. # Low level dataspace allocator for Genode.
# For interacting with dataspaces outside of the
# standard library see the Genode Nimble package.
when not defined(genode): when not defined(genode):
{.error: "Genode only module".} {.error: "Genode only module".}
when not declared(GenodeEnv):
include genode/env
type DataspaceCapability {. type DataspaceCapability {.
importcpp: "Genode::Dataspace_capability", pure.} = object importcpp: "Genode::Dataspace_capability", pure.} = object
@ -31,35 +36,35 @@ type
const SlabBackendSize = 4096 const SlabBackendSize = 4096
proc ramAvail(): int {. proc ramAvail(env: GenodeEnv): int {.
importcpp: "genodeEnv->pd().avail_ram().value".} importcpp: "#->pd().avail_ram().value".}
## Return number of bytes available for allocation. ## Return number of bytes available for allocation.
proc capsAvail(): int {. proc capsAvail(env: GenodeEnv): int {.
importcpp: "genodeEnv->pd().avail_caps().value".} importcpp: "#->pd().avail_caps().value".}
## Return the number of available capabilities. ## Return the number of available capabilities.
## Each dataspace allocation consumes a capability. ## Each dataspace allocation consumes a capability.
proc allocDataspace(size: int): DataspaceCapability {. proc allocDataspace(env: GenodeEnv; size: int): DataspaceCapability {.
importcpp: "genodeEnv->pd().alloc(@)".} importcpp: "#->pd().alloc(@)".}
## Allocate a dataspace and its capability. ## Allocate a dataspace and its capability.
proc attachDataspace(ds: DataspaceCapability): pointer {. proc attachDataspace(env: GenodeEnv; ds: DataspaceCapability): pointer {.
importcpp: "genodeEnv->rm().attach(@)".} importcpp: "#->rm().attach(@)".}
## Attach a dataspace into the component address-space. ## Attach a dataspace into the component address-space.
proc detachAddress(p: pointer) {. proc detachAddress(env: GenodeEnv; p: pointer) {.
importcpp: "genodeEnv->rm().detach(@)".} importcpp: "#->rm().detach(@)".}
## Detach a dataspace from the component address-space. ## Detach a dataspace from the component address-space.
proc freeDataspace(ds: DataspaceCapability) {. proc freeDataspace(env: GenodeEnv; ds: DataspaceCapability) {.
importcpp: "genodeEnv->pd().free(@)".} importcpp: "#->pd().free(@)".}
## Free a dataspace. ## Free a dataspace.
proc newMapSlab(): ptr MapSlab = proc newMapSlab(): ptr MapSlab =
let let
ds = allocDataspace SlabBackendSize ds = runtimeEnv.allocDataspace SlabBackendSize
p = attachDataspace ds p = runtimeEnv.attachDataspace ds
result = cast[ptr MapSlab](p) result = cast[ptr MapSlab](p)
result.meta.ds = ds result.meta.ds = ds
@ -89,13 +94,13 @@ proc osAllocPages(size: int): pointer =
# tack a new slab on the tail # tack a new slab on the tail
slab = slab.meta.next slab = slab.meta.next
# move to next slab in linked list # move to next slab in linked list
map.ds = allocDataspace size map.ds = runtimeEnv.allocDataspace size
map.size = size map.size = size
map.attachment = attachDataspace map.ds map.attachment = runtimeEnv.attachDataspace map.ds
result = map.attachment result = map.attachment
proc osTryAllocPages(size: int): pointer = proc osTryAllocPages(size: int): pointer =
if ramAvail() >= size and capsAvail() > 1: if runtimeEnv.ramAvail() >= size and runtimeEnv.capsAvail() > 4:
result = osAllocPages size result = osAllocPages size
proc osDeallocPages(p: pointer; size: int) = proc osDeallocPages(p: pointer; size: int) =
@ -107,8 +112,8 @@ proc osDeallocPages(p: pointer; size: int) =
if m.size != size: if m.size != size:
echo "cannot partially detach dataspace" echo "cannot partially detach dataspace"
quit -1 quit -1
detachAddress m.attachment runtimeEnv.detachAddress m.attachment
freeDataspace m.ds runtimeEnv.freeDataspace m.ds
m[] = Map() m[] = Map()
return return
slab = slab.meta.next slab = slab.meta.next

29
lib/genode/env.nim Normal file
View 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

View file

@ -13,6 +13,7 @@
#define _GENODE_CPP__THREAD_H_ #define _GENODE_CPP__THREAD_H_
#include <base/thread.h> #include <base/thread.h>
#include <base/env.h>
#include <util/reconstructible.h> #include <util/reconstructible.h>
namespace Nim { struct SysThread; } namespace Nim { struct SysThread; }

View file

@ -502,11 +502,6 @@ typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == siz
# include <sys/types.h> # include <sys/types.h>
#endif #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 */ /* Compile with -d:checkAbi and a sufficiently C11:ish compiler to enable */
#define NIM_CHECK_SIZE(typ, sz) \ #define NIM_CHECK_SIZE(typ, sz) \
_Static_assert(sizeof(typ) == sz, "Nim & C disagree on type size") _Static_assert(sizeof(typ) == sz, "Nim & C disagree on type size")

View file

@ -38,8 +38,10 @@ when defined(macosx) or defined(bsd):
importc: "sysctl", nodecl.} importc: "sysctl", nodecl.}
when defined(genode): when defined(genode):
proc affinitySpaceTotal(): cuint {. include genode/env
importcpp: "genodeEnv->cpu().affinity_space().total()".}
proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {.
importcpp: "@->cpu().affinity_space().total()".}
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
## returns the numer of the processors/cores the machine has. ## 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 var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "<unistd.h>".}: cint
result = sysconf(SC_NPROC_ONLN) result = sysconf(SC_NPROC_ONLN)
elif defined(genode): elif defined(genode):
result = affinitySpaceTotal().int result = runtimeEnv.affinitySpaceTotal().int
else: else:
result = sysconf(SC_NPROCESSORS_ONLN) result = sysconf(SC_NPROCESSORS_ONLN)
if result <= 0: result = 0 if result <= 0: result = 0

View file

@ -1440,7 +1440,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
elif defined(solaris): elif defined(solaris):
result = getApplAux("/proc/" & $getpid() & "/path/a.out") result = getApplAux("/proc/" & $getpid() & "/path/a.out")
elif defined(genode): elif defined(genode):
raiseOSError("POSIX command line not supported") raiseOSError(OSErrorCode(-1), "POSIX command line not supported")
elif defined(freebsd) or defined(dragonfly): elif defined(freebsd) or defined(dragonfly):
result = getApplFreebsd() result = getApplFreebsd()
# little heuristic that may work on other POSIX-like systems: # little heuristic that may work on other POSIX-like systems:

View file

@ -1498,11 +1498,21 @@ when defined(nimdoc):
## macro, use the `error <manual.html#error-pragma>`_ or `fatal ## macro, use the `error <manual.html#error-pragma>`_ or `fatal
## <manual.html#fatal-pragma>`_ pragmas. ## <manual.html#fatal-pragma>`_ pragmas.
elif defined(genode): elif defined(genode):
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn, include genode/env
importcpp: "genodeEnv->parent().exit(@); Genode::sleep_forever()",
header: "<base/sleep.h>".} 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): elif defined(nodejs):
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit",
@ -4215,3 +4225,22 @@ when not defined(js):
type type
ForLoopStmt* {.compilerProc.} = object ## special type that marks a macro ForLoopStmt* {.compilerProc.} = object ## special type that marks a macro
## as a `for-loop macro`:idx: ## 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.

View file

@ -78,7 +78,7 @@ when defined(emscripten):
munmap(mmapDescr.realPointer, mmapDescr.realSize) munmap(mmapDescr.realPointer, mmapDescr.realSize)
elif defined(genode): elif defined(genode):
include genodealloc # osAllocPages, osTryAllocPages, osDeallocPages include genode/alloc # osAllocPages, osTryAllocPages, osDeallocPages
elif defined(posix): elif defined(posix):
const const

View file

@ -116,6 +116,7 @@ when defined(windows):
importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".} importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
elif defined(genode): elif defined(genode):
import genode/env
const const
GenodeHeader = "genode_cpp/threads.h" GenodeHeader = "genode_cpp/threads.h"
type type
@ -125,11 +126,12 @@ elif defined(genode):
ThreadVarSlot = int ThreadVarSlot = int
proc initThread(s: var SysThread, proc initThread(s: var SysThread,
env: GenodeEnv,
stackSize: culonglong, stackSize: culonglong,
entry: GenodeThreadProc, entry: GenodeThreadProc,
arg: pointer, arg: pointer,
affinity: cuint) {. affinity: cuint) {.
importcpp: "#.initThread(genodeEnv, @)".} importcpp: "#.initThread(@)".}
proc threadVarAlloc(): ThreadVarSlot = 0 proc threadVarAlloc(): ThreadVarSlot = 0
@ -569,7 +571,7 @@ when hostOS == "windows":
elif defined(genode): elif defined(genode):
var affinityOffset: cuint = 1 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], proc createThread*[TArg](t: var Thread[TArg],
tp: proc (arg: TArg) {.thread, nimcall.}, tp: proc (arg: TArg) {.thread, nimcall.},
@ -580,6 +582,7 @@ elif defined(genode):
t.dataFn = tp t.dataFn = tp
when hasSharedHeap: t.stackSize = ThreadStackSize when hasSharedHeap: t.stackSize = ThreadStackSize
t.sys.initThread( t.sys.initThread(
runtimeEnv,
ThreadStackSize.culonglong, ThreadStackSize.culonglong,
threadProcWrapper[TArg], addr(t), affinityOffset) threadProcWrapper[TArg], addr(t), affinityOffset)
inc affinityOffset inc affinityOffset

View file

@ -44,6 +44,10 @@ else:
const const
DLLSSLName* = "libssl" & versions & ".dylib" DLLSSLName* = "libssl" & versions & ".dylib"
DLLUtilName* = "libcrypto" & versions & ".dylib" DLLUtilName* = "libcrypto" & versions & ".dylib"
elif defined(genode):
const
DLLSSLName* = "libssl.lib.so"
DLLUtilName* = "libcrypto.lib.so"
else: else:
const const
DLLSSLName* = "libssl.so" & versions DLLSSLName* = "libssl.so" & versions