#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <inttypes.h>
#include <sys/time.h>
uint32_t COUNTER;
int64_t t0, t1;
int64_t timeInMS ()
{
struct timeval t;
gettimeofday(&t, NULL);
return (
(int64_t)t.tv_sec * 1000 +
(int64_t)t.tv_usec / 1000
);
}
ucontext_t start_context, tasks[2];
void threads(
int id
)
{
for (;;) {
if ((COUNTER & 0xfff) == 0) {
t1 = timeInMS();
if (t1 - t0 >= 1000) {
// finished
setcontext(&start_context);
}
}
COUNTER++;
swapcontext(&tasks[id], &tasks[1-id]);
}
}
#define panic printf("panic: %u\n", __LINE__); exit(1);
int main(void)
{
char task1_stack[SIGSTKSZ];
char task2_stack[SIGSTKSZ];
volatile int flag = 0;
COUNTER = 0;
getcontext(&tasks[0]);
getcontext(&tasks[1]);
if (flag)
{
panic;
}
flag = 1;
tasks[0].uc_link = 0;
tasks[0].uc_stack.ss_sp = task1_stack;
tasks[0].uc_stack.ss_size = sizeof(task1_stack);
makecontext(&tasks[0], (void (*)(void))threads, 1, 0);
tasks[1].uc_link = 0;
tasks[1].uc_stack.ss_sp = task2_stack;
tasks[1].uc_stack.ss_size = sizeof(task2_stack);
makecontext(&tasks[1], (void (*)(void))threads, 1, 1);
t0 = timeInMS();
if (-1 == swapcontext(&start_context, &tasks[1]))
{
panic;
}
t1 = timeInMS() - t0;
// Correct the number of context switches accordingly
COUNTER = (uint32_t)(((uint64_t)COUNTER * 1000) / t1);
printf("Number of ucontext switches in about one second was %u\n", COUNTER);
exit(0);
}