mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-25 00:35:26 +00:00
Add `tearDownForeignThreadGc` function (#5369)
This commit is contained in:
committed by
Andreas Rumpf
parent
279e4b0451
commit
6fa1dba515
88
tests/gc/foreign_thr.nim
Normal file
88
tests/gc/foreign_thr.nim
Normal file
@@ -0,0 +1,88 @@
|
||||
discard """
|
||||
output: '''
|
||||
Hello from thread
|
||||
Hello from thread
|
||||
Hello from thread
|
||||
Hello from thread
|
||||
'''
|
||||
cmd: "nim $target --hints:on --threads:on --tlsEmulation:off $options $file"
|
||||
"""
|
||||
# Copied from stdlib
|
||||
import strutils
|
||||
|
||||
const
|
||||
StackGuardSize = 4096
|
||||
ThreadStackMask = 1024*256*sizeof(int)-1
|
||||
ThreadStackSize = ThreadStackMask+1 - StackGuardSize
|
||||
|
||||
type ThreadFunc = proc() {.thread.}
|
||||
|
||||
when defined(posix):
|
||||
import posix
|
||||
|
||||
proc runInForeignThread(f: ThreadFunc) =
|
||||
proc wrapper(p: pointer): pointer {.noconv.} =
|
||||
let thr = cast[ThreadFunc](p)
|
||||
setupForeignThreadGc()
|
||||
thr()
|
||||
tearDownForeignThreadGc()
|
||||
setupForeignThreadGc()
|
||||
thr()
|
||||
tearDownForeignThreadGc()
|
||||
result = nil
|
||||
|
||||
var attrs {.noinit.}: PthreadAttr
|
||||
doAssert pthread_attr_init(addr attrs) == 0
|
||||
doAssert pthread_attr_setstacksize(addr attrs, ThreadStackSize) == 0
|
||||
var tid: Pthread
|
||||
doAssert pthread_create(addr tid, addr attrs, wrapper, f) == 0
|
||||
doAssert pthread_join(tid, nil) == 0
|
||||
|
||||
elif defined(windows):
|
||||
import winlean
|
||||
type
|
||||
WinThreadProc = proc (x: pointer): int32 {.stdcall.}
|
||||
|
||||
proc createThread(lpThreadAttributes: pointer, dwStackSize: DWORD,
|
||||
lpStartAddress: WinThreadProc,
|
||||
lpParameter: pointer,
|
||||
dwCreationFlags: DWORD,
|
||||
lpThreadId: var DWORD): Handle {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateThread".}
|
||||
|
||||
proc wrapper(p: pointer): int32 {.stdcall.} =
|
||||
let thr = cast[ThreadFunc](p)
|
||||
setupForeignThreadGc()
|
||||
thr()
|
||||
tearDownForeignThreadGc()
|
||||
setupForeignThreadGc()
|
||||
thr()
|
||||
tearDownForeignThreadGc()
|
||||
result = 0'i32
|
||||
|
||||
proc runInForeignThread(f: ThreadFunc) =
|
||||
var dummyThreadId: DWORD
|
||||
var h = createThread(nil, ThreadStackSize.int32, wrapper.WinThreadProc, cast[pointer](f), 0, dummyThreadId)
|
||||
doAssert h != 0.Handle
|
||||
doAssert waitForSingleObject(h, -1'i32) == 0.DWORD
|
||||
|
||||
else:
|
||||
{.fatal: "Unknown system".}
|
||||
|
||||
proc runInNativeThread(f: ThreadFunc) =
|
||||
proc wrapper(f: ThreadFunc) {.thread.} =
|
||||
# These operations must be NOP
|
||||
setupForeignThreadGc()
|
||||
tearDownForeignThreadGc()
|
||||
f()
|
||||
f()
|
||||
var thr: Thread[ThreadFunc]
|
||||
createThread(thr, wrapper, f)
|
||||
joinThread(thr)
|
||||
|
||||
proc f {.thread.} =
|
||||
var msg = "Hello " & "from thread"
|
||||
echo msg
|
||||
|
||||
runInForeignThread(f)
|
||||
runInNativeThread(f)
|
||||
@@ -147,6 +147,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) =
|
||||
testSpec r, makeTest("tests/gc" / filename, options &
|
||||
" -d:release --gc:boehm", cat, actionRun)
|
||||
|
||||
testWithoutBoehm "foreign_thr"
|
||||
test "gcemscripten"
|
||||
test "growobjcrash"
|
||||
test "gcbench"
|
||||
|
||||
Reference in New Issue
Block a user