summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/system.nim8
-rw-r--r--lib/system/channels.nim2
-rw-r--r--lib/system/threadlocalstorage.nim233
-rw-r--r--lib/system/threads.nim344
4 files changed, 258 insertions, 329 deletions
diff --git a/lib/system.nim b/lib/system.nim
index c0efc40a3..9d0871490 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -3481,6 +3481,10 @@ when not defined(JS): #and not defined(nimscript):
     when defined(endb):
       proc endbStep()
 
+  when hasThreadSupport and hostOS != "standalone":
+    const insideRLocksModule = false
+    include "system/syslocks"
+    include "system/threadlocalstorage"
 
   when defined(gcDestructors) and not defined(nimscript):
     include "core/strs"
@@ -3545,8 +3549,6 @@ when not defined(JS): #and not defined(nimscript):
   when declared(initAllocator):
     initAllocator()
   when hasThreadSupport:
-    const insideRLocksModule = false
-    include "system/syslocks"
     when hostOS != "standalone": include "system/threads"
   elif not defined(nogc) and not defined(nimscript):
     when not defined(useNimRtl) and not defined(createNimRtl): initStackBottom()
@@ -3632,7 +3634,7 @@ when not defined(JS): #and not defined(nimscript):
     when hasAlloc: include "system/strmantle"
 
     when hasThreadSupport:
-      when hostOS != "standalone": include "system/channels"
+      when hostOS != "standalone" and not defined(gcDestructors): include "system/channels"
 
   when not defined(nimscript) and hasAlloc:
     when not defined(gcDestructors):
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index 27293c2d4..27393a9c6 100644
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -21,7 +21,7 @@
 ## **Note:** Channels cannot be passed between threads. Use globals or pass
 ## them by `ptr`.
 
-when not declared(NimString):
+when not declared(ThisIsSystem):
   {.error: "You must not import this module explicitly".}
 
 type
diff --git a/lib/system/threadlocalstorage.nim b/lib/system/threadlocalstorage.nim
new file mode 100644
index 000000000..eeef0ccf8
--- /dev/null
+++ b/lib/system/threadlocalstorage.nim
@@ -0,0 +1,233 @@
+
+when defined(windows):
+  type
+    SysThread* = Handle
+    WinThreadProc = proc (x: pointer): int32 {.stdcall.}
+
+  proc createThread(lpThreadAttributes: pointer, dwStackSize: int32,
+                     lpStartAddress: WinThreadProc,
+                     lpParameter: pointer,
+                     dwCreationFlags: int32,
+                     lpThreadId: var int32): SysThread {.
+    stdcall, dynlib: "kernel32", importc: "CreateThread".}
+
+  proc winSuspendThread(hThread: SysThread): int32 {.
+    stdcall, dynlib: "kernel32", importc: "SuspendThread".}
+
+  proc winResumeThread(hThread: SysThread): int32 {.
+    stdcall, dynlib: "kernel32", importc: "ResumeThread".}
+
+  proc waitForMultipleObjects(nCount: int32,
+                              lpHandles: ptr SysThread,
+                              bWaitAll: int32,
+                              dwMilliseconds: int32): int32 {.
+    stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
+
+  proc terminateThread(hThread: SysThread, dwExitCode: int32): int32 {.
+    stdcall, dynlib: "kernel32", importc: "TerminateThread".}
+
+  proc getCurrentThreadId(): int32 {.
+    stdcall, dynlib: "kernel32", importc: "GetCurrentThreadId".}
+
+  type
+    ThreadVarSlot = distinct int32
+
+  when true:
+    proc threadVarAlloc(): ThreadVarSlot {.
+      importc: "TlsAlloc", stdcall, header: "<windows.h>".}
+    proc threadVarSetValue(dwTlsIndex: ThreadVarSlot, lpTlsValue: pointer) {.
+      importc: "TlsSetValue", stdcall, header: "<windows.h>".}
+    proc tlsGetValue(dwTlsIndex: ThreadVarSlot): pointer {.
+      importc: "TlsGetValue", stdcall, header: "<windows.h>".}
+
+    proc getLastError(): uint32 {.
+      importc: "GetLastError", stdcall, header: "<windows.h>".}
+    proc setLastError(x: uint32) {.
+      importc: "SetLastError", stdcall, header: "<windows.h>".}
+
+    proc threadVarGetValue(dwTlsIndex: ThreadVarSlot): pointer =
+      let realLastError = getLastError()
+      result = tlsGetValue(dwTlsIndex)
+      setLastError(realLastError)
+  else:
+    proc threadVarAlloc(): ThreadVarSlot {.
+      importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
+    proc threadVarSetValue(dwTlsIndex: ThreadVarSlot, lpTlsValue: pointer) {.
+      importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
+    proc threadVarGetValue(dwTlsIndex: ThreadVarSlot): pointer {.
+      importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
+
+  proc setThreadAffinityMask(hThread: SysThread, dwThreadAffinityMask: uint) {.
+    importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
+
+elif defined(genode):
+  import genode/env
+  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,
+                  env: GenodeEnv,
+                  stackSize: culonglong,
+                  entry: GenodeThreadProc,
+                  arg: pointer,
+                  affinity: cuint) {.
+    importcpp: "#.initThread(@)".}
+
+  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) or defined(haiku)):
+    {.passL: "-pthread".}
+
+  when not defined(haiku):
+    {.passC: "-pthread".}
+
+  const
+    schedh = "#define _GNU_SOURCE\n#include <sched.h>"
+    pthreadh = "#define _GNU_SOURCE\n#include <pthread.h>"
+
+  when not declared(Time):
+    when defined(linux):
+      type Time = clong
+    else:
+      type Time = int
+
+  when (defined(linux) or defined(nintendoswitch)) and defined(amd64):
+    type
+      SysThread* {.importc: "pthread_t",
+                  header: "<sys/types.h>" .} = distinct culong
+      Pthread_attr {.importc: "pthread_attr_t",
+                    header: "<sys/types.h>".} = object
+        abi: array[56 div sizeof(clong), clong]
+      ThreadVarSlot {.importc: "pthread_key_t",
+                    header: "<sys/types.h>".} = distinct cuint
+  else:
+    type
+      SysThread* {.importc: "pthread_t", header: "<sys/types.h>".} = object
+      Pthread_attr {.importc: "pthread_attr_t",
+                       header: "<sys/types.h>".} = object
+      ThreadVarSlot {.importc: "pthread_key_t",
+                     header: "<sys/types.h>".} = object
+  type
+    Timespec {.importc: "struct timespec", header: "<time.h>".} = object
+      tv_sec: Time
+      tv_nsec: clong
+
+  proc pthread_attr_init(a1: var PthreadAttr) {.
+    importc, header: pthreadh.}
+  proc pthread_attr_setstacksize(a1: var PthreadAttr, a2: int) {.
+    importc, header: pthreadh.}
+
+  proc pthread_create(a1: var SysThread, a2: var PthreadAttr,
+            a3: proc (x: pointer): pointer {.noconv.},
+            a4: pointer): cint {.importc: "pthread_create",
+            header: pthreadh.}
+  proc pthread_join(a1: SysThread, a2: ptr pointer): cint {.
+    importc, header: pthreadh.}
+
+  proc pthread_cancel(a1: SysThread): cint {.
+    importc: "pthread_cancel", header: pthreadh.}
+
+  proc pthread_getspecific(a1: ThreadVarSlot): pointer {.
+    importc: "pthread_getspecific", header: pthreadh.}
+  proc pthread_key_create(a1: ptr ThreadVarSlot,
+                          destruct: proc (x: pointer) {.noconv.}): int32 {.
+    importc: "pthread_key_create", header: pthreadh.}
+  proc pthread_key_delete(a1: ThreadVarSlot): int32 {.
+    importc: "pthread_key_delete", header: pthreadh.}
+
+  proc pthread_setspecific(a1: ThreadVarSlot, a2: pointer): int32 {.
+    importc: "pthread_setspecific", header: pthreadh.}
+
+  proc threadVarAlloc(): ThreadVarSlot {.inline.} =
+    discard pthread_key_create(addr(result), nil)
+  proc threadVarSetValue(s: ThreadVarSlot, value: pointer) {.inline.} =
+    discard pthread_setspecific(s, value)
+  proc threadVarGetValue(s: ThreadVarSlot): pointer {.inline.} =
+    result = pthread_getspecific(s)
+
+  type CpuSet {.importc: "cpu_set_t", header: schedh.} = object
+     when defined(linux) and defined(amd64):
+       abi: array[1024 div (8 * sizeof(culong)), culong]
+
+  proc cpusetZero(s: var CpuSet) {.importc: "CPU_ZERO", header: schedh.}
+  proc cpusetIncl(cpu: cint; s: var CpuSet) {.
+    importc: "CPU_SET", header: schedh.}
+
+  proc setAffinity(thread: SysThread; setsize: csize; s: var CpuSet) {.
+    importc: "pthread_setaffinity_np", header: pthreadh.}
+
+
+const
+  emulatedThreadVars = compileOption("tlsEmulation")
+
+when emulatedThreadVars:
+  # the compiler generates this proc for us, so that we can get the size of
+  # the thread local var block; we use this only for sanity checking though
+  proc nimThreadVarsSize(): int {.noconv, importc: "NimThreadVarsSize".}
+
+# we preallocate a fixed size for thread local storage, so that no heap
+# allocations are needed. Currently less than 16K are used on a 64bit machine.
+# We use ``float`` for proper alignment:
+const nimTlsSize {.intdefine.} = 16000
+type
+  ThreadLocalStorage = array[0..(nimTlsSize div sizeof(float)), float]
+  PGcThread = ptr GcThread
+  GcThread {.pure, inheritable.} = object
+    when emulatedThreadVars:
+      tls: ThreadLocalStorage
+    else:
+      nil
+
+when emulatedThreadVars:
+  var globalsSlot: ThreadVarSlot
+
+  when not defined(useNimRtl):
+    var mainThread: GcThread
+
+  proc GetThreadLocalVars(): pointer {.compilerRtl, inl.} =
+    result = addr(cast[PGcThread](threadVarGetValue(globalsSlot)).tls)
+
+  proc initThreadVarsEmulation() {.compilerProc, inline.} =
+    when not defined(useNimRtl):
+      globalsSlot = threadVarAlloc()
+      when declared(mainThread):
+        threadVarSetValue(globalsSlot, addr(mainThread))
+
+when not defined(useNimRtl):
+  when emulatedThreadVars:
+    if nimThreadVarsSize() > sizeof(ThreadLocalStorage):
+      c_fprintf(cstderr, """too large thread local storage size requested,
+use -d:\"nimTlsSize=X\" to setup even more or stop using unittest.nim""")
+      quit 1
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index ec22a2b12..18ceb900b 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -41,12 +41,10 @@
 ##    createThread(thr[i], threadFunc, (i*10, i*10+5))
 ##  joinThreads(thr)
 
-when not declared(NimString):
+when not declared(ThisIsSystem):
   {.error: "You must not import this module explicitly".}
 
 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 =
     when defined(genode):
@@ -55,312 +53,24 @@ const
       1024*256*sizeof(int)-1
   ThreadStackSize = ThreadStackMask+1 - StackGuardSize
 
-when defined(windows):
-  type
-    SysThread* = Handle
-    WinThreadProc = proc (x: pointer): int32 {.stdcall.}
-
-  proc createThread(lpThreadAttributes: pointer, dwStackSize: int32,
-                     lpStartAddress: WinThreadProc,
-                     lpParameter: pointer,
-                     dwCreationFlags: int32,
-                     lpThreadId: var int32): SysThread {.
-    stdcall, dynlib: "kernel32", importc: "CreateThread".}
-
-  proc winSuspendThread(hThread: SysThread): int32 {.
-    stdcall, dynlib: "kernel32", importc: "SuspendThread".}
-
-  proc winResumeThread(hThread: SysThread): int32 {.
-    stdcall, dynlib: "kernel32", importc: "ResumeThread".}
-
-  proc waitForMultipleObjects(nCount: int32,
-                              lpHandles: ptr SysThread,
-                              bWaitAll: int32,
-                              dwMilliseconds: int32): int32 {.
-    stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
-
-  proc terminateThread(hThread: SysThread, dwExitCode: int32): int32 {.
-    stdcall, dynlib: "kernel32", importc: "TerminateThread".}
-
-  proc getCurrentThreadId(): int32 {.
-    stdcall, dynlib: "kernel32", importc: "GetCurrentThreadId".}
-
-  type
-    ThreadVarSlot = distinct int32
-
-  when true:
-    proc threadVarAlloc(): ThreadVarSlot {.
-      importc: "TlsAlloc", stdcall, header: "<windows.h>".}
-    proc threadVarSetValue(dwTlsIndex: ThreadVarSlot, lpTlsValue: pointer) {.
-      importc: "TlsSetValue", stdcall, header: "<windows.h>".}
-    proc tlsGetValue(dwTlsIndex: ThreadVarSlot): pointer {.
-      importc: "TlsGetValue", stdcall, header: "<windows.h>".}
-
-    proc getLastError(): uint32 {.
-      importc: "GetLastError", stdcall, header: "<windows.h>".}
-    proc setLastError(x: uint32) {.
-      importc: "SetLastError", stdcall, header: "<windows.h>".}
-
-    proc threadVarGetValue(dwTlsIndex: ThreadVarSlot): pointer =
-      let realLastError = getLastError()
-      result = tlsGetValue(dwTlsIndex)
-      setLastError(realLastError)
-  else:
-    proc threadVarAlloc(): ThreadVarSlot {.
-      importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
-    proc threadVarSetValue(dwTlsIndex: ThreadVarSlot, lpTlsValue: pointer) {.
-      importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
-    proc threadVarGetValue(dwTlsIndex: ThreadVarSlot): pointer {.
-      importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
-
-  proc setThreadAffinityMask(hThread: SysThread, dwThreadAffinityMask: uint) {.
-    importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
-
-elif defined(genode):
-  import genode/env
-  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,
-                  env: GenodeEnv,
-                  stackSize: culonglong,
-                  entry: GenodeThreadProc,
-                  arg: pointer,
-                  affinity: cuint) {.
-    importcpp: "#.initThread(@)".}
-
-  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) or defined(haiku)):
-    {.passL: "-pthread".}
-
-  when not defined(haiku):
-    {.passC: "-pthread".}
-
-  const
-    schedh = "#define _GNU_SOURCE\n#include <sched.h>"
-    pthreadh = "#define _GNU_SOURCE\n#include <pthread.h>"
-
-  when not declared(Time):
-    when defined(linux):
-      type Time = clong
-    else:
-      type Time = int
-
-  when (defined(linux) or defined(nintendoswitch)) and defined(amd64):
-    type
-      SysThread* {.importc: "pthread_t",
-                  header: "<sys/types.h>" .} = distinct culong
-      Pthread_attr {.importc: "pthread_attr_t",
-                    header: "<sys/types.h>".} = object
-        abi: array[56 div sizeof(clong), clong]
-      ThreadVarSlot {.importc: "pthread_key_t",
-                    header: "<sys/types.h>".} = distinct cuint
-  else:
-    type
-      SysThread* {.importc: "pthread_t", header: "<sys/types.h>".} = object
-      Pthread_attr {.importc: "pthread_attr_t",
-                       header: "<sys/types.h>".} = object
-      ThreadVarSlot {.importc: "pthread_key_t",
-                     header: "<sys/types.h>".} = object
-  type
-    Timespec {.importc: "struct timespec", header: "<time.h>".} = object
-      tv_sec: Time
-      tv_nsec: clong
-
-  proc pthread_attr_init(a1: var PthreadAttr) {.
-    importc, header: pthreadh.}
-  proc pthread_attr_setstacksize(a1: var PthreadAttr, a2: int) {.
-    importc, header: pthreadh.}
-
-  proc pthread_create(a1: var SysThread, a2: var PthreadAttr,
-            a3: proc (x: pointer): pointer {.noconv.},
-            a4: pointer): cint {.importc: "pthread_create",
-            header: pthreadh.}
-  proc pthread_join(a1: SysThread, a2: ptr pointer): cint {.
-    importc, header: pthreadh.}
-
-  proc pthread_cancel(a1: SysThread): cint {.
-    importc: "pthread_cancel", header: pthreadh.}
-
-  proc pthread_getspecific(a1: ThreadVarSlot): pointer {.
-    importc: "pthread_getspecific", header: pthreadh.}
-  proc pthread_key_create(a1: ptr ThreadVarSlot,
-                          destruct: proc (x: pointer) {.noconv.}): int32 {.
-    importc: "pthread_key_create", header: pthreadh.}
-  proc pthread_key_delete(a1: ThreadVarSlot): int32 {.
-    importc: "pthread_key_delete", header: pthreadh.}
-
-  proc pthread_setspecific(a1: ThreadVarSlot, a2: pointer): int32 {.
-    importc: "pthread_setspecific", header: pthreadh.}
-
-  proc threadVarAlloc(): ThreadVarSlot {.inline.} =
-    discard pthread_key_create(addr(result), nil)
-  proc threadVarSetValue(s: ThreadVarSlot, value: pointer) {.inline.} =
-    discard pthread_setspecific(s, value)
-  proc threadVarGetValue(s: ThreadVarSlot): pointer {.inline.} =
-    result = pthread_getspecific(s)
-
-  when useStackMaskHack:
-    proc pthread_attr_setstack(attr: var PthreadAttr, stackaddr: pointer,
-                               size: int): cint {.
-      importc: "pthread_attr_setstack", header: pthreadh.}
-
-  type CpuSet {.importc: "cpu_set_t", header: schedh.} = object
-     when defined(linux) and defined(amd64):
-       abi: array[1024 div (8 * sizeof(culong)), culong]
-
-  proc cpusetZero(s: var CpuSet) {.importc: "CPU_ZERO", header: schedh.}
-  proc cpusetIncl(cpu: cint; s: var CpuSet) {.
-    importc: "CPU_SET", header: schedh.}
-
-  proc setAffinity(thread: SysThread; setsize: csize; s: var CpuSet) {.
-    importc: "pthread_setaffinity_np", header: pthreadh.}
-
-const
-  emulatedThreadVars = compileOption("tlsEmulation")
-
-when emulatedThreadVars:
-  # the compiler generates this proc for us, so that we can get the size of
-  # the thread local var block; we use this only for sanity checking though
-  proc nimThreadVarsSize(): int {.noconv, importc: "NimThreadVarsSize".}
-
-# we preallocate a fixed size for thread local storage, so that no heap
-# allocations are needed. Currently less than 16K are used on a 64bit machine.
-# We use ``float`` for proper alignment:
-const nimTlsSize {.intdefine.} = 16000
-type
-  ThreadLocalStorage = array[0..(nimTlsSize div sizeof(float)), float]
-
-  PGcThread = ptr GcThread
-  GcThread {.pure, inheritable.} = object
-    when emulatedThreadVars and not useStackMaskHack:
-      tls: ThreadLocalStorage
-    else:
-      nil
-    when hasSharedHeap:
-      next, prev: PGcThread
-      stackBottom, stackTop: pointer
-      stackSize: int
-    else:
-      nil
-
-when not defined(useNimRtl):
-  when not useStackMaskHack:
-    var mainThread: GcThread
-
 #const globalsSlot = ThreadVarSlot(0)
 #sysAssert checkSlot.int == globalsSlot.int
 
-when emulatedThreadVars:
-  # XXX it'd be more efficient to not use a global variable for the
-  # thread storage slot, but to rely on the implementation to assign slot X
-  # for us... ;-)
-  var globalsSlot: ThreadVarSlot
-
-  proc GetThreadLocalVars(): pointer {.compilerRtl, inl.} =
-    result = addr(cast[PGcThread](threadVarGetValue(globalsSlot)).tls)
-
-  proc initThreadVarsEmulation() {.compilerProc, inline.} =
-    when not defined(useNimRtl):
-      globalsSlot = threadVarAlloc()
-      when declared(mainThread):
-        threadVarSetValue(globalsSlot, addr(mainThread))
-
-when useStackMaskHack:
-  proc maskStackPointer(offset: int): pointer {.compilerRtl, inl.} =
-    var x {.volatile.}: pointer
-    x = addr(x)
-    result = cast[pointer]((cast[int](x) and not ThreadStackMask) +%
-      (0) +% offset)
-
 # create for the main thread. Note: do not insert this data into the list
 # of all threads; it's not to be stopped etc.
 when not defined(useNimRtl):
-  when not useStackMaskHack:
-    #when not defined(createNimRtl): initStackBottom()
-    when declared(initGC):
-      initGC()
-      when not emulatedThreadVars:
-        type ThreadType {.pure.} = enum
-          None = 0,
-          NimThread = 1,
-          ForeignThread = 2
-        var
-          threadType {.rtlThreadVar.}: ThreadType
-
-        threadType = ThreadType.NimThread
-
-
-
-  when emulatedThreadVars:
-    if nimThreadVarsSize() > sizeof(ThreadLocalStorage):
-      c_fprintf(cstderr, """too large thread local storage size requested,
-use -d:\"nimTlsSize=X\" to setup even more or stop using unittest.nim""")
-      quit 1
-
-  when hasSharedHeap and not defined(boehmgc) and not defined(gogc) and not defined(nogc):
-    var
-      threadList: PGcThread
-
-    proc registerThread(t: PGcThread) =
-      # we need to use the GC global lock here!
-      acquireSys(HeapLock)
-      t.prev = nil
-      t.next = threadList
-      if threadList != nil:
-        sysAssert(threadList.prev == nil, "threadList.prev == nil")
-        threadList.prev = t
-      threadList = t
-      releaseSys(HeapLock)
-
-    proc unregisterThread(t: PGcThread) =
-      # we need to use the GC global lock here!
-      acquireSys(HeapLock)
-      if t == threadList: threadList = t.next
-      if t.next != nil: t.next.prev = t.prev
-      if t.prev != nil: t.prev.next = t.next
-      # so that a thread can be unregistered twice which might happen if the
-      # code executes `destroyThread`:
-      t.next = nil
-      t.prev = nil
-      releaseSys(HeapLock)
-
-    # on UNIX, the GC uses ``SIGFREEZE`` to tell every thread to stop so that
-    # the GC can examine the stacks?
-    proc stopTheWord() = discard
+  #when not defined(createNimRtl): initStackBottom()
+  when declared(initGC):
+    initGC()
+    when not emulatedThreadVars:
+      type ThreadType {.pure.} = enum
+        None = 0,
+        NimThread = 1,
+        ForeignThread = 2
+      var
+        threadType {.rtlThreadVar.}: ThreadType
+
+      threadType = ThreadType.NimThread
 
 # We jump through some hops here to ensure that Nim thread procs can have
 # the Nim calling convention. This is needed because thread procs are
@@ -434,20 +144,15 @@ 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(gcRegions):
+  elif not defined(nogc) and not defined(gogc) and not defined(gcRegions) and not defined(gcDestructors):
     var p {.volatile.}: proc(a: ptr Thread[TArg]) {.nimcall.} =
       threadProcWrapDispatch[TArg]
-    when not hasSharedHeap:
-      # init the GC for refc/markandsweep
-      nimGC_setStackBottom(addr(p))
-      initGC()
-      when declared(threadType):
-        threadType = ThreadType.NimThread
-    when declared(registerThread):
-      thrd.core.stackBottom = addr(thrd)
-      registerThread(thrd.core)
+    # init the GC for refc/markandsweep
+    nimGC_setStackBottom(addr(p))
+    initGC()
+    when declared(threadType):
+      threadType = ThreadType.NimThread
     p(thrd)
-    when declared(registerThread): unregisterThread(thrd.core)
     when declared(deallocOsPages): deallocOsPages()
   else:
     threadProcWrapDispatch(thrd)
@@ -623,17 +328,6 @@ else:
 proc createThread*(t: var Thread[void], tp: proc () {.thread, nimcall.}) =
   createThread[void](t, tp)
 
-when false:
-  proc mainThreadId*[TArg](): ThreadId[TArg] =
-    ## Returns the thread ID of the main thread.
-    result = cast[ThreadId[TArg]](addr(mainThread))
-
-when useStackMaskHack:
-  proc runMain(tp: proc () {.thread.}) {.compilerproc.} =
-    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