diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/system/gc_common.nim | 29 | ||||
-rw-r--r-- | lib/system/threads.nim | 16 |
2 files changed, 35 insertions, 10 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 diff --git a/lib/system/threads.nim b/lib/system/threads.nim index e8b34bf2e..6e58638e9 100644 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -285,7 +285,19 @@ when useStackMaskHack: when not defined(useNimRtl): when not useStackMaskHack: #when not defined(createNimRtl): initStackBottom() - when declared(initGC): initGC() + 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): @@ -442,6 +454,8 @@ proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) = # init the GC for refc/markandsweep setStackBottom(addr(p)) initGC() + when declared(threadType): + threadType = ThreadType.NimThread when declared(registerThread): thrd.stackBottom = addr(thrd) registerThread(thrd) |