4 ms·
That is majestically vile. It took me a while before I figured out how it was assigning the new coroutine's stack pointer, and then I was filled with admiration
by david-given 12y ago
That is majestically vile. It took me a while before I figured out how it was assigning the new coroutine's stack pointer, and then I was filled with admiration and a little nausea.
I'm not sure if this will work in real life; it looks like it's relying heavily on C compiler magic to ensure that the stack's laid out the way it wants. (Plus, allocating stacks with malloc() doesn't work on some architectures, and I have encountered pthreads implementations that get very unhappy if you change stacks on them).
But it's still a deeply impressive piece of lateral thinking.
- ehmmm 12y agoCan you elaborate on that. It doesn't seem to work correctly on my machine. Writing beyond heap bounds and uninitialized reads.
- rumcajz 12y agoIt uses dynamically allocated array (char filler_[...]) to shift stack pointer to arbitrary memory address. If it doesn't work with your compiler you may try to use alloca() instead.
- ehmmm 12y agoOh I see, it moves the stack pointer so it coincides with the heap allocated memory? I like articles that combine hacking and C, but this one really needs more explanation.
- rumcajz 12y agoThis article is really about the arguments to the coroutine. The original idea for shifting the stack pointer comes from here: http://fanf.livejournal.com/105413.html http://fanf.livejournal.com/105413.html
- thechao 12y agoHere's my implementation in c++, using alloca(): https://github.com/jaroslov/coro https://github.com/jaroslov/coro. Without debugger support, coroutines are pretty difficult to work with.
- userbinator 12y agoIt should be possible to do this without malloc(), by allocating the co-stack as an array within the current stack. Something like this... char stack[STACK_SIZE]; int anchor_[unoptimisable_]; char filler_[(char*)&anchor_ - (char*)(stack + STACK_SIZE)]; ... (Haven't tested it, but it's basically the same principle. The same caveats about stack layout and VLAs apply.)
- rumcajz 12y agoExcept that if the parent function terminated before the coroutine it have launched, you would get memory overwrites.
- mtanski 12y agoYou would also need to align the stack per. target requirements (gcc keyword, or offset the address). The aliment guarantees for char[] placed on stack are probably insufficient for many machines.
- userbinator 12y agoIf none of the variables on the stack are smaller than your desired alignment size, and the stack starts out aligned (which it should), then it will remain aligned.
- mtanski 12y agoThe code in question strikes me as being a proof of concept. Obviously, a more complete implementation would be more complex. In the real world you'd create a stack with mmap with the MMAP_STACK flag. You would ensure the stack is property aligned and make sure there's a guard page at the end of it.