Bunki, a C Coroutine Library
github.com
github.com
There is a really good blog post to understand coroutines from an assembly perspective here: https://blog.dziban.net/coroutines/
I ported the intel assembly syntax in that blog post to at&t syntax and assembled it with GNU Assembler https://github.com/samsquire/assembly as coroutines.S
there is also protothreads and Tina http://dunkels.com/adam/pt/ https://github.com/slembcke/Tina
If you happen to know what a void* is pointing to, you can cast it to another type like "my_struct_t*" and deference the value. I would call it a work around for C lacking true polymorphism.
Certain win32 api calls actually use fibers deep down even if you don't use them. You will get a crash after bouncing around. I vaguely remember(or think) schannel is one such set of win32 functions that'll cause it.
Good name! That's very nice.
We also have "búnt" which is used for a bunch of flowers
For a few similar things:
* It can Yield from anywhere
* You can push data on the stack when creating a co-routine
* It has a slot for local storage in the coroutine (the library you linked calls it user_data).
* It should be pretty light weight since it uses assembly and saves as little state as possible based off the calling the conventions.
There are differences though. One big difference is I do have functions that let you call functions that generate deep call stacks on the thread stack.
As for the errno thing: the whole point about coroutines is that they are cooperatively scheduled, they don't yield unless you specifically tell them to. As long as you don't insert a yield-point in between the function that sets errno and then reading the value (and you should also always read errno immediately anyway), I don't see what the problem is (except errno being a terrible API in general, but that ship has pretty much sailed).
address_of_errno = &errno;
...
foo = *address_of_errno;
The compiler can assume that the address stays the same across the whole execution of the function and cache it in a register. Unfortunately, if you can change threads across yield points, you can end up reading the errno of the wrong function.Instead, C++ stackless coroutines explicitly promise that you will read the TLS of the currently executing thread in this case.
This is what we found, but I cannot rule out that this is the only possibility.
I'd argue that the problem here is that you should obviously not use TLS with corutines, since they can be scheduled on any thread. The concept of thread-local storage just doesn't make much sense for coroutines. The issue isn't necessarily that there's anything wrong with coroutines, it's rather with APIs that use TLS as an information side-channel. errno is just a bad idea, basically.
But point taken.
Unfortunately, this has happened and is not hypothetical, but at least for now we're stuck in the stackful hole we dug for ourselves. :( A few years back we had similar issues on Windows.
As for runtime this is why people follow an ABI. Otherwise lots of things like dynamic linking ect... would not work.
QEMU uses stackful coroutines, and it's a great programming model but we ended up fighting the compiler more than once. You can build a more traditional enter/yield API on top of C++ coroutines, see for example https://lore.kernel.org/qemu-devel/YjMuyMcwG09Tohyh@redhat.c....
So unless there is an authoritative mirror somewhere I can't tell you.
cothread_t co_active(void); cothread_t co_derive(void, unsigned int, void ()(void)); cothread_t co_create(unsigned int, void (*)(void)); void co_delete(cothread_t); void co_switch(cothread_t); int co_serializable(void);
Also it uses malloc to create the stacks. My library lets decide how wish to allocate stacks with. On linux I recommend mmap since you can create guard pages and such, but it's completely up to. Also I have functions that can let you call an other function on thread stack. This is handy to let you call a function that generates a deep call stack. Otherwise you have to mess around hopping back and forth between couroutines and the main thread context.