1 /* Implementation of the POSIX sleep function using nanosleep.
2 Copyright (C) 1996,1997,1998,1999,2003,2005 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
23 #include <string.h> /* For the real memset prototype. */
25 #include <sys/param.h>
32 (void) __sigprocmask (SIG_SETMASK
, arg
, (sigset_t
*) NULL
);
37 /* We are going to use the `nanosleep' syscall of the kernel. But the
38 kernel does not implement the stupid SysV SIGCHLD vs. SIG_IGN
39 behaviour for this syscall. Therefore we have to emulate it here. */
41 __sleep (unsigned int seconds
)
43 const unsigned int max
44 = (unsigned int) (((unsigned long int) (~((time_t) 0))) >> 1);
49 /* This is not necessary but some buggy programs depend on this. */
50 if (__builtin_expect (seconds
== 0, 0))
53 CANCELLATION_P (THREAD_SELF
);
61 if (sizeof (ts
.tv_sec
) <= sizeof (seconds
))
63 /* Since SECONDS is unsigned assigning the value to .tv_sec can
64 overflow it. In this case we have to wait in steps. */
65 ts
.tv_sec
+= MIN (seconds
, max
);
66 seconds
-= (unsigned int) ts
.tv_sec
;
70 ts
.tv_sec
= (time_t) seconds
;
74 /* Linux will wake up the system call, nanosleep, when SIGCHLD
75 arrives even if SIGCHLD is ignored. We have to deal with it
76 in libc. We block SIGCHLD first. */
78 __sigaddset (&set
, SIGCHLD
);
79 if (__sigprocmask (SIG_BLOCK
, &set
, &oset
))
82 /* If SIGCHLD is already blocked, we don't have to do anything. */
83 if (!__sigismember (&oset
, SIGCHLD
))
86 struct sigaction oact
;
89 __sigaddset (&set
, SIGCHLD
);
91 /* We get the signal handler for SIGCHLD. */
92 if (__sigaction (SIGCHLD
, (struct sigaction
*) NULL
, &oact
) < 0)
95 /* Restore the original signal mask. */
96 (void) __sigprocmask (SIG_SETMASK
, &oset
, (sigset_t
*) NULL
);
97 __set_errno (saved_errno
);
101 /* Note the sleep() is a cancellation point. But since we call
102 nanosleep() which itself is a cancellation point we do not
103 have to do anything here. */
104 if (oact
.sa_handler
== SIG_IGN
)
106 //__libc_cleanup_push (cl, &oset);
108 /* We should leave SIGCHLD blocked. */
111 result
= __nanosleep (&ts
, &ts
);
113 if (result
!= 0 || seconds
== 0)
116 if (sizeof (ts
.tv_sec
) <= sizeof (seconds
))
118 ts
.tv_sec
= MIN (seconds
, max
);
119 seconds
-= (unsigned int) ts
.tv_nsec
;
123 //__libc_cleanup_pop (0);
126 /* Restore the original signal mask. */
127 (void) __sigprocmask (SIG_SETMASK
, &oset
, (sigset_t
*) NULL
);
128 __set_errno (saved_errno
);
133 /* We should unblock SIGCHLD. Restore the original signal mask. */
134 (void) __sigprocmask (SIG_SETMASK
, &oset
, (sigset_t
*) NULL
);
137 result
= __nanosleep (&ts
, &ts
);
138 if (result
== 0 && seconds
!= 0)
143 /* Round remaining time. */
144 result
= seconds
+ (unsigned int) ts
.tv_sec
+ (ts
.tv_nsec
>= 500000000L);
148 weak_alias (__sleep
, sleep
)