summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-10-22 15:22:40 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-10-22 15:22:40 +0200
commit62fb840ea00d9d10446959d290d93a45065220f4 (patch)
treee6a31f6d248a40613fb5926793d5367513488f5f /libc
parentf53db356f53686cb0e4ddb25946b8cff9e82453d (diff)
sleep: check "SIGCHLD is SIG_IGN'ed" first. Saves two syscalls in common case
text data bss dec hex filename - 197 0 0 197 c5 libc/unistd/sleep.o + 168 0 0 168 a8 libc/unistd/sleep.o Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'libc')
-rw-r--r--libc/unistd/sleep.c40
1 files changed, 18 insertions, 22 deletions
diff --git a/libc/unistd/sleep.c b/libc/unistd/sleep.c
index 55e646380..481e635a2 100644
--- a/libc/unistd/sleep.c
+++ b/libc/unistd/sleep.c
@@ -50,6 +50,7 @@ unsigned int sleep (unsigned int seconds)
{
struct timespec ts = { .tv_sec = (long int) seconds, .tv_nsec = 0 };
sigset_t set;
+ struct sigaction oact;
unsigned int result;
/* This is not necessary but some buggy programs depend on this. */
@@ -62,33 +63,28 @@ unsigned int sleep (unsigned int seconds)
/* Linux will wake up the system call, nanosleep, when SIGCHLD
arrives even if SIGCHLD is ignored. We have to deal with it
- in libc. We block SIGCHLD first. */
+ in libc. */
+
__sigemptyset (&set);
__sigaddset (&set, SIGCHLD);
- sigprocmask (SIG_BLOCK, &set, &set); /* never fails */
- /* If SIGCHLD was already blocked, no need to check SIG_IGN. Else... */
+ /* Is SIGCHLD set to SIG_IGN? */
+ sigaction (SIGCHLD, NULL, &oact); /* never fails */
+ if (oact.sa_handler == SIG_IGN) {
+ /* Yes. Block SIGCHLD, save old mask. */
+ sigprocmask (SIG_BLOCK, &set, &set); /* never fails */
+ }
+
+ /* Run nanosleep, with SIGCHLD blocked if SIGCHLD is SIG_IGNed. */
+ result = nanosleep (&ts, &ts);
+
if (!__sigismember (&set, SIGCHLD)) {
- struct sigaction oact;
-
- /* Is SIGCHLD set to SIG_IGN? */
- sigaction (SIGCHLD, NULL, &oact); /* never fails */
- if (oact.sa_handler == SIG_IGN) {
- /* Yes, run nanosleep with SIGCHLD blocked. */
- result = nanosleep (&ts, &ts);
-
- /* Unblock SIGCHLD by restoring signal mask. */
- /* this sigprocmask call never fails, thus never updates errno,
- and therefore we don't need to save/restore it. */
- sigprocmask (SIG_SETMASK, &set, NULL);
- } else {
- /* No workaround needed, unblock SIGCHLD by restoring signal mask. */
- sigprocmask (SIG_SETMASK, &set, NULL);
- result = nanosleep (&ts, &ts);
- }
+ /* We did block SIGCHLD, and old mask had no SIGCHLD bit.
+ IOW: we need to unblock SIGCHLD now. Do it. */
+ /* this sigprocmask call never fails, thus never updates errno,
+ and therefore we don't need to save/restore it. */
+ sigprocmask (SIG_SETMASK, &set, NULL); /* never fails */
}
- else
- result = nanosleep (&ts, &ts);
if (result != 0)
/* Round remaining time. */