#include <valgrind/memcheck.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>

void foo (int flass)
{
  fprintf (stderr, "**** %d ****\n", flass);
}

void func (int flass)
{
  ucontext_t *megacp;
  ucontext_t *omegacp;

  malloc (69);

  megacp = malloc (sizeof (ucontext_t));
  omegacp = malloc (sizeof (ucontext_t));

  getcontext (megacp);
  getcontext (omegacp);

  megacp->uc_stack.ss_sp = malloc (32768);
  megacp->uc_stack.ss_flags = 0;
  megacp->uc_stack.ss_size = 32768;
  megacp->uc_link = omegacp;

  makecontext (megacp, (void (*) ()) foo, 1, 2);

  VALGRIND_MAKE_READABLE (megacp, sizeof (ucontext_t));
  VALGRIND_MAKE_READABLE (omegacp, sizeof (ucontext_t));

  fprintf (stderr, "omegacp = %p, megacp = %p\n", omegacp, megacp);

  swapcontext (omegacp, megacp);

  fprintf (stderr, "**** %d ****\n", flass);

  free (megacp->uc_stack.ss_sp);
  free (megacp);
  free (omegacp);
}

int main (void)
{
  ucontext_t *ucp;
  ucontext_t *oucp;

  ucp = malloc (sizeof (ucontext_t));
  oucp = malloc (sizeof (ucontext_t));

  getcontext (ucp);
  getcontext (oucp);

  ucp->uc_stack.ss_sp = malloc (32768);
  ucp->uc_stack.ss_flags = 0;
  ucp->uc_stack.ss_size = 32768;
  ucp->uc_link = oucp;

  makecontext (ucp, (void (*) ()) func, 1, 1);

  VALGRIND_MAKE_READABLE (ucp, sizeof (ucontext_t));
  VALGRIND_MAKE_READABLE (oucp, sizeof (ucontext_t));

  fprintf (stderr, "oucp = %p, ucp = %p\n", oucp, ucp);

  swapcontext (oucp, ucp);

  fprintf (stderr, "**** %d ****\n", 4);

  free (ucp->uc_stack.ss_sp);
  free (ucp);
  free (oucp);

  return 0;
}
