mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 12:07:51 +00:00
Co-authored-by: drswinghead <drswinghead@gmail.com> Co-authored-by: Clyybber <darkmine956@gmail.com>
This commit is contained in:
@@ -36,6 +36,7 @@ const defaultStackSize = 512 * 1024
|
||||
proc GC_addStack(bottom: pointer) {.cdecl, importc.}
|
||||
proc GC_removeStack(bottom: pointer) {.cdecl, importc.}
|
||||
proc GC_setActiveStack(bottom: pointer) {.cdecl, importc.}
|
||||
proc GC_getActiveStack() : pointer {.cdecl, importc.}
|
||||
|
||||
const
|
||||
CORO_BACKEND_UCONTEXT = 0
|
||||
@@ -166,6 +167,7 @@ type
|
||||
coroutines: DoublyLinkedList[CoroutinePtr]
|
||||
current: DoublyLinkedNode[CoroutinePtr]
|
||||
loop: Coroutine
|
||||
ncbottom: pointer # non coroutine stack botttom
|
||||
|
||||
var ctx {.threadvar.}: CoroutineLoopContext
|
||||
|
||||
@@ -183,6 +185,7 @@ proc initialize() =
|
||||
ctx.coroutines = initDoublyLinkedList[CoroutinePtr]()
|
||||
ctx.loop = Coroutine()
|
||||
ctx.loop.state = CORO_EXECUTING
|
||||
ctx.ncbottom = GC_getActiveStack()
|
||||
when coroBackend == CORO_BACKEND_FIBERS:
|
||||
ctx.loop.execContext = ConvertThreadToFiberEx(nil, FIBER_FLAG_FLOAT_SWITCH)
|
||||
|
||||
@@ -193,6 +196,7 @@ proc switchTo(current, to: CoroutinePtr) =
|
||||
to.lastRun = getTicks()
|
||||
# Update position of current stack so gc invoked from another stack knows how much to scan.
|
||||
GC_setActiveStack(current.stack.bottom)
|
||||
nimGC_setStackBottom(current.stack.bottom)
|
||||
var frame = getFrameState()
|
||||
block:
|
||||
# Execution will switch to another fiber now. We do not need to update current stack
|
||||
@@ -215,12 +219,14 @@ proc switchTo(current, to: CoroutinePtr) =
|
||||
# Execution was just resumed. Restore frame information and set active stack.
|
||||
setFrameState(frame)
|
||||
GC_setActiveStack(current.stack.bottom)
|
||||
nimGC_setStackBottom(ctx.ncbottom)
|
||||
|
||||
proc suspend*(sleepTime: float = 0) =
|
||||
## Stops coroutine execution and resumes no sooner than after ``sleeptime`` seconds.
|
||||
## Until then other coroutines are executed.
|
||||
var current = getCurrent()
|
||||
current.sleepTime = sleepTime
|
||||
nimGC_setStackBottom(ctx.ncbottom)
|
||||
switchTo(current, addr(ctx.loop))
|
||||
|
||||
proc runCurrentTask() =
|
||||
@@ -230,6 +236,7 @@ proc runCurrentTask() =
|
||||
block:
|
||||
var current = getCurrent()
|
||||
current.stack.bottom = sp
|
||||
nimGC_setStackBottom(current.stack.bottom)
|
||||
# Execution of new fiber just started. Since it was entered not through `switchTo` we
|
||||
# have to set active stack here as well. GC_removeStack() has to be called in main loop
|
||||
# because we still need stack available in final suspend(0) call from which we will not
|
||||
@@ -244,6 +251,7 @@ proc runCurrentTask() =
|
||||
echo "Unhandled exception in coroutine."
|
||||
writeStackTrace()
|
||||
current.state = CORO_FINISHED
|
||||
nimGC_setStackBottom(ctx.ncbottom)
|
||||
suspend(0) # Exit coroutine without returning from coroExecWithStack()
|
||||
doAssert false
|
||||
|
||||
|
||||
@@ -273,6 +273,9 @@ when nimCoroutines:
|
||||
gch.activeStack = gch.stack.find(bottom)
|
||||
gch.activeStack.setPosition(addr(sp))
|
||||
|
||||
proc GC_getActiveStack() : pointer {.cdecl, exportc.} =
|
||||
return gch.activeStack.bottom
|
||||
|
||||
when not defined(useNimRtl):
|
||||
proc nimGC_setStackBottom(theStackBottom: pointer) =
|
||||
# Initializes main stack of the thread.
|
||||
@@ -300,6 +303,9 @@ when not defined(useNimRtl):
|
||||
else:
|
||||
gch.stack.bottom = cast[pointer](max(a, b))
|
||||
|
||||
when nimCoroutines:
|
||||
if theStackBottom != nil: gch.stack.bottom = theStackBottom
|
||||
|
||||
gch.stack.setPosition(theStackBottom)
|
||||
{.pop.}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user