diff --git a/lib/system/gc.nim b/lib/system/gc.nim index fe4b409035..e0db3fba43 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -292,6 +292,20 @@ proc initGC() = when useMarkForDebug or useBackupGc: init(gch.marked) +var + localGcInitialized {.rtlThreadVar.}: bool + +proc setupForeignThreadGc*() = + ## 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 + ## this thread will only be initialized once per thread, no matter how often + ## it is called. + if not localGcInitialized: + localGcInitialized = true + var stackTop {.volatile.}: pointer + setStackBottom(addr(stackTop)) + initGC() + when useMarkForDebug or useBackupGc: type TGlobalMarkerProc = proc () {.nimcall, benign.} diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index 242ca16084..0eafd3255d 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -168,6 +168,20 @@ proc initGC() = Init(gch.allocated) init(gch.marked) +var + localGcInitialized {.rtlThreadVar.}: bool + +proc setupForeignThreadGc*() = + ## 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 + ## this thread will only be initialized once per thread, no matter how often + ## it is called. + if not localGcInitialized: + localGcInitialized = true + var stackTop {.volatile.}: pointer + setStackBottom(addr(stackTop)) + initGC() + proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.benign.} = var d = cast[ByteAddress](dest) case n.kind