My web server uses coroutines, and for x86 and x86-64 it uses open-coded assembly routines to yield/resume, with fallbacks to setjmp()/longjmp() on other architectures.
It works fairly well, performance-wise. In fact, it's one of the top-performing servers/frameworks in the TechEmpower's Web Framework benchmarks[1].
I wrote a similar article explaining how everything is put together here[2].
[1] https://www.techempower.com/benchmarks/ [2] http://tia.mat.br/blog/html/2014/10/06/life_of_a_http_reques...
The Boost Coroutine library is built on top, adds type safety, ensures the stack is unwound when contexts are destroyed, and enables propagation of exceptions across switches.
$ ls -lh /usr/lib/libboost_context.so.1.58.0
-rwxr-xr-x 1 root root 55K May 30 09:58 /usr/lib/libboost_context.so.1.58.0
[0] http://www.boost.org/doc/libs/1_58_0/libs/context/doc/html/i...[1] http://www.boost.org/doc/libs/1_58_0/libs/context/doc/html/c...
[2] http://www.boost.org/doc/libs/1_58_0/libs/context/doc/html/c...
[1] https://lwn.net/Articles/605607/
(Also, I ended up mixing up ucontext.h with setjmp.h in my comment above; Lwan uses ucontext.h as a fallback. There are coroutine implementations that will use setjmp/longjmp, or at the very least reuse the jmp_buf struct and roll their own asm, though.)
(Note: in case it wasn't clear, I'm not suggesting we put all of coroutines into glibc, just the stack dancing stuff)