On 2020-03-10 22:24, Florian Weimer wrote:
> * David Brown:
>
>> I am not familiar with Scheme, and while I have used functional
>> programming languages, I have never translated them to C. Are you
>> talking about something like lazy evaluation, implemented using
>> coroutines? I would expect setcontext/getcontext to be very inefficient
>> for such purposes.
>
> Yes, setcontext/getcontext are basically used as a fallback if you
> want to implement context switching without an existing assembler
> implementation. They were specified to save and restore the process
> signal mask, which makes them quite slow. Perhaps slightly faster
> than a signal through a condition variable, but probably not by much.
>
The cost of changing the process(thread) signal mask depends heavily
on the implementation of that mask, specifically if it involves a
kernel transition or other slow serialization. It is certainly
conceivable to design a POSIX system that stores the signal mask in
a libc global/thread variable and checks it in an async libc function
invoked upon signal reception (that libc function would then decide
if it should call a handler, queue the signal, abnormally terminate
the process or simply ignore the signal).
> The trouble is anyone can write assembler code for coroutine
> suspend/resume, but the tricky part is making sure that it's actually
> correct in the presence of compiler optimizations. (We just went
> through that with the context switching implementation in C++ for a
> new architecture.) Using setcontext/getcontext is generally a safe
> bet (if you always resume on the same thread), but it's really quite
> slow.
>
>> Efficient coroutine support is going to need serious compiler support.
>
> Yes, and there could be ABI implications for TLS if the goal is to
> suspend with non-coroutine functions on the stack (as it is possible
> with setcontext/getcontext, but not with C++ coroutines).
>
What is even more important is to make a cross-platform API decision
if setcontext/getcontext should change the API level TLS context or
leave that context as referring to the thread that actually runs the
code on both sides of the context switch.
Knowing which it is would allow setcontext/getcontext programs to
know for sure which behavior to expect and program for.
Unless there is a widely implemented existing rule, it would be
preferable to avoid the common POSIX interpretation mistake of making
things per process simply because the sentence mentioning "process"
was written before threads were part of the overall concept.