tags:

views:

120

answers:

2

Hi, is there a way to implement multitasking using setjmp and longjmp

+2  A: 

No, the context produced by setjmp becomes invalid when you leave the function which called setjmp. So, you can't jump back and forth between setjmp locations, you can only jump back up the stack.

For clarity, it also means, if you longjmp out of a function, any contexts created by setjmp within the function you're just jumping out of, will also be invalidated.

roe
Actually, you're mistaken. Many years ago, I created a threading library using `setjmp` and `longjmp` which worked on both Linux and under 32-bit DOS. Admittedly, it wasn't complete though -- no Mutex or scheduling, etc.
Carter Galle
@Carter; I'm only quoting the man-page, can't say I've ever actually had the idea to try if it worked when it says it shouldn't.
roe
Just as a `return` from a thread function ends the thread, returning from the context of the `setjmp` would indeed invalidate the context used in the _*jmp_ thread. So your first sentence is correct except for the word *No*. Jumping between "threads" does work with the `setjmp`/`longjmp` functions (I've forgot the details) but it is tedious and prone to errors.
Carter Galle
+2  A: 

It may be bending the rules a little, but GNU pth does this. It's possible, but you probably shouldn't try it yourself except as an academic proof-of-concept exercise, use the pth implementation if you want to do it seriously and in a remotely portable fashion -- you'll understand why when you read the pth thread creation code.

(Essentially it uses a signal handler to trick the OS into creating a fresh stack, then longjmp's out of there and keeps the stack around. It works, evidently, but it's sketchy as hell.)

In production code, if your OS supports makecontext/swapcontext, use those instead. If it supports CreateFiber/SwitchToFiber, use those instead. And be aware of the disappointing truth that one of the most compelling use of coroutines -- that is, inverting control by yielding out of event handlers called by foreign code -- is unsafe because the calling module has to be reentrant, and you generally can't prove that. This is why fibers still aren't supported in .NET...

The Netscape Portable Runtime (NSPR) also appears to define macros for doing this using a simpler but hairier method: they just call setjmp and then change the machine stack pointer and instruction pointer in the buffer. Google "_MD_INIT_CONTEXT" for an entertaining read.