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.nim140
1 files changed, 89 insertions, 51 deletions
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 49b13576c..a7a811844 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -115,10 +115,6 @@ when defined(windows):
   proc setThreadAffinityMask(hThread: SysThread, dwThreadAffinityMask: uint) {.
     importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
 
-  proc getThreadId*(): int =
-    ## get the ID of the currently running thread.
-    result = int(getCurrentThreadId())
-
 elif defined(genode):
   const
     GenodeHeader = "genode_cpp/threads.h"
@@ -249,48 +245,6 @@ else:
   proc setAffinity(thread: SysThread; setsize: csize; s: var CpuSet) {.
     importc: "pthread_setaffinity_np", header: pthreadh.}
 
-  when defined(linux):
-    proc syscall(arg: clong): clong {.varargs, importc: "syscall", header: "<unistd.h>".}
-    var NR_gettid {.importc: "__NR_gettid", header: "<sys/syscall.h>".}: int
-
-    #type Pid {.importc: "pid_t", header: "<sys/types.h>".} = distinct int
-    #proc gettid(): Pid {.importc, header: "<sys/types.h>".}
-
-    proc getThreadId*(): int =
-      ## get the ID of the currently running thread.
-      result = int(syscall(NR_gettid))
-  elif defined(dragonfly):
-    proc lwp_gettid(): int32 {.importc, header: "unistd.h".}
-
-    proc getThreadId*(): int =
-      result = int(lwp_gettid())
-  elif defined(openbsd):
-    proc getthrid(): int32 {.importc: "getthrid", header: "<unistd.h>".}
-
-    proc getThreadId*(): int =
-      result = int(getthrid())
-  elif defined(netbsd):
-    proc lwp_self(): int32 {.importc: "_lwp_self", header: "<lwp.h>".}
-
-    proc getThreadId*(): int =
-      result = int(lwp_self())
-  elif defined(macosx) or defined(freebsd):
-    proc pthread_threadid_np(y: pointer; x: var uint64): cint {.importc, header: "pthread.h".}
-
-    proc getThreadId*(): int =
-      ## get the ID of the currently running thread.
-      var x: uint64
-      result = pthread_threadid_np(nil, x)
-      result = int(x)
-  elif defined(solaris):
-    # just a guess really:
-    type thread_t {.importc: "thread_t", header: "<thread.h>".} = distinct int
-    proc thr_self(): thread_t {.importc, header: "<thread.h>".}
-
-    proc getThreadId*(): int =
-      ## get the ID of the currently running thread.
-      result = int(thr_self())
-
 const
   emulatedThreadVars = compileOption("tlsEmulation")
 
@@ -302,8 +256,9 @@ when emulatedThreadVars:
 # we preallocate a fixed size for thread local storage, so that no heap
 # allocations are needed. Currently less than 7K are used on a 64bit machine.
 # We use ``float`` for proper alignment:
+const nimTlsSize {.intdefine.} = 8000
 type
-  ThreadLocalStorage = array[0..1_000, float]
+  ThreadLocalStorage = array[0..(nimTlsSize div sizeof(float)), float]
 
   PGcThread = ptr GcThread
   GcThread {.pure, inheritable.} = object
@@ -369,7 +324,11 @@ when not defined(useNimRtl):
 
   when emulatedThreadVars:
     if nimThreadVarsSize() > sizeof(ThreadLocalStorage):
-      echo "too large thread local storage size requested"
+      echo "too large thread local storage size requested ",
+           "(", nimThreadVarsSize(), "/", sizeof(ThreadLocalStorage), "). ",
+           "Use -d:\"nimTlsSize=", nimThreadVarsSize(),
+           "\" to preallocate sufficient storage."
+
       quit 1
 
   when hasSharedHeap and not defined(boehmgc) and not defined(gogc) and not defined(nogc):
@@ -437,7 +396,7 @@ template afterThreadRuns() =
   for i in countdown(threadDestructionHandlers.len-1, 0):
     threadDestructionHandlers[i]()
 
-when not defined(boehmgc) and not hasSharedHeap and not defined(gogc) and not defined(gcstack):
+when not defined(boehmgc) and not hasSharedHeap and not defined(gogc) and not defined(gcRegions):
   proc deallocOsPages()
 
 when defined(boehmgc):
@@ -475,7 +434,7 @@ else:
 proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
   when defined(boehmgc):
     boehmGC_call_with_stack_base(threadProcWrapDispatch[TArg], thrd)
-  elif not defined(nogc) and not defined(gogc) and not defined(gcstack):
+  elif not defined(nogc) and not defined(gogc) and not defined(gcRegions):
     var p {.volatile.}: proc(a: ptr Thread[TArg]) {.nimcall.} =
       threadProcWrapDispatch[TArg]
     when not hasSharedHeap:
@@ -493,7 +452,7 @@ proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
   else:
     threadProcWrapDispatch(thrd)
 
-template threadProcWrapperBody(closure: expr) {.immediate.} =
+template threadProcWrapperBody(closure: untyped): untyped =
   var thrd = cast[ptr Thread[TArg]](closure)
   var core = thrd.core
   when declared(globalsSlot): threadVarSetValue(globalsSlot, thrd.core)
@@ -665,3 +624,82 @@ when useStackMaskHack:
     var mainThread: Thread[pointer]
     createThread(mainThread, tp)
     joinThread(mainThread)
+
+## we need to cache current threadId to not perform syscall all the time
+var threadId {.threadvar.}: int
+
+when defined(windows):
+  proc getThreadId*(): int =
+    ## get the ID of the currently running thread.
+    if threadId == 0:
+      threadId = int(getCurrentThreadId())
+    result = threadId
+
+elif defined(linux):
+  proc syscall(arg: clong): clong {.varargs, importc: "syscall", header: "<unistd.h>".}
+  var NR_gettid {.importc: "__NR_gettid", header: "<sys/syscall.h>".}: int
+
+  proc getThreadId*(): int =
+    ## get the ID of the currently running thread.
+    if threadId == 0:
+      threadId = int(syscall(NR_gettid))
+    result = threadId
+
+elif defined(dragonfly):
+  proc lwp_gettid(): int32 {.importc, header: "unistd.h".}
+
+  proc getThreadId*(): int =
+    ## get the ID of the currently running thread.
+    if threadId == 0:
+      threadId = int(lwp_gettid())
+    result = threadId
+
+elif defined(openbsd):
+  proc getthrid(): int32 {.importc: "getthrid", header: "<unistd.h>".}
+
+  proc getThreadId*(): int =
+    ## get the ID of the currently running thread.
+    if threadId == 0:
+      threadId = int(getthrid())
+    result = threadId
+
+elif defined(netbsd):
+  proc lwp_self(): int32 {.importc: "_lwp_self", header: "<lwp.h>".}
+
+  proc getThreadId*(): int =
+    ## get the ID of the currently running thread.
+    if threadId == 0:
+      threadId = int(lwp_self())
+    result = threadId
+
+elif defined(freebsd):
+  proc syscall(arg: cint, arg0: ptr cint): cint {.varargs, importc: "syscall", header: "<unistd.h>".}
+  var SYS_thr_self {.importc:"SYS_thr_self", header:"<sys/syscall.h>"}: cint
+
+  proc getThreadId*(): int =
+    ## get the ID of the currently running thread.
+    var tid = 0.cint
+    if threadId == 0:
+      discard syscall(SYS_thr_self, addr tid)
+      threadId = tid
+    result = threadId
+
+elif defined(macosx):
+  proc syscall(arg: cint): cint {.varargs, importc: "syscall", header: "<unistd.h>".}
+  var SYS_thread_selfid {.importc:"SYS_thread_selfid", header:"<sys/syscall.h>".}: cint
+
+  proc getThreadId*(): int =
+    ## get the ID of the currently running thread.
+    if threadId == 0:
+      threadId = int(syscall(SYS_thread_selfid))
+    result = threadId
+
+elif defined(solaris):
+  type thread_t {.importc: "thread_t", header: "<thread.h>".} = distinct int
+  proc thr_self(): thread_t {.importc, header: "<thread.h>".}
+
+  proc getThreadId*(): int =
+    ## get the ID of the currently running thread.
+    if threadId == 0:
+      threadId = int(thr_self())
+    result = threadId