#include #include #include #include #define STACK_SIZE 8192 /* * Structure of a process (a thread) */ struct proc { jmp_buf buf; char stack[STACK_SIZE]; }; struct proc buff; /* the "f" process */ struct proc bufg; /* the "g" process */ char* stack; /* lower adress of the stack (stack goes from stack to stack + STACK_SIZE */ int stack_index; /* an index used when we copy the stack */ struct proc* current; /* the current process */ void commut_to(struct proc* to) { /* save registers */ if(setjmp(current->buf) == 0) { /* save stack */ for(stack_index=0; stack_indexstack[stack_index] = stack[stack_index]; /* mark to as the new process */ current = to; /* restore registers */ longjmp(current->buf, 1); } else { /* be carreful: don't use any local variable to restore the stack of the new process */ /* basically, we are restoring the stack of the new process */ /* if we use a local variable, this variable will be in the stack (in the stack of the old process) */ /* when we will restore the stack of the new process, we will overwrite this local variable, which will take a strange value! */ /* => don't use local variable, and don't use memcpy as memcpy may use local variable */ /* restore stack (stack_index and current are both global variables) */ for(stack_index=0; stack_indexstack[stack_index]; } } void f() { int n = 0; for(int i=0; i<10; i++) { printf("f: %d\n", n++); /* f is running, jump to g */ commut_to(&bufg); } } void g() { int m = 1000; for(int i=0; i<10; i++) { printf("g: %d\n", m++); /* g is running, jump to f */ commut_to(&buff); } } int main(int argc, char** argv) { /* a random variable on the stack (in the frame of main) */ char var; stack = &var - STACK_SIZE; /* the lower adress of the stack is at &var - STACK_SIZE */ current = &buff; /* f is running at the beginning */ /* preserve the registers to start g */ if(setjmp(bufg.buf) == 0) { f(); } else { g(); } }