[git commit master 1/1] sleep: check "SIGCHLD is SIG_IGN'ed" first. Saves two syscalls in common case

Denys Vlasenko dvlasenk at redhat.com
Fri Oct 22 13:24:13 UTC 2010


commit: http://git.uclibc.org/uClibc/commit/?id=62fb840ea00d9d10446959d290d93a45065220f4
branch: http://git.uclibc.org/uClibc/commit/?id=refs/heads/master

    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 at redhat.com>
---
 libc/unistd/sleep.c |   40 ++++++++++++++++++----------------------
 1 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/libc/unistd/sleep.c b/libc/unistd/sleep.c
index 55e6463..481e635 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.  */
-- 
1.7.1



More information about the uClibc-cvs mailing list