summary refs log tree commit diff stats
path: root/lib/system/threads.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system/threads.nim')
-rw-r--r--lib/system/threads.nim75
1 files changed, 74 insertions, 1 deletions
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index dc9cc9656..4855a2b93 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -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.},