Add `tearDownForeignThreadGc` function (#5369)

This commit is contained in:
Anatoly Galiulin 2017-02-13 19:37:20 +07:00 • committed by Andreas Rumpf
commit 6fa1dba515
5 changed files with 132 additions and 10 deletions

View file

@ -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

View file

@ -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)