mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-16 01:35:35 +00:00
support for the Genode OS framework (#5560)
This commit is contained in:
committed by
Andreas Rumpf
parent
57246cbcec
commit
7e351fc7fa
@@ -944,7 +944,6 @@ proc genEcho(p: BProc, n: PNode) =
|
||||
# this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
|
||||
# is threadsafe.
|
||||
internalAssert n.kind == nkBracket
|
||||
p.module.includeHeader("<stdio.h>")
|
||||
var args: Rope = nil
|
||||
var a: TLoc
|
||||
for i in countup(0, n.len-1):
|
||||
@@ -953,9 +952,15 @@ proc genEcho(p: BProc, n: PNode) =
|
||||
else:
|
||||
initLocExpr(p, n.sons[i], a)
|
||||
addf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
|
||||
linefmt(p, cpsStmts, "printf($1$2);$n",
|
||||
makeCString(repeat("%s", n.len) & tnl), args)
|
||||
linefmt(p, cpsStmts, "fflush(stdout);$n")
|
||||
if platform.targetOS == osGenode:
|
||||
# bypass libc and print directly to the Genode LOG session
|
||||
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) =
|
||||
if gSelectedGC == gcNone: message(n.info, warnGcMem, n.renderTree)
|
||||
|
||||
@@ -966,6 +966,19 @@ proc genMainProc(m: BModule) =
|
||||
MainProcs &
|
||||
"}$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
|
||||
if platform.targetOS == osWindows and
|
||||
gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
||||
@@ -976,6 +989,9 @@ proc genMainProc(m: BModule) =
|
||||
nimMain = WinNimDllMain
|
||||
otherMain = WinCDllMain
|
||||
m.includeHeader("<windows.h>")
|
||||
elif platform.targetOS == osGenode:
|
||||
nimMain = GenodeNimMain
|
||||
otherMain = ComponentConstruct
|
||||
elif optGenDynLib in gGlobalOptions:
|
||||
nimMain = PosixNimDllMain
|
||||
otherMain = PosixCDllMain
|
||||
|
||||
@@ -21,7 +21,7 @@ type
|
||||
# conditionals to condsyms (end of module).
|
||||
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
|
||||
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
|
||||
|
||||
type
|
||||
@@ -147,6 +147,11 @@ const
|
||||
objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\",
|
||||
scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".",
|
||||
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: "..",
|
||||
dllFrmt: "lib$1.so", altDirSep: "/",
|
||||
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,
|
||||
otherwise this property is inferred by the compiler. Note that ``noSideEffect``
|
||||
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
|
||||
contain a ``ref`` or ``closure`` type. This enforces
|
||||
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>
|
||||
#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")
|
||||
|
||||
@@ -37,6 +37,10 @@ when defined(macosx) or defined(bsd):
|
||||
a: var csize, b: pointer, c: int): cint {.
|
||||
importc: "sysctl", nodecl.}
|
||||
|
||||
when defined(genode):
|
||||
proc affinitySpaceTotal(): cuint {.
|
||||
importcpp: "genodeEnv->cpu().affinity_space().total()".}
|
||||
|
||||
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
|
||||
## returns the numer of the processors/cores the machine has.
|
||||
## Returns 0 if it cannot be detected.
|
||||
@@ -61,7 +65,8 @@ proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
|
||||
elif defined(irix):
|
||||
var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "<unistd.h>".}: cint
|
||||
result = sysconf(SC_NPROC_ONLN)
|
||||
elif defined(genode):
|
||||
result = affinitySpaceTotal().int
|
||||
else:
|
||||
result = sysconf(SC_NPROCESSORS_ONLN)
|
||||
if result <= 0: result = 1
|
||||
|
||||
|
||||
@@ -825,16 +825,16 @@ proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
|
||||
else:
|
||||
add environment, (key & '=' & val)
|
||||
indx = high(environment)
|
||||
when defined(unix):
|
||||
if c_putenv(environment[indx]) != 0'i32:
|
||||
raiseOSError(osLastError())
|
||||
else:
|
||||
when defined(windows):
|
||||
when useWinUnicode:
|
||||
var k = newWideCString(key)
|
||||
var v = newWideCString(val)
|
||||
if setEnvironmentVariableW(k, v) == 0'i32: raiseOSError(osLastError())
|
||||
else:
|
||||
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].} =
|
||||
## Iterate over all `environments variables`:idx:. In the first component
|
||||
@@ -1091,7 +1091,7 @@ proc rawCreateDir(dir: string): bool =
|
||||
result = false
|
||||
else:
|
||||
raiseOSError(osLastError())
|
||||
elif defined(unix):
|
||||
elif defined(posix):
|
||||
let res = mkdir(dir, 0o777)
|
||||
if res == 0'i32:
|
||||
result = true
|
||||
@@ -1452,7 +1452,9 @@ elif defined(windows):
|
||||
if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
|
||||
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.
|
||||
var
|
||||
cmdCount {.importc: "cmdCount".}: cint
|
||||
@@ -1606,6 +1608,8 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
|
||||
result = getApplAux("/proc/self/exe")
|
||||
elif defined(solaris):
|
||||
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
|
||||
elif defined(genode):
|
||||
raiseOSError("POSIX command line not supported")
|
||||
elif defined(freebsd) or defined(dragonfly):
|
||||
result = getApplFreebsd()
|
||||
# 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
|
||||
## prematurely using ``quit``, this value is ignored.
|
||||
|
||||
proc quit*(errorcode: int = QuitSuccess) {.
|
||||
magic: "Exit", importc: "exit", header: "<stdlib.h>", noreturn.}
|
||||
## Stops the program immediately with an exit code.
|
||||
##
|
||||
## Before stopping the program the "quit procedures" are called in the
|
||||
## opposite order they were added with `addQuitProc <#addQuitProc>`_.
|
||||
## ``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
|
||||
## all the memory, unless a quit procedure calls `GC_fullCollect
|
||||
## <#GC_fullCollect>`_.
|
||||
##
|
||||
## The proc ``quit(QuitSuccess)`` is called implicitly when your nim
|
||||
## program finishes without incident. A raised unhandled exception is
|
||||
## equivalent to calling ``quit(QuitFailure)``.
|
||||
##
|
||||
## 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
|
||||
## macro, use the `error <manual.html#error-pragma>`_ or `fatal
|
||||
## <manual.html#fatal-pragma>`_ pragmas.
|
||||
when defined(nimdoc):
|
||||
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.}
|
||||
## Stops the program immediately with an exit code.
|
||||
##
|
||||
## Before stopping the program the "quit procedures" are called in the
|
||||
## opposite order they were added with `addQuitProc <#addQuitProc>`_.
|
||||
## ``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
|
||||
## all the memory, unless a quit procedure calls `GC_fullCollect
|
||||
## <#GC_fullCollect>`_.
|
||||
##
|
||||
## The proc ``quit(QuitSuccess)`` is called implicitly when your nim
|
||||
## program finishes without incident. A raised unhandled exception is
|
||||
## equivalent to calling ``quit(QuitFailure)``.
|
||||
##
|
||||
## 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
|
||||
## 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(@)", header: "<base/env.h>".}
|
||||
|
||||
else:
|
||||
proc quit*(errorcode: int = QuitSuccess) {.
|
||||
magic: "Exit", importc: "exit", header: "<stdlib.h>", noreturn.}
|
||||
|
||||
template sysAssert(cond: bool, msg: string) =
|
||||
when defined(useSysAssert):
|
||||
|
||||
@@ -146,6 +146,17 @@ elif defined(windows) or defined(dos):
|
||||
if result != nil: return
|
||||
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:
|
||||
{.error: "no implementation for dyncalls".}
|
||||
|
||||
|
||||
@@ -77,6 +77,19 @@ when defined(emscripten):
|
||||
var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
|
||||
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):
|
||||
const
|
||||
PROT_READ = 1 # page can be read
|
||||
|
||||
@@ -75,6 +75,28 @@ when defined(Windows):
|
||||
proc waitSysCondWindows(cond: var SysCond) =
|
||||
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:
|
||||
type
|
||||
SysLock {.importc: "pthread_mutex_t", pure, final,
|
||||
|
||||
@@ -46,7 +46,11 @@ const
|
||||
maxRegisters = 256 # don't think there is an arch with more registers
|
||||
useStackMaskHack = false ## use the stack mask hack for better performance
|
||||
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
|
||||
|
||||
when defined(windows):
|
||||
@@ -115,6 +119,49 @@ when defined(windows):
|
||||
## get the ID of the currently running thread.
|
||||
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:
|
||||
when not defined(macosx):
|
||||
{.passL: "-pthread".}
|
||||
@@ -451,6 +498,9 @@ when defined(windows):
|
||||
proc threadProcWrapper[TArg](closure: pointer): int32 {.stdcall.} =
|
||||
threadProcWrapperBody(closure)
|
||||
# implicitly return 0
|
||||
elif defined(genode):
|
||||
proc threadProcWrapper[TArg](closure: pointer) {.noconv.} =
|
||||
threadProcWrapperBody(closure)
|
||||
else:
|
||||
proc threadProcWrapper[TArg](closure: pointer): pointer {.noconv.} =
|
||||
threadProcWrapperBody(closure)
|
||||
@@ -482,6 +532,14 @@ when hostOS == "windows":
|
||||
cast[ptr SysThread](addr(a)), 1, -1)
|
||||
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:
|
||||
proc joinThread*[TArg](t: Thread[TArg]) {.inline.} =
|
||||
## waits for the thread `t` to finish.
|
||||
@@ -531,6 +589,21 @@ when hostOS == "windows":
|
||||
## shouldn't use this proc.
|
||||
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:
|
||||
proc createThread*[TArg](t: var Thread[TArg],
|
||||
tp: proc (arg: TArg) {.thread, nimcall.},
|
||||
|
||||
Reference in New Issue
Block a user