cooperate1.c
/**
* 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 <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");
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;
}