/** * cooperate1.c * * Demonstrates two "threads" (or rather, execution contexts), one running * before another. This example is probably not that exciting: it looks like it * just runs two functions in succession. However, imagine that the functions * were loaded dynamically (like regular programs such as ls, pwd, etc.), and * note that we are not directly calling them. * * Compile: * gcc -Wall -o cooperate1 cooperate1.c */ #include #include ucontext_t context[3]; void thread1(void) { int i; for (i = 0; i <= 1000000000; i++) { /* Spin! Spin! Spin! */ } printf("Thread 1: Finished first loop\n"); for (i = 0; i <= 1000000000; i++); printf("Thread 1: Finished second loop\n"); for (i = 0; i <= 1000000000; i++); printf("Thread 1: Finished third loop\n"); } void thread2(void) { int i; for (i = 0; i <= 1000000000; i++); printf("Thread 2: Finished first loop\n"); for (i = 0; i <= 1000000000; i++); printf("Thread 2: Finished second loop\n"); for (i = 0; i <= 1000000000; i++); printf("Thread 2: Finished third loop\n"); } int main(void) { char stack1[SIGSTKSZ]; char stack2[SIGSTKSZ]; getcontext(&context[0]); getcontext(&context[1]); context[1].uc_stack.ss_sp = stack1; context[1].uc_stack.ss_size = sizeof(stack1); /* uc_link determines where the execution context returns to when it * completes: */ context[1].uc_link = &context[2]; makecontext(&context[1], thread1, 0); getcontext(&context[2]); context[2].uc_stack.ss_sp = stack2; context[2].uc_stack.ss_size = sizeof(stack2); /* Note that the 2nd thread will return back to main(): */ context[2].uc_link = &context[0]; makecontext(&context[2], thread2, 0); swapcontext(&context[0], &context[1]); return 0; }