<p>Guile Scheme has had support for delimited continuations for over a decade. Much was written about it in a 2012 blog post: <a href="https://www.wingolog.org/archives/2010/02/26/guile-and-delimited-continuations" rel="noreferrer">guile and delimited continuations</a>.</p>
<p>They have a limitation: continuations that thread through the C stack cannot be resumed.</p>
<p>When a lisp expression is evaluated, a C function is called, the evaluator is called again and a continuation is then captured, the result is a continuation that threads from Scheme to C and then back to Scheme. This continuation can exit back to the prompt but cannot be resumed from there.</p>
<p><a href="https://i.sstatic.net/CHMTChrk.png" rel="noreferrer"><img src="https://i.sstatic.net/CHMTChrk.png" alt="Delimited continuation involving two stacks." /></a></p>
<p>It makes sense: continuations only capture the Scheme stack, they wouldn't know where in the foreign function to return to.</p>
<p>It's been over a decade since then. Has a solution to this problem been found? Is there a technique to make this work?</p>
<p>First thing that came to mind was <code>setjmp</code>/<code>longjmp</code>. What if it could be made to save the native stack frames in addition to the registers?</p>
<p>It appears the author had the same idea. <a href="https://www.wingolog.org/pub/qc-2012-delimited-continuations-slides.pdf" rel="noreferrer">During a presentation on the subject</a>, it was asserted that it is impossible to copy over the native C stack to the heap:</p>
<blockquote>
<p>No way to use copying of C stack to do this: C stack frames are not relocatable</p>
</blockquote>
<p>Is this really the case? Doesn't Go reallocate its stack on overflow? They copy the old stack over to the new location and fix all the pointers.</p>

<implementation><control-flow><stack><call-stack>
Delimited continuations and foreign functions
CC BY-SA 4.0
2024-12-22T07:20:12.110Z
I don't know much about Go, but from what I read, it has garbage collection and no pointer arithmetic, so conceivably the runtime knows about all extant pointers to stack objects, and actually can fix them all.  That's not the case for C, where you can create pointers, perform arithmetic on them, copy them, stash them away, store them in unrelated types, all willy-nilly with no tracking. There's no hope for the runtime to know where all of them might be.
Nate Eldredge
CC BY-SA 4.0
2024-12-22T07:29:32.687Z
Sort of the whole point of `longjmp` is that the stack contents are left untouched; we just move straight up the stack, discarding all the frames that have been created since `setjmp`, and it's up to the programmer to ensure that any remaining pointers to those objects don't get used again.  But objects in higher stack frames (local to the function which called `setjmp` and its parents) stay right where they were, and pointers to them remain valid without needing any "fixing".
Nate Eldredge
CC BY-SA 4.0
2024-12-22T17:37:29.390Z
@NateEldredge So the problem is the pointers could be invalidated when the continuation is reactivated because the stack could be placed at some other location. I wonder if there's another way. What if the language could ensure the stack is placed exactly where it was? If it doesn't overlap with the existing stack, there shouldn't be conflicts. If that would clobber the stack of the current continuation, it could be backed up too, then restored later in the exact same way. Delimited continuations make it easier by reducing the size of the stack. Am I talking nonsense? I should experiment...
Matheus Moreira
# Delimited continuations and foreign functions
Posted by: username_0 on 2024-12-22
Guile Scheme has had support for delimited continuations for over a decade. Much was written about it in a 2012 blog post: [guile and delimited continuations](https://www.wingolog.org/archives/2010/02/26/guile-and-delimited-continuations).

They have a limitation: continuations that thread through the C stack cannot be resumed.

When a lisp expression is evaluated, a C function is called, the evaluator is called again and a continuation is then captured, the result is a continuation that threads from Scheme to C and then back to Scheme. This continuation can exit back to the prompt but cannot be resumed from there.

[![Delimited continuation involving two stacks.](https://i.sstatic.net/CHMTChrk.png)](https://i.sstatic.net/CHMTChrk.png)

It makes sense: continuations only capture the Scheme stack, they wouldn't know where in the foreign function to return to.

It's been over a decade since then. Has a solution to this problem been found? Is there a technique to make this work?

First thing that came to mind was `setjmp`/`longjmp`. What if it could be made to save the native stack frames in addition to the registers?

It appears the author had the same idea. [During a presentation on the subject](https://www.wingolog.org/pub/qc-2012-delimited-continuations-slides.pdf), it was asserted that it is impossible to copy over the native C stack to the heap:

> No way to use copying of C stack to do this: C stack frames are not relocatable

Is this really the case? Doesn't Go reallocate its stack on overflow? They copy the old stack over to the new location and fix all the pointers.
**Tags:** implementation control-flow stack call-stack
> **Comments:**
> **username_1**: I don't know much about Go, but from what I read, it has garbage collection and no pointer arithmetic, so conceivably the runtime knows about all extant pointers to stack objects, and actually can fix them all.  That's not the case for C, where you can create pointers, perform arithmetic on them, copy them, stash them away, store them in unrelated types, all willy-nilly with no tracking. There's no hope for the runtime to know where all of them might be.  
> **username_1**: Sort of the whole point of `longjmp` is that the stack contents are left untouched; we just move straight up the stack, discarding all the frames that have been created since `setjmp`, and it's up to the programmer to ensure that any remaining pointers to those objects don't get used again.  But objects in higher stack frames (local to the function which called `setjmp` and its parents) stay right where they were, and pointers to them remain valid without needing any "fixing".  
> **username_0**: @NateEldredge So the problem is the pointers could be invalidated when the continuation is reactivated because the stack could be placed at some other location. I wonder if there's another way. What if the language could ensure the stack is placed exactly where it was? If it doesn't overlap with the existing stack, there shouldn't be conflicts. If that would clobber the stack of the current continuation, it could be backed up too, then restored later in the exact same way. Delimited continuations make it easier by reducing the size of the stack. Am I talking nonsense? I should experiment...  
---
## 0 answers
