Re: SBCL Fibers proposal

Anthony Green <[email protected]> Sun, 1 Mar 2026 13:27:59 -0500
Newsgroups gmane.lisp.steel-bank.devel
Message-ID <CACxje59Z0G8+uZVhAFCeNi19Qz2drUbFQH-cePbfbFRcXJ-kUg@mail.gmail.com>
Thank you for the review!

On Sun, Mar 1, 2026 at 9:56 AM Michał "phoe" Herda <[email protected]> wrote:

> When it returns normally, the return value becomes the fiber’s result
> (retrievable via fiber-result). If it signals an unhandled error, the
> condition object becomes the result instead.
>
> This means that a fiber can't return a condition instance without causing
> confusion (not all conditions are errors, yadda yadda). Can FIBER-RESULT
> return two values, similar to IGNORE-ERRORS?
>
This is a good point.  I will change this.

> Re 2.4, does it mandate calling with a function object even if I want
> something to execute 5+ seconds from now? So it would be (FIBER-PARK
> (CONSTANTLY NIL) :TIMEOUT 5)?
>
Use FIBER-SLEEP instead. FIBER-PARK is specifically for predicate-based
waiting.  I'll clarify this in the doc.


> Re 5.2, the title mentions no guard page, but the content mentions guard
> pages.
>
There used to be no guard page, but then I added one and updated the text,
but forgot to change the header.


> Re 5, I assume that it is impossible or nigh impossible to dynamically
> change the stack size of a process upon an overflow, BEAM-process-style -
> am I correct?
>
Yes, that's right.  Fiber stacks are fixed-size mmap allocations. Growing
them would require either relocating the stack (invalidating all interior
pointers) or discontiguous segments (requiring compiler support for
segment-crossing checks on every call). Neither is feasible in SBCL's
native-code model. Choose the right size at make-fiber time.


> Re 9.4, what are the safety mechanisms during copying?
>
The key invariant is that only the owner thread ever calls wsd-push (and
therefore wsd-grow). Thieves only touch top via CAS.  They never write to
the buffer or modify bottom. During growth, the owner allocates a new
power-of-two array, copies all live entries from [top, bottom) using
circular index masking, and publishes the new buffer via a single setf of
the buffer slot. A thief that races with this either sees the old buffer
(still valid — it contains the same elements at the same circular indices)
or the new one. Either way, the thief's CAS on top serializes the steal: if
top has moved, the CAS fails and the thief retries. The old buffer becomes
unreferenced and is collected by GC. After each push, a write barrier
ensures the stored element is visible to other threads before bottom is
incremented, preventing a thief from reading an uninitialized slot.


> Re 12.2, that is just for errors; how does this handle (possibly invalid)
> non-local returns via RETURN-FROM and GO?
>
THROW to a tag not established within the fiber signals "tag does not
exist", caught by the handler-case. RETURN-FROM and GO can't cross fiber
boundaries.  They're lexically scoped (same constraint as threads).


> Re 13: is INTERRUPT-THREAD patched in any way?
>
No. An interrupt on a carrier thread runs in whatever fiber context is
active.

I'll add some clarifying text to the document, and modify fiber-result.

Thanks again!

AG


> W dniu 2026-03-01 14:57, Anthony Green napisał(a):
>
> My fibers patches aren't ready to be submitted yet, but I've posted
> the proposal, including many details and some benchmark results here:
> https://atgreen.github.io/repl-yell/posts/sbcl-fibers/
>
> If it's easier to provide feedback on the list, I could post the entire
> text here.
>
> Thanks,
> AG
>
> _______________________________________________
> Sbcl-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/sbcl-devel
>
>
>

_______________________________________________
Sbcl-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-devel