xref: /netbsd-src/external/gpl2/xcvs/dist/lib/nanosleep.c (revision 5a6c14c844c4c665da5632061aebde7bb2cb5766)
1a7c91847Schristos /* Provide a replacement for the POSIX nanosleep function.
2a7c91847Schristos    Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
3a7c91847Schristos 
4a7c91847Schristos    This program is free software; you can redistribute it and/or modify
5a7c91847Schristos    it under the terms of the GNU General Public License as published by
6a7c91847Schristos    the Free Software Foundation; either version 2, or (at your option)
7a7c91847Schristos    any later version.
8a7c91847Schristos 
9a7c91847Schristos    This program is distributed in the hope that it will be useful,
10a7c91847Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
11a7c91847Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12a7c91847Schristos    GNU General Public License for more details.
13a7c91847Schristos 
14a7c91847Schristos    You should have received a copy of the GNU General Public License
15a7c91847Schristos    along with this program; if not, write to the Free Software Foundation,
16a7c91847Schristos    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17*5a6c14c8Schristos #include <sys/cdefs.h>
18*5a6c14c8Schristos __RCSID("$NetBSD: nanosleep.c,v 1.2 2016/05/17 14:00:09 christos Exp $");
19*5a6c14c8Schristos 
20a7c91847Schristos 
21a7c91847Schristos /* written by Jim Meyering */
22a7c91847Schristos 
23a7c91847Schristos #ifdef HAVE_CONFIG_H
24a7c91847Schristos # include <config.h>
25a7c91847Schristos #endif
26a7c91847Schristos 
27a7c91847Schristos /* Undefine nanosleep here so any prototype is not redefined to be a
28a7c91847Schristos    prototype for rpl_nanosleep. (they'd conflict e.g., on alpha-dec-osf3.2)  */
29a7c91847Schristos #undef nanosleep
30a7c91847Schristos 
31a7c91847Schristos #include <stdbool.h>
32a7c91847Schristos #include <stdio.h>
33a7c91847Schristos #include <sys/types.h>
34a7c91847Schristos #include <signal.h>
35a7c91847Schristos 
36a7c91847Schristos #include <errno.h>
37a7c91847Schristos 
38a7c91847Schristos #if HAVE_UNISTD_H
39a7c91847Schristos # include <unistd.h>
40a7c91847Schristos #endif
41a7c91847Schristos 
42a7c91847Schristos #include "timespec.h"
43a7c91847Schristos 
44a7c91847Schristos /* Some systems (MSDOS) don't have SIGCONT.
45a7c91847Schristos    Using SIGTERM here turns the signal-handling code below
46a7c91847Schristos    into a no-op on such systems. */
47a7c91847Schristos #ifndef SIGCONT
48a7c91847Schristos # define SIGCONT SIGTERM
49a7c91847Schristos #endif
50a7c91847Schristos 
51a7c91847Schristos #if ! HAVE_SIGINTERRUPT
52a7c91847Schristos # define siginterrupt(sig, flag) /* empty */
53a7c91847Schristos #endif
54a7c91847Schristos 
55a7c91847Schristos static sig_atomic_t volatile suspended;
56a7c91847Schristos 
57a7c91847Schristos /* Handle SIGCONT. */
58a7c91847Schristos 
59a7c91847Schristos static void
sighandler(int sig)60a7c91847Schristos sighandler (int sig)
61a7c91847Schristos {
62a7c91847Schristos   suspended = 1;
63a7c91847Schristos }
64a7c91847Schristos 
65a7c91847Schristos /* FIXME: comment */
66a7c91847Schristos 
67a7c91847Schristos static void
my_usleep(const struct timespec * ts_delay)68a7c91847Schristos my_usleep (const struct timespec *ts_delay)
69a7c91847Schristos {
70a7c91847Schristos   struct timeval tv_delay;
71a7c91847Schristos   tv_delay.tv_sec = ts_delay->tv_sec;
72a7c91847Schristos   tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000;
73a7c91847Schristos   if (tv_delay.tv_usec == 1000000)
74a7c91847Schristos     {
75a7c91847Schristos       tv_delay.tv_sec++;
76a7c91847Schristos       tv_delay.tv_usec = 0;
77a7c91847Schristos     }
78a7c91847Schristos   select (0, NULL, NULL, NULL, &tv_delay);
79a7c91847Schristos }
80a7c91847Schristos 
81a7c91847Schristos /* FIXME: comment */
82a7c91847Schristos 
83a7c91847Schristos int
rpl_nanosleep(const struct timespec * requested_delay,struct timespec * remaining_delay)84a7c91847Schristos rpl_nanosleep (const struct timespec *requested_delay,
85a7c91847Schristos 	       struct timespec *remaining_delay)
86a7c91847Schristos {
87a7c91847Schristos   static bool initialized;
88a7c91847Schristos 
89a7c91847Schristos   /* set up sig handler */
90a7c91847Schristos   if (! initialized)
91a7c91847Schristos     {
92a7c91847Schristos #ifdef SA_NOCLDSTOP
93a7c91847Schristos       struct sigaction oldact, newact;
94a7c91847Schristos       newact.sa_handler = sighandler;
95a7c91847Schristos       sigemptyset (&newact.sa_mask);
96a7c91847Schristos       newact.sa_flags = 0;
97a7c91847Schristos 
98a7c91847Schristos       sigaction (SIGCONT, NULL, &oldact);
99a7c91847Schristos       if (oldact.sa_handler != SIG_IGN)
100a7c91847Schristos 	sigaction (SIGCONT, &newact, NULL);
101a7c91847Schristos #else
102a7c91847Schristos       if (signal (SIGCONT, SIG_IGN) != SIG_IGN)
103a7c91847Schristos 	{
104a7c91847Schristos 	  signal (SIGCONT, sighandler);
105a7c91847Schristos 	  siginterrupt (SIGCONT, 1);
106a7c91847Schristos 	}
107a7c91847Schristos #endif
108a7c91847Schristos       initialized = true;
109a7c91847Schristos     }
110a7c91847Schristos 
111a7c91847Schristos   suspended = 0;
112a7c91847Schristos 
113a7c91847Schristos   my_usleep (requested_delay);
114a7c91847Schristos 
115a7c91847Schristos   if (suspended)
116a7c91847Schristos     {
117a7c91847Schristos       /* Calculate time remaining.  */
118a7c91847Schristos       /* FIXME: the code in sleep doesn't use this, so there's no
119a7c91847Schristos 	 rush to implement it.  */
120a7c91847Schristos 
121a7c91847Schristos       errno = EINTR;
122a7c91847Schristos     }
123a7c91847Schristos 
124a7c91847Schristos   /* FIXME: Restore sig handler?  */
125a7c91847Schristos 
126a7c91847Schristos   return suspended;
127a7c91847Schristos }
128