minix/lib/posix/_sleep.c
2005-04-21 14:53:53 +00:00

70 lines
1.8 KiB
C
Executable file

/* sleep() - Sleep for a number of seconds. Author: Kees J. Bot
* 24 Apr 2000
* (Inspired by the Minix-vmd version of same, except that
* this implementation doesn't bother to check if all the signal
* functions succeed. Under Minix that is no problem.)
*/
#include <lib.h>
#define sleep _sleep
#include <signal.h>
#include <unistd.h>
#include <time.h>
static void handler(int sig)
{
/* Dummy signal handler. */
}
unsigned sleep(unsigned sleep_seconds)
{
sigset_t ss_full, ss_orig, ss_alarm;
struct sigaction action_alarm, action_orig;
unsigned alarm_seconds, nap_seconds;
if (sleep_seconds == 0) return 0; /* No rest for the wicked */
/* Mask all signals. */
sigfillset(&ss_full);
sigprocmask(SIG_BLOCK, &ss_full, &ss_orig);
/* Cancel currently running alarm. */
alarm_seconds= alarm(0);
/* How long can we nap without interruptions? */
nap_seconds= sleep_seconds;
if (alarm_seconds != 0 && alarm_seconds < sleep_seconds) {
nap_seconds= alarm_seconds;
}
/* Now sleep. */
action_alarm.sa_handler= handler;
sigemptyset(&action_alarm.sa_mask);
action_alarm.sa_flags= 0;
sigaction(SIGALRM, &action_alarm, &action_orig);
alarm(nap_seconds);
/* Wait for a wakeup call, either our alarm, or some other signal. */
ss_alarm= ss_orig;
sigdelset(&ss_alarm, SIGALRM);
sigsuspend(&ss_alarm);
/* Cancel alarm, set mask and stuff back to normal. */
nap_seconds -= alarm(0);
sigaction(SIGALRM, &action_orig, NULL);
sigprocmask(SIG_SETMASK, &ss_orig, NULL);
/* Restore alarm counter to the time remaining. */
if (alarm_seconds != 0 && alarm_seconds >= nap_seconds) {
alarm_seconds -= nap_seconds;
if (alarm_seconds == 0) {
raise(SIGALRM); /* Alarm expires now! */
} else {
alarm(alarm_seconds); /* Count time remaining. */
}
}
/* Return time not slept. */
return sleep_seconds - nap_seconds;
}