diff options
author | Anatoly Galiulin <galiulin.anatoly@gmail.com> | 2017-02-13 19:37:20 +0700 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-02-13 13:37:20 +0100 |
commit | 6fa1dba515e514ea9a4ac5850b0188fb6cf95fbf (patch) | |
tree | 83022f414ebf91f5bc144f77982439be8c6381a3 /lib/system | |
parent | 279e4b045133bad59e349520547e5220408b232e (diff) | |
download | Nim-6fa1dba515e514ea9a4ac5850b0188fb6cf95fbf.tar.gz |
Add ``tearDownForeignThreadGc`` function (#5369)
Diffstat (limited to 'lib/system')
-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) |