cooperate2.c
/**
* 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 <stdio.h>
#include <ucontext.h>
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;
}