#include <stdio.h>
#include <errno.h>

#include <signal.h>
#include <stddef.h>

#include <sys/time.h>

static void
sig_alrm(int arg)
{
  return; // nothing to do, just returning wakes up sigsuspend
}

unsigned int
msec_sleep(unsigned int msec)
{
  struct sigaction   newact, oldact;
  sigset_t           newmask, oldmask, suspmask;
  unsigned int       unslept;
  struct itimerval   itimer, itimerafter;

  newact.sa_handler = sig_alrm;
  sigemptyset(&newact.sa_mask);
  newact.sa_flags = 0;
  sigaction(SIGALRM, &newact, &oldact);

  sigemptyset(&newmask);
  sigaddset(&newmask, SIGALRM);
  sigprocmask(SIG_BLOCK, &newmask, &oldmask);

  itimer.it_interval.tv_sec = 0;
  itimer.it_interval.tv_usec = 0;
  itimer.it_value.tv_sec = msec / 1000;
  itimer.it_value.tv_usec = (msec % 1000) * 1000; 
  setitimer(ITIMER_REAL, &itimer, 0);

  suspmask = oldmask;
  sigdelset(&suspmask, SIGALRM);
  sigsuspend(&suspmask);

  getitimer(ITIMER_REAL, &itimerafter);
  unslept = itimerafter.it_value.tv_sec * 1000 +
    itimerafter.it_value.tv_usec / 1000;

  sigaction(SIGALRM, &oldact, NULL);
  sigprocmask(SIG_SETMASK, &oldmask, NULL);

  return unslept;
}

  

