| 1 | /*      sleep() - Sleep for a number of seconds.        Author: Kees J. Bot
 | 
|---|
| 2 |  *                                                              24 Apr 2000
 | 
|---|
| 3 |  * (Inspired by the Minix-vmd version of same, except that
 | 
|---|
| 4 |  * this implementation doesn't bother to check if all the signal
 | 
|---|
| 5 |  * functions succeed.  Under Minix that is no problem.)
 | 
|---|
| 6 |  */
 | 
|---|
| 7 | 
 | 
|---|
| 8 | #include <lib.h>
 | 
|---|
| 9 | #define sleep _sleep
 | 
|---|
| 10 | #include <signal.h>
 | 
|---|
| 11 | #include <unistd.h>
 | 
|---|
| 12 | #include <time.h>
 | 
|---|
| 13 | 
 | 
|---|
| 14 | static void handler(int sig)
 | 
|---|
| 15 | {
 | 
|---|
| 16 |         /* Dummy signal handler. */
 | 
|---|
| 17 | }
 | 
|---|
| 18 | 
 | 
|---|
| 19 | unsigned sleep(unsigned sleep_seconds)
 | 
|---|
| 20 | {
 | 
|---|
| 21 |         sigset_t ss_full, ss_orig, ss_alarm;
 | 
|---|
| 22 |         struct sigaction action_alarm, action_orig;
 | 
|---|
| 23 |         unsigned alarm_seconds, nap_seconds;
 | 
|---|
| 24 | 
 | 
|---|
| 25 |         if (sleep_seconds == 0) return 0;       /* No rest for the wicked */
 | 
|---|
| 26 | 
 | 
|---|
| 27 |         /* Mask all signals. */
 | 
|---|
| 28 |         sigfillset(&ss_full);
 | 
|---|
| 29 |         sigprocmask(SIG_BLOCK, &ss_full, &ss_orig);
 | 
|---|
| 30 | 
 | 
|---|
| 31 |         /* Cancel currently running alarm. */
 | 
|---|
| 32 |         alarm_seconds= alarm(0);
 | 
|---|
| 33 | 
 | 
|---|
| 34 |         /* How long can we nap without interruptions? */
 | 
|---|
| 35 |         nap_seconds= sleep_seconds;
 | 
|---|
| 36 |         if (alarm_seconds != 0 && alarm_seconds < sleep_seconds) {
 | 
|---|
| 37 |                 nap_seconds= alarm_seconds;
 | 
|---|
| 38 |         }
 | 
|---|
| 39 | 
 | 
|---|
| 40 |         /* Now sleep. */
 | 
|---|
| 41 |         action_alarm.sa_handler= handler;
 | 
|---|
| 42 |         sigemptyset(&action_alarm.sa_mask);
 | 
|---|
| 43 |         action_alarm.sa_flags= 0;
 | 
|---|
| 44 |         sigaction(SIGALRM, &action_alarm, &action_orig);
 | 
|---|
| 45 |         alarm(nap_seconds);
 | 
|---|
| 46 | 
 | 
|---|
| 47 |         /* Wait for a wakeup call, either our alarm, or some other signal. */
 | 
|---|
| 48 |         ss_alarm= ss_orig;
 | 
|---|
| 49 |         sigdelset(&ss_alarm, SIGALRM);
 | 
|---|
| 50 |         sigsuspend(&ss_alarm);
 | 
|---|
| 51 | 
 | 
|---|
| 52 |         /* Cancel alarm, set mask and stuff back to normal. */
 | 
|---|
| 53 |         nap_seconds -= alarm(0);
 | 
|---|
| 54 |         sigaction(SIGALRM, &action_orig, NULL);
 | 
|---|
| 55 |         sigprocmask(SIG_SETMASK, &ss_orig, NULL);
 | 
|---|
| 56 | 
 | 
|---|
| 57 |         /* Restore alarm counter to the time remaining. */
 | 
|---|
| 58 |         if (alarm_seconds != 0 && alarm_seconds >= nap_seconds) {
 | 
|---|
| 59 |                 alarm_seconds -= nap_seconds;
 | 
|---|
| 60 |                 if (alarm_seconds == 0) {
 | 
|---|
| 61 |                         raise(SIGALRM);         /* Alarm expires now! */
 | 
|---|
| 62 |                 } else {
 | 
|---|
| 63 |                         alarm(alarm_seconds);   /* Count time remaining. */
 | 
|---|
| 64 |                 }
 | 
|---|
| 65 |         }
 | 
|---|
| 66 | 
 | 
|---|
| 67 |         /* Return time not slept. */
 | 
|---|
| 68 |         return sleep_seconds - nap_seconds;
 | 
|---|
| 69 | }
 | 
|---|