/** * cooperate2.c * * Demonstrates two "threads" employing an extremely basic cooperative * multitasking approach. Each thread does a bit of its overall work and then * yields control of the CPU over to the other thread. This interleaves thread * progress (rather than executing sequentially as in cooperate1.c) * * Compile: * gcc -Wall -o cooperate2 cooperate2.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"); swapcontext(&context[1], &context[2]); for (i = 0; i <= 1000000000; i++); printf("Thread 1: Finished second loop\n"); swapcontext(&context[1], &context[2]); 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"); swapcontext(&context[2], &context[1]); for (i = 0; i <= 1000000000; i++); printf("Thread 2: Finished second loop\n"); swapcontext(&context[2], &context[1]); 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; }