looponce() called nothing due when waiting for the sockets failed,
returning at once: a caller waiting for a timer turned forever. What is
due is called all the same, and on Windows WSAEINTR is no failure, not
errno. looptest reports any failure to wait with its error; fibertest
starts Winsock, its loop could not be made without, and recurses into
half of a fiber's stack rather than most of it, which Windows takes
more of. The units case shows what a test which never finished wrote.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
src/fiber.c, not used yet: a fiber runs a function on a stack of its
own, yielding back to the thread which resumed it, for a thread to
serve many clients with code written as if each had a thread.
The switch is our own on x86-64 (System V), aarch64, i386, arm (ARM or
Thumb code, with or without a floating point unit) and mips o32 (with
soft, 32 or 64 bit floating point registers, position independent or
not), Windows' fibers on Windows. It saves the registers a function
has to keep and swaps the stack. Elsewhere there are no fibers
(WITH_FIBERS is not defined), nor where x86-64 Linux checks returns
against a shadow stack, which fiberusable() tells: each client has a
thread there.
Stacks are mapped with a guard page below them. A fiber whose function
returned is started again with another, its stack kept. Switches are
annotated for AddressSanitizer.
tests/fibertest.c tests them: yielding and resuming, the integer and
floating point registers a function keeps across switches both ways, a
thousand fibers resumed at random each keeping its stack, recursion
deep in a stack, fibers sleeping on the event loop's timers. The units
case, which was the loop case, runs it with looptest.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>