[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: pcall() and coroutine.yield()
- From: Edgar Toernig <froese@...>
- Date: Thu, 21 Oct 2004 00:23:29 +0200
David Given wrote:
>
> There are some very handy but little-known functions called
> setcontext()/getcontext()/makecontext()/swapcontext() that make
> implementing coroutines a doddle.
Yes, I know them. Unfortunately, they are not widely available.
I.e. not on my system and afaik not under Windows either.
The major downside I see with the ucontext functions is that they
perform system calls during swapcontext (to change signal masks).
Performance goes down the drain...
The setup_jmpbuf function I posted earlier is the absolutely
minimal code[1] required to implement coroutines or userspace
threads. I.e. an implementation of the ucontext functions with
all features required for Lua comes down to this:
| typedef jmp_buf mcontext_t; // our mcontext is a jmp_buf
|
| // setcontext/getcontext are not really needed but
| // to show their implementation:
| #define setcontext(uc) longjmp((uc)->uc_mcontext, 1)
| #define getcontext(uc) (setjmp((uc)->uc_mcontext), 0)
|
| int swapcontext(ucontext_t *ouc, ucontext_t *nuc)
| {
| if (setjmp(ouc->uc_mcontext) == 0)
| longjmp(nuc->uc_mcontext, 1);
| return 0;
| }
|
| void makecontext(ucontext_t *uc, void (*func)(), int argc, ...)
| {
| assert(argc == 0); // makecontext only allows int args
| // which makes them useless for Lua.
| setup_jmpbuf(uc->uc_mcontext, func,
| uc->uc_stack.ss_sp,
| uc->uc_stack.ss_sp + uc->uc_stack.ss_size)
| }
Maybe one could use the ucontext functions to implement the
C-level coroutines for Lua. If there is no native implement-
ation or it is too slow because of the sigmask stuff one could
fall back to the trivial version based on setup_jmpbuf.
Ciao, ET.
[1] I.e. the implementation for x86-linux libc5 (my system):
| void
| setup_jmpbuf(jmp_buf buf, void (*func)(void), void *stack, void *stackend)
| {
| setjmp(buf); // initialize jmp_buf with some sane values
| buf->__sp = stackend;
| buf->__pc = func;
| }