Stefan Hajnoczi wrote: > My current plan is to try using sigaltstack(2) instead of > makecontext()/swapcontext() as a hack since OpenBSD doesn't have > makecontext()/swapcontext().
sigaltstack() is just a system call to tell the system about an alternative signal stack - that you have allocated yourself using malloc(). According to 'info libc "Signal Stack"'. It won't help you get a new stack by itself. Maybe take a look at what GNU Pth does. It has a similar matrix of tested platforms using different strategies on each, though it is slightly different because it obviously doesn't link with libpthread.so (it provides it!), and it has to context switch from the SIGALRM handler for pre-emption. > TBH I'm almost at the stage where I think we should just use threads > and/or async callbacks, as appropriate. Hopefully I'll be able to cook > up a reasonably portable implementation of coroutines though, because > the prospect of having to go fully threaded or do async callbacks isn't > attractive in many cases. Another classic trick is just to call a function recursively which has a large local array(*), setjmp() every M calls, and longjmp() back to the start after M*N calls. That gets you N setjmp() contexts to switch between, all in the same larger stack so it's fine even with old pthread implementations, providing the total stack used isn't too big, and the individual stacks you've allocated aren't too small for the program. If the large local array insists on being optimised away, it's probably better anyway to track the address of a local variable, and split the stack whenever the address has changed by enough. Try to make sure the compiler doesn't optimise away the tail recursion :-) It works better on non-threaded programs as per-thread stacks are more likely to have limited size. *But* the initial thread often has a large growable stack, just like a single-threaded program. So it's a good idea to do the stack carving in the initial thread (doesn't necessarily have to be at the start of the program). You may be able to add guard pages afterwards with mprotect() if you're paranoid :-) -- Jamie