From 62fb840ea00d9d10446959d290d93a45065220f4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 22 Oct 2010 15:22:40 +0200 Subject: 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 --- libc/unistd/sleep.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'libc/unistd') 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. */ -- cgit v1.2.3