support for the Genode OS framework (#5560)
This commit is contained in:
parent
57246cbcec
commit
7e351fc7fa
14 changed files with 348 additions and 33 deletions
|
|
@ -944,7 +944,6 @@ proc genEcho(p: BProc, n: PNode) =
|
||||||
# this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
|
# this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
|
||||||
# is threadsafe.
|
# is threadsafe.
|
||||||
internalAssert n.kind == nkBracket
|
internalAssert n.kind == nkBracket
|
||||||
p.module.includeHeader("<stdio.h>")
|
|
||||||
var args: Rope = nil
|
var args: Rope = nil
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
for i in countup(0, n.len-1):
|
for i in countup(0, n.len-1):
|
||||||
|
|
@ -953,9 +952,15 @@ proc genEcho(p: BProc, n: PNode) =
|
||||||
else:
|
else:
|
||||||
initLocExpr(p, n.sons[i], a)
|
initLocExpr(p, n.sons[i], a)
|
||||||
addf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
|
addf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
|
||||||
linefmt(p, cpsStmts, "printf($1$2);$n",
|
if platform.targetOS == osGenode:
|
||||||
makeCString(repeat("%s", n.len) & tnl), args)
|
# bypass libc and print directly to the Genode LOG session
|
||||||
linefmt(p, cpsStmts, "fflush(stdout);$n")
|
p.module.includeHeader("<base/log.h>")
|
||||||
|
linefmt(p, cpsStmts, """Genode::log(""$1);$n""", args)
|
||||||
|
else:
|
||||||
|
p.module.includeHeader("<stdio.h>")
|
||||||
|
linefmt(p, cpsStmts, "printf($1$2);$n",
|
||||||
|
makeCString(repeat("%s", n.len) & tnl), args)
|
||||||
|
linefmt(p, cpsStmts, "fflush(stdout);$n")
|
||||||
|
|
||||||
proc gcUsage(n: PNode) =
|
proc gcUsage(n: PNode) =
|
||||||
if gSelectedGC == gcNone: message(n.info, warnGcMem, n.renderTree)
|
if gSelectedGC == gcNone: message(n.info, warnGcMem, n.renderTree)
|
||||||
|
|
|
||||||
|
|
@ -966,6 +966,19 @@ proc genMainProc(m: BModule) =
|
||||||
MainProcs &
|
MainProcs &
|
||||||
"}$N$N"
|
"}$N$N"
|
||||||
|
|
||||||
|
GenodeNimMain =
|
||||||
|
"Libc::Env *genodeEnv;$N" &
|
||||||
|
NimMainBody
|
||||||
|
|
||||||
|
ComponentConstruct =
|
||||||
|
"void Libc::Component::construct(Libc::Env &env) {$N" &
|
||||||
|
"\tgenodeEnv = &env;$N" &
|
||||||
|
"\tLibc::with_libc([&] () {$n\t" &
|
||||||
|
MainProcs &
|
||||||
|
"\t});$N" &
|
||||||
|
"\tenv.parent().exit(0);$N" &
|
||||||
|
"}$N$N"
|
||||||
|
|
||||||
var nimMain, otherMain: FormatStr
|
var nimMain, otherMain: FormatStr
|
||||||
if platform.targetOS == osWindows and
|
if platform.targetOS == osWindows and
|
||||||
gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
||||||
|
|
@ -976,6 +989,9 @@ proc genMainProc(m: BModule) =
|
||||||
nimMain = WinNimDllMain
|
nimMain = WinNimDllMain
|
||||||
otherMain = WinCDllMain
|
otherMain = WinCDllMain
|
||||||
m.includeHeader("<windows.h>")
|
m.includeHeader("<windows.h>")
|
||||||
|
elif platform.targetOS == osGenode:
|
||||||
|
nimMain = GenodeNimMain
|
||||||
|
otherMain = ComponentConstruct
|
||||||
elif optGenDynLib in gGlobalOptions:
|
elif optGenDynLib in gGlobalOptions:
|
||||||
nimMain = PosixNimDllMain
|
nimMain = PosixNimDllMain
|
||||||
otherMain = PosixCDllMain
|
otherMain = PosixCDllMain
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ type
|
||||||
# conditionals to condsyms (end of module).
|
# conditionals to condsyms (end of module).
|
||||||
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
||||||
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
|
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osAix, osPalmos, osQnx,
|
||||||
osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osVxworks,
|
osAmiga, osAtari, osNetware, osMacos, osMacosx, osHaiku, osVxworks, osGenode
|
||||||
osJS, osNimrodVM, osStandalone
|
osJS, osNimrodVM, osStandalone
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -147,6 +147,11 @@ const
|
||||||
objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\",
|
objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\",
|
||||||
scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".",
|
scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".",
|
||||||
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
|
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
|
||||||
|
(name: "Genode", pardir: "..", dllFrmt: "$1.lib.so", altDirSep: "/",
|
||||||
|
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
|
||||||
|
scriptExt: "", curDir: "/", exeExt: "", extSep: ".",
|
||||||
|
props: {ospNeedsPIC, ospLacksThreadVars}),
|
||||||
|
|
||||||
(name: "JS", parDir: "..",
|
(name: "JS", parDir: "..",
|
||||||
dllFrmt: "lib$1.so", altDirSep: "/",
|
dllFrmt: "lib$1.so", altDirSep: "/",
|
||||||
objExt: ".o", newLine: "\x0A",
|
objExt: ".o", newLine: "\x0A",
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ directly or indirectly through a call to a GC unsafe proc.
|
||||||
The `gcsafe`:idx: annotation can be used to mark a proc to be gcsafe,
|
The `gcsafe`:idx: annotation can be used to mark a proc to be gcsafe,
|
||||||
otherwise this property is inferred by the compiler. Note that ``noSideEffect``
|
otherwise this property is inferred by the compiler. Note that ``noSideEffect``
|
||||||
implies ``gcsafe``. The only way to create a thread is via ``spawn`` or
|
implies ``gcsafe``. The only way to create a thread is via ``spawn`` or
|
||||||
``createThead``. ``spawn`` is usually the preferable method. Either way
|
``createThread``. ``spawn`` is usually the preferable method. Either way
|
||||||
the invoked proc must not use ``var`` parameters nor must any of its parameters
|
the invoked proc must not use ``var`` parameters nor must any of its parameters
|
||||||
contain a ``ref`` or ``closure`` type. This enforces
|
contain a ``ref`` or ``closure`` type. This enforces
|
||||||
the *no heap sharing restriction*.
|
the *no heap sharing restriction*.
|
||||||
|
|
|
||||||
78
lib/genode_cpp/syslocks.h
Normal file
78
lib/genode_cpp/syslocks.h
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Nim's Runtime Library
|
||||||
|
* (c) Copyright 2017 Emery Hemingway
|
||||||
|
*
|
||||||
|
* See the file "copying.txt", included in this
|
||||||
|
* distribution, for details about the copyright.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GENODE_CPP__SYSLOCKS_H_
|
||||||
|
#define _GENODE_CPP__SYSLOCKS_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <base/semaphore.h>
|
||||||
|
#include <base/lock.h>
|
||||||
|
|
||||||
|
namespace Nim {
|
||||||
|
struct SysLock;
|
||||||
|
struct SysCond;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Nim::SysLock
|
||||||
|
{
|
||||||
|
Genode::Lock _lock_a, _lock_b;
|
||||||
|
bool _locked;
|
||||||
|
|
||||||
|
void acquireSys()
|
||||||
|
{
|
||||||
|
_lock_a.lock();
|
||||||
|
_locked = true;
|
||||||
|
_lock_a.unlock();
|
||||||
|
_lock_b.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tryAcquireSys()
|
||||||
|
{
|
||||||
|
if (_locked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_lock_a.lock();
|
||||||
|
if (_locked) {
|
||||||
|
_lock_a.unlock();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
_locked = true;
|
||||||
|
_lock_b.lock();
|
||||||
|
_lock_a.unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseSys()
|
||||||
|
{
|
||||||
|
_locked = false;
|
||||||
|
_lock_a.unlock();
|
||||||
|
_lock_b.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Nim::SysCond
|
||||||
|
{
|
||||||
|
Genode::Semaphore _semaphore;
|
||||||
|
|
||||||
|
void waitSysCond(SysLock &syslock)
|
||||||
|
{
|
||||||
|
syslock.releaseSys();
|
||||||
|
_semaphore.down();
|
||||||
|
syslock.acquireSys();
|
||||||
|
}
|
||||||
|
|
||||||
|
void signalSysCond()
|
||||||
|
{
|
||||||
|
_semaphore.up();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
69
lib/genode_cpp/threads.h
Normal file
69
lib/genode_cpp/threads.h
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Nim's Runtime Library
|
||||||
|
* (c) Copyright 2017 Emery Hemingway
|
||||||
|
*
|
||||||
|
* See the file "copying.txt", included in this
|
||||||
|
* distribution, for details about the copyright.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _GENODE_CPP__THREAD_H_
|
||||||
|
#define _GENODE_CPP__THREAD_H_
|
||||||
|
|
||||||
|
#include <base/thread.h>
|
||||||
|
#include <util/avl_tree.h>
|
||||||
|
#include <util/reconstructible.h>
|
||||||
|
|
||||||
|
namespace Nim { struct SysThread; }
|
||||||
|
|
||||||
|
struct Nim::SysThread
|
||||||
|
{
|
||||||
|
typedef void (Entry)(void*);
|
||||||
|
|
||||||
|
struct Thread : Genode::Thread
|
||||||
|
{
|
||||||
|
void *_tls;
|
||||||
|
|
||||||
|
Entry *_func;
|
||||||
|
void *_arg;
|
||||||
|
|
||||||
|
void entry() override {
|
||||||
|
(_func)(_arg); }
|
||||||
|
|
||||||
|
Thread(Genode::Env &env, Genode::size_t stack_size, Entry func, void *arg)
|
||||||
|
: Genode::Thread(env, "nim-thread", stack_size), _func(func), _arg(arg)
|
||||||
|
{
|
||||||
|
Genode::Thread::start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Genode::Constructible<Thread> _thread;
|
||||||
|
|
||||||
|
void initThread(Genode::Env *env, Genode::size_t stack_size, Entry func, void *arg) {
|
||||||
|
_thread.construct(*env, stack_size, func, arg); }
|
||||||
|
|
||||||
|
void joinThread() {
|
||||||
|
_thread->join(); }
|
||||||
|
|
||||||
|
static bool offMainThread() {
|
||||||
|
return dynamic_cast<SysThread::Thread*>(Genode::Thread::myself()); }
|
||||||
|
|
||||||
|
static void *threadVarGetValue()
|
||||||
|
{
|
||||||
|
SysThread::Thread *thr =
|
||||||
|
static_cast<SysThread::Thread*>(Genode::Thread::myself());
|
||||||
|
return thr->_tls;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void threadVarSetValue(void *value)
|
||||||
|
{
|
||||||
|
SysThread::Thread *thr =
|
||||||
|
static_cast<SysThread::Thread*>(Genode::Thread::myself());
|
||||||
|
thr->_tls = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -498,6 +498,11 @@ 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")
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,10 @@ when defined(macosx) or defined(bsd):
|
||||||
a: var csize, b: pointer, c: int): cint {.
|
a: var csize, b: pointer, c: int): cint {.
|
||||||
importc: "sysctl", nodecl.}
|
importc: "sysctl", nodecl.}
|
||||||
|
|
||||||
|
when defined(genode):
|
||||||
|
proc affinitySpaceTotal(): cuint {.
|
||||||
|
importcpp: "genodeEnv->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.
|
||||||
## Returns 0 if it cannot be detected.
|
## Returns 0 if it cannot be detected.
|
||||||
|
|
@ -61,7 +65,8 @@ proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
|
||||||
elif defined(irix):
|
elif defined(irix):
|
||||||
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):
|
||||||
|
result = affinitySpaceTotal().int
|
||||||
else:
|
else:
|
||||||
result = sysconf(SC_NPROCESSORS_ONLN)
|
result = sysconf(SC_NPROCESSORS_ONLN)
|
||||||
if result <= 0: result = 1
|
if result <= 0: result = 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -825,16 +825,16 @@ proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
|
||||||
else:
|
else:
|
||||||
add environment, (key & '=' & val)
|
add environment, (key & '=' & val)
|
||||||
indx = high(environment)
|
indx = high(environment)
|
||||||
when defined(unix):
|
when defined(windows):
|
||||||
if c_putenv(environment[indx]) != 0'i32:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
else:
|
|
||||||
when useWinUnicode:
|
when useWinUnicode:
|
||||||
var k = newWideCString(key)
|
var k = newWideCString(key)
|
||||||
var v = newWideCString(val)
|
var v = newWideCString(val)
|
||||||
if setEnvironmentVariableW(k, v) == 0'i32: raiseOSError(osLastError())
|
if setEnvironmentVariableW(k, v) == 0'i32: raiseOSError(osLastError())
|
||||||
else:
|
else:
|
||||||
if setEnvironmentVariableA(key, val) == 0'i32: raiseOSError(osLastError())
|
if setEnvironmentVariableA(key, val) == 0'i32: raiseOSError(osLastError())
|
||||||
|
else:
|
||||||
|
if c_putenv(environment[indx]) != 0'i32:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
||||||
## Iterate over all `environments variables`:idx:. In the first component
|
## Iterate over all `environments variables`:idx:. In the first component
|
||||||
|
|
@ -1091,7 +1091,7 @@ proc rawCreateDir(dir: string): bool =
|
||||||
result = false
|
result = false
|
||||||
else:
|
else:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
elif defined(unix):
|
elif defined(posix):
|
||||||
let res = mkdir(dir, 0o777)
|
let res = mkdir(dir, 0o777)
|
||||||
if res == 0'i32:
|
if res == 0'i32:
|
||||||
result = true
|
result = true
|
||||||
|
|
@ -1452,7 +1452,9 @@ elif defined(windows):
|
||||||
if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
|
if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
|
||||||
return TaintedString(ownArgv[i])
|
return TaintedString(ownArgv[i])
|
||||||
|
|
||||||
elif not defined(createNimRtl) and not(defined(posix) and appType == "lib"):
|
elif not defined(createNimRtl) and
|
||||||
|
not(defined(posix) and appType == "lib") and
|
||||||
|
not defined(genode):
|
||||||
# On Posix, there is no portable way to get the command line from a DLL.
|
# On Posix, there is no portable way to get the command line from a DLL.
|
||||||
var
|
var
|
||||||
cmdCount {.importc: "cmdCount".}: cint
|
cmdCount {.importc: "cmdCount".}: cint
|
||||||
|
|
@ -1606,6 +1608,8 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
|
||||||
result = getApplAux("/proc/self/exe")
|
result = getApplAux("/proc/self/exe")
|
||||||
elif defined(solaris):
|
elif defined(solaris):
|
||||||
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
|
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
|
||||||
|
elif defined(genode):
|
||||||
|
raiseOSError("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:
|
||||||
|
|
|
||||||
|
|
@ -1384,25 +1384,34 @@ var programResult* {.exportc: "nim_program_result".}: int
|
||||||
## under normal circumstances. When the program is terminated
|
## under normal circumstances. When the program is terminated
|
||||||
## prematurely using ``quit``, this value is ignored.
|
## prematurely using ``quit``, this value is ignored.
|
||||||
|
|
||||||
proc quit*(errorcode: int = QuitSuccess) {.
|
when defined(nimdoc):
|
||||||
magic: "Exit", importc: "exit", header: "<stdlib.h>", noreturn.}
|
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.}
|
||||||
## Stops the program immediately with an exit code.
|
## Stops the program immediately with an exit code.
|
||||||
##
|
##
|
||||||
## Before stopping the program the "quit procedures" are called in the
|
## Before stopping the program the "quit procedures" are called in the
|
||||||
## opposite order they were added with `addQuitProc <#addQuitProc>`_.
|
## opposite order they were added with `addQuitProc <#addQuitProc>`_.
|
||||||
## ``quit`` never returns and ignores any exception that may have been raised
|
## ``quit`` never returns and ignores any exception that may have been raised
|
||||||
## by the quit procedures. It does *not* call the garbage collector to free
|
## by the quit procedures. It does *not* call the garbage collector to free
|
||||||
## all the memory, unless a quit procedure calls `GC_fullCollect
|
## all the memory, unless a quit procedure calls `GC_fullCollect
|
||||||
## <#GC_fullCollect>`_.
|
## <#GC_fullCollect>`_.
|
||||||
##
|
##
|
||||||
## The proc ``quit(QuitSuccess)`` is called implicitly when your nim
|
## The proc ``quit(QuitSuccess)`` is called implicitly when your nim
|
||||||
## program finishes without incident. A raised unhandled exception is
|
## program finishes without incident. A raised unhandled exception is
|
||||||
## equivalent to calling ``quit(QuitFailure)``.
|
## equivalent to calling ``quit(QuitFailure)``.
|
||||||
##
|
##
|
||||||
## Note that this is a *runtime* call and using ``quit`` inside a macro won't
|
## Note that this is a *runtime* call and using ``quit`` inside a macro won't
|
||||||
## have any compile time effect. If you need to stop the compiler inside a
|
## have any compile time effect. If you need to stop the compiler inside a
|
||||||
## 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):
|
||||||
|
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn,
|
||||||
|
importcpp: "genodeEnv->parent().exit(@)", header: "<base/env.h>".}
|
||||||
|
|
||||||
|
else:
|
||||||
|
proc quit*(errorcode: int = QuitSuccess) {.
|
||||||
|
magic: "Exit", importc: "exit", header: "<stdlib.h>", noreturn.}
|
||||||
|
|
||||||
template sysAssert(cond: bool, msg: string) =
|
template sysAssert(cond: bool, msg: string) =
|
||||||
when defined(useSysAssert):
|
when defined(useSysAssert):
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,17 @@ elif defined(windows) or defined(dos):
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
procAddrError(name)
|
procAddrError(name)
|
||||||
|
|
||||||
|
elif defined(genode):
|
||||||
|
|
||||||
|
proc nimUnloadLibrary(lib: LibHandle) {.
|
||||||
|
error: "nimUnloadLibrary not implemented".}
|
||||||
|
|
||||||
|
proc nimLoadLibrary(path: string): LibHandle {.
|
||||||
|
error: "nimLoadLibrary not implemented".}
|
||||||
|
|
||||||
|
proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.
|
||||||
|
error: "nimGetProcAddr not implemented".}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
{.error: "no implementation for dyncalls".}
|
{.error: "no implementation for dyncalls".}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,19 @@ when defined(emscripten):
|
||||||
var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
|
var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
|
||||||
munmap(mmapDescr.realPointer, mmapDescr.realSize)
|
munmap(mmapDescr.realPointer, mmapDescr.realSize)
|
||||||
|
|
||||||
|
elif defined(genode):
|
||||||
|
|
||||||
|
proc osAllocPages(size: int): pointer {.
|
||||||
|
importcpp: "genodeEnv->rm().attach(genodeEnv->ram().alloc(@))".}
|
||||||
|
|
||||||
|
proc osTryAllocPages(size: int): pointer =
|
||||||
|
{.emit: """try {""".}
|
||||||
|
result = osAllocPages size
|
||||||
|
{.emit: """} catch (...) { }""".}
|
||||||
|
|
||||||
|
proc osDeallocPages(p: pointer, size: int) {.
|
||||||
|
importcpp: "genodeEnv->rm().detach(#)".}
|
||||||
|
|
||||||
elif defined(posix):
|
elif defined(posix):
|
||||||
const
|
const
|
||||||
PROT_READ = 1 # page can be read
|
PROT_READ = 1 # page can be read
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,28 @@ when defined(Windows):
|
||||||
proc waitSysCondWindows(cond: var SysCond) =
|
proc waitSysCondWindows(cond: var SysCond) =
|
||||||
discard waitForSingleObject(cond, -1'i32)
|
discard waitForSingleObject(cond, -1'i32)
|
||||||
|
|
||||||
|
elif defined(genode):
|
||||||
|
const
|
||||||
|
Header = "genode_cpp/syslocks.h"
|
||||||
|
type
|
||||||
|
SysLock {.importcpp: "Nim::SysLock", pure, final,
|
||||||
|
header: Header.} = object
|
||||||
|
SysCond {.importcpp: "Nim::SysCond", pure, final,
|
||||||
|
header: Header.} = object
|
||||||
|
|
||||||
|
proc initSysLock(L: var SysLock) = discard
|
||||||
|
proc deinitSys(L: var SysLock) = discard
|
||||||
|
proc acquireSys(L: var SysLock) {.noSideEffect, importcpp.}
|
||||||
|
proc tryAcquireSys(L: var SysLock): bool {.noSideEffect, importcpp.}
|
||||||
|
proc releaseSys(L: var SysLock) {.noSideEffect, importcpp.}
|
||||||
|
|
||||||
|
proc initSysCond(L: var SysCond) = discard
|
||||||
|
proc deinitSysCond(L: var SysCond) = discard
|
||||||
|
proc waitSysCond(cond: var SysCond, lock: var SysLock) {.
|
||||||
|
noSideEffect, importcpp.}
|
||||||
|
proc signalSysCond(cond: var SysCond) {.
|
||||||
|
noSideEffect, importcpp.}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
type
|
type
|
||||||
SysLock {.importc: "pthread_mutex_t", pure, final,
|
SysLock {.importc: "pthread_mutex_t", pure, final,
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,11 @@ const
|
||||||
maxRegisters = 256 # don't think there is an arch with more registers
|
maxRegisters = 256 # don't think there is an arch with more registers
|
||||||
useStackMaskHack = false ## use the stack mask hack for better performance
|
useStackMaskHack = false ## use the stack mask hack for better performance
|
||||||
StackGuardSize = 4096
|
StackGuardSize = 4096
|
||||||
ThreadStackMask = 1024*256*sizeof(int)-1
|
ThreadStackMask =
|
||||||
|
when defined(genode):
|
||||||
|
1024*64*sizeof(int)-1
|
||||||
|
else:
|
||||||
|
1024*256*sizeof(int)-1
|
||||||
ThreadStackSize = ThreadStackMask+1 - StackGuardSize
|
ThreadStackSize = ThreadStackMask+1 - StackGuardSize
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
|
|
@ -115,6 +119,49 @@ when defined(windows):
|
||||||
## get the ID of the currently running thread.
|
## get the ID of the currently running thread.
|
||||||
result = int(getCurrentThreadId())
|
result = int(getCurrentThreadId())
|
||||||
|
|
||||||
|
elif defined(genode):
|
||||||
|
const
|
||||||
|
GenodeHeader = "genode_cpp/threads.h"
|
||||||
|
type
|
||||||
|
SysThread* {.importcpp: "Nim::SysThread",
|
||||||
|
header: GenodeHeader, final, pure.} = object
|
||||||
|
GenodeThreadProc = proc (x: pointer) {.noconv.}
|
||||||
|
ThreadVarSlot = int
|
||||||
|
|
||||||
|
proc initThread(s: var SysThread,
|
||||||
|
stackSize: culonglong,
|
||||||
|
entry: GenodeThreadProc,
|
||||||
|
arg: pointer) {.
|
||||||
|
importcpp: "#.initThread(genodeEnv, @)".}
|
||||||
|
|
||||||
|
proc threadVarAlloc(): ThreadVarSlot = 0
|
||||||
|
|
||||||
|
proc offMainThread(): bool {.
|
||||||
|
importcpp: "Nim::SysThread::offMainThread",
|
||||||
|
header: GenodeHeader.}
|
||||||
|
|
||||||
|
proc threadVarSetValue(value: pointer) {.
|
||||||
|
importcpp: "Nim::SysThread::threadVarSetValue(@)",
|
||||||
|
header: GenodeHeader.}
|
||||||
|
|
||||||
|
proc threadVarGetValue(): pointer {.
|
||||||
|
importcpp: "Nim::SysThread::threadVarGetValue()",
|
||||||
|
header: GenodeHeader.}
|
||||||
|
|
||||||
|
var mainTls: pointer
|
||||||
|
|
||||||
|
proc threadVarSetValue(s: ThreadVarSlot, value: pointer) {.inline.} =
|
||||||
|
if offMainThread():
|
||||||
|
threadVarSetValue(value);
|
||||||
|
else:
|
||||||
|
mainTls = value
|
||||||
|
|
||||||
|
proc threadVarGetValue(s: ThreadVarSlot): pointer {.inline.} =
|
||||||
|
if offMainThread():
|
||||||
|
threadVarGetValue();
|
||||||
|
else:
|
||||||
|
mainTls
|
||||||
|
|
||||||
else:
|
else:
|
||||||
when not defined(macosx):
|
when not defined(macosx):
|
||||||
{.passL: "-pthread".}
|
{.passL: "-pthread".}
|
||||||
|
|
@ -451,6 +498,9 @@ when defined(windows):
|
||||||
proc threadProcWrapper[TArg](closure: pointer): int32 {.stdcall.} =
|
proc threadProcWrapper[TArg](closure: pointer): int32 {.stdcall.} =
|
||||||
threadProcWrapperBody(closure)
|
threadProcWrapperBody(closure)
|
||||||
# implicitly return 0
|
# implicitly return 0
|
||||||
|
elif defined(genode):
|
||||||
|
proc threadProcWrapper[TArg](closure: pointer) {.noconv.} =
|
||||||
|
threadProcWrapperBody(closure)
|
||||||
else:
|
else:
|
||||||
proc threadProcWrapper[TArg](closure: pointer): pointer {.noconv.} =
|
proc threadProcWrapper[TArg](closure: pointer): pointer {.noconv.} =
|
||||||
threadProcWrapperBody(closure)
|
threadProcWrapperBody(closure)
|
||||||
|
|
@ -482,6 +532,14 @@ when hostOS == "windows":
|
||||||
cast[ptr SysThread](addr(a)), 1, -1)
|
cast[ptr SysThread](addr(a)), 1, -1)
|
||||||
inc(k, MAXIMUM_WAIT_OBJECTS)
|
inc(k, MAXIMUM_WAIT_OBJECTS)
|
||||||
|
|
||||||
|
elif defined(genode):
|
||||||
|
proc joinThread*[TArg](t: Thread[TArg]) {.importcpp.}
|
||||||
|
## waits for the thread `t` to finish.
|
||||||
|
|
||||||
|
proc joinThreads*[TArg](t: varargs[Thread[TArg]]) =
|
||||||
|
## waits for every thread in `t` to finish.
|
||||||
|
for i in 0..t.high: joinThread(t[i])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
proc joinThread*[TArg](t: Thread[TArg]) {.inline.} =
|
proc joinThread*[TArg](t: Thread[TArg]) {.inline.} =
|
||||||
## waits for the thread `t` to finish.
|
## waits for the thread `t` to finish.
|
||||||
|
|
@ -531,6 +589,21 @@ when hostOS == "windows":
|
||||||
## shouldn't use this proc.
|
## shouldn't use this proc.
|
||||||
setThreadAffinityMask(t.sys, uint(1 shl cpu))
|
setThreadAffinityMask(t.sys, uint(1 shl cpu))
|
||||||
|
|
||||||
|
elif defined(genode):
|
||||||
|
proc createThread*[TArg](t: var Thread[TArg],
|
||||||
|
tp: proc (arg: TArg) {.thread, nimcall.},
|
||||||
|
param: TArg) =
|
||||||
|
when TArg isnot void: t.data = param
|
||||||
|
t.dataFn = tp
|
||||||
|
when hasSharedHeap: t.stackSize = ThreadStackSize
|
||||||
|
t.sys.initThread(
|
||||||
|
ThreadStackSize.culonglong,
|
||||||
|
threadProcWrapper[TArg], addr(t))
|
||||||
|
|
||||||
|
proc pinToCpu*[Arg](t: var Thread[Arg]; cpu: Natural) =
|
||||||
|
{.hint: "cannot change Genode thread CPU affinity after initialization".}
|
||||||
|
discard
|
||||||
|
|
||||||
else:
|
else:
|
||||||
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.},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue