summary refs log tree commit diff stats
path: root/lib/system/gc_common.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system/gc_common.nim')
-rw-r--r--lib/system/gc_common.nim29
1 files changed, 20 insertions, 9 deletions
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index 269514ceb..6ab6bd920 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -128,13 +128,7 @@ iterator items(stack: ptr GcStack): ptr GcStack =
     yield s
     s = s.next
 
-# There will be problems with GC in foreign threads if `threads` option is off or TLS emulation is enabled
-const allowForeignThreadGc = compileOption("threads") and not compileOption("tlsEmulation")
-
-when allowForeignThreadGc:
-  var
-    localGcInitialized {.rtlThreadVar.}: bool
-
+when declared(threadType):
   proc setupForeignThreadGc*() {.gcsafe.} =
     ## Call this if you registered a callback that will be run from a thread not
     ## under your control. This has a cheap thread-local guard, so the GC for
@@ -143,16 +137,33 @@ when allowForeignThreadGc:
     ##
     ## This function is available only when ``--threads:on`` and ``--tlsEmulation:off``
     ## switches are used
-    if not localGcInitialized:
-      localGcInitialized = true
+    if threadType == ThreadType.None:
       initAllocator()
       var stackTop {.volatile.}: pointer
       setStackBottom(addr(stackTop))
       initGC()
+      threadType = ThreadType.ForeignThread
+
+  proc tearDownForeignThreadGc*() {.gcsafe.} =
+    ## Call this to tear down the GC, previously initialized by ``setupForeignThreadGc``.
+    ## If GC has not been previously initialized, or has already been torn down, the
+    ## call does nothing.
+    ##
+    ## This function is available only when ``--threads:on`` and ``--tlsEmulation:off``
+    ## switches are used
+    if threadType != ThreadType.ForeignThread:
+      return
+    when declared(deallocOsPages): deallocOsPages()
+    threadType = ThreadType.None
+    when declared(gch): zeroMem(addr gch, sizeof(gch))
+
 else:
   template setupForeignThreadGc*() =
     {.error: "setupForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
 
+  template tearDownForeignThreadGc*() =
+    {.error: "tearDownForeignThreadGc is available only when ``--threads:on`` and ``--tlsEmulation:off`` are used".}
+
 # ----------------- stack management --------------------------------------
 #  inspired from Smart Eiffel