#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>
#include <ucontext.h>
#include <assert.h>
#include <string.h>

ucontext_t box_context;
ucontext_t old_context;

sig_atomic_t in_box = 0;


void handler (int sig, siginfo_t *info, void *context) {
 ucontext_t *c = context;

 if (in_box) {
  /* context is box_context */
  box_context = *c;
  *c = old_context;
  in_box = 0;
 } else {
  old_context = *c;
  *c = box_context;
  in_box = 1;
 }
}

void sig_handler (int sig) {
 puts ("SIG");
}

void box (int a, int b) {
 while (1) {
  puts ("BOX");
 }
}

int main () { 
 int error;
 struct itimerval timer;
 struct sigaction action;
 char *stack;
 
 action.sa_handler = SIG_IGN;
 action.sa_sigaction = handler;
 sigemptyset (&action.sa_mask);
 action.sa_flags = SA_SIGINFO | SA_RESTART;

 error = sigaction (SIGALRM, &action, NULL);

 if (error) {
  perror ("sigaction");
  return EXIT_FAILURE;
 }


 stack = malloc (4096);
 /* hack */
 assert (NULL != stack);

 if (getcontext (&box_context)) {
  perror ("getcontext");
  return EXIT_FAILURE;
 }

 box_context.uc_link = NULL;
 box_context.uc_stack.ss_sp = stack;
 box_context.uc_stack.ss_size = 4096;
 box_context.uc_stack.ss_flags = 0;

 makecontext (&box_context, box, 2, 1, 2);

 timer.it_interval.tv_sec = 1;
 timer.it_interval.tv_usec = 0;
 
 timer.it_value.tv_sec = 0;
 timer.it_value.tv_usec = 10;

 error = setitimer (ITIMER_REAL, &timer, NULL);

 if (error) {
  perror ("setitimer");
  return EXIT_FAILURE;
 }

 while (1) {
  puts ("MAIN");
 }

 return EXIT_SUCCESS;
}
