From 0e4d4dd89170d47a662f1cd0de1b4f3a5dbc1f2d Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 1 Dec 2008 15:31:22 +0000 Subject: optimize signal mask ops. comment out "impossible" errors text data bss dec hex filename - 1179 13 2 1194 4aa libc/misc/syslog/syslog.o + 1165 13 2 1180 49c libc/misc/syslog/syslog.o - 435 4 0 439 1b7 libc/pwd_grp/lckpwdf.o + 393 4 0 397 18d libc/pwd_grp/lckpwdf.o - 38 0 0 38 26 libc/signal/sigandset.o + 32 0 0 32 20 libc/signal/sigandset.o - 63 0 0 63 3f libc/signal/sigblock.o + 56 0 0 56 38 libc/signal/sigblock.o - 22 0 0 22 16 libc/signal/sigempty.o + 20 0 0 20 14 libc/signal/sigempty.o - 25 0 0 25 19 libc/signal/sigfillset.o + 20 0 0 20 14 libc/signal/sigfillset.o - 34 0 0 34 22 libc/signal/sigisempty.o + 16 0 0 16 10 libc/signal/sigisempty.o - 38 0 0 38 26 libc/signal/sigorset.o + 32 0 0 32 20 libc/signal/sigorset.o - 119 0 0 119 77 libc/signal/sigpause.o + 113 0 0 113 71 libc/signal/sigpause.o - 215 0 0 215 d7 libc/signal/sigset.o + 211 0 0 211 d3 libc/signal/sigset.o - 63 0 0 63 3f libc/signal/sigsetmask.o + 56 0 0 56 38 libc/signal/sigsetmask.o - 194 0 1 195 c3 libc/stdlib/abort.o + 183 0 1 184 b8 libc/stdlib/abort.o - 323 0 0 323 143 libc/unistd/sleep.o + 309 0 0 309 135 libc/unistd/sleep.o --- libc/misc/syslog/syslog.c | 7 +- libc/pwd_grp/lckpwdf.c | 42 ++++++----- libc/signal/sigempty.c | 4 +- libc/signal/sigfillset.c | 4 +- libc/signal/sigset-cvt-mask.h | 4 +- libc/signal/sigwait.c | 4 +- libc/sysdeps/linux/alpha/sigprocmask.c | 4 +- libc/sysdeps/linux/common/bits/sigset.h | 127 +++++++++++++++++++++----------- libc/sysdeps/linux/common/ssp.c | 4 +- 9 files changed, 127 insertions(+), 73 deletions(-) (limited to 'libc') diff --git a/libc/misc/syslog/syslog.c b/libc/misc/syslog/syslog.c index ccc71ddec..32fcd1f2b 100644 --- a/libc/misc/syslog/syslog.c +++ b/libc/misc/syslog/syslog.c @@ -207,11 +207,11 @@ vsyslog(int pri, const char *fmt, va_list ap) memset(&action, 0, sizeof(action)); action.sa_handler = closelog_intern; - sigemptyset(&action.sa_mask); /* TODO: memset already zeroed it out! */ + /* __sigemptyset(&action.sa_mask); - memset already did it */ /* Only two errors are possible for sigaction: * EFAULT (bad address of &oldaction) and EINVAL (invalid signo) * none of which can happen here. */ - /*int sigpipe =*/ sigaction(SIGPIPE, &action, &oldaction); + sigaction(SIGPIPE, &action, &oldaction); saved_errno = errno; @@ -317,8 +317,7 @@ vsyslog(int pri, const char *fmt, va_list ap) getout: __UCLIBC_MUTEX_UNLOCK(mylock); - /*if (sigpipe == 0)*/ - sigaction(SIGPIPE, &oldaction, (struct sigaction *) NULL); + sigaction(SIGPIPE, &oldaction, NULL); } libc_hidden_def(vsyslog) diff --git a/libc/pwd_grp/lckpwdf.c b/libc/pwd_grp/lckpwdf.c index a9601d45d..41987ca5d 100644 --- a/libc/pwd_grp/lckpwdf.c +++ b/libc/pwd_grp/lckpwdf.c @@ -39,11 +39,9 @@ /* libc_hidden_proto(sigemptyset) */ /* libc_hidden_proto(alarm) */ -/* How long to wait for getting the lock before returning with an - error. */ +/* How long to wait for getting the lock before returning with an error. */ #define TIMEOUT 15 /* sec */ - /* File descriptor for lock file. */ static int lock_fd = -1; @@ -51,7 +49,6 @@ static int lock_fd = -1; #include __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); - /* Prototypes for local functions. */ static void noop_handler (int __sig); @@ -82,33 +79,39 @@ lckpwdf (void) } /* Make sure file gets correctly closed when process finished. */ - flags = fcntl (lock_fd, F_GETFD, 0); + flags = fcntl (lock_fd, F_GETFD); +#if 0 /* never fails */ if (flags == -1) { /* Cannot get file flags. */ close(lock_fd); lock_fd = -1; goto DONE; } - flags |= FD_CLOEXEC; /* Close on exit. */ +#endif + flags |= FD_CLOEXEC; +#if 1 + fcntl (lock_fd, F_SETFD, flags); +#else /* never fails */ if (fcntl (lock_fd, F_SETFD, flags) < 0) { /* Cannot set new flags. */ close(lock_fd); lock_fd = -1; goto DONE; } - +#endif /* Now we have to get exclusive write access. Since multiple process could try this we won't stop when it first fails. Instead we set a timeout for the system call. Once the timer expires it is likely that there are some problems which cannot be - resolved by waiting. + resolved by waiting. (sa_flags have no SA_RESTART. Thus SIGALRM + will EINTR fcntl(F_SETLKW) It is important that we don't change the signal state. We must restore the old signal behaviour. */ memset (&new_act, '\0', sizeof (struct sigaction)); new_act.sa_handler = noop_handler; - sigfillset (&new_act.sa_mask); - new_act.sa_flags = 0ul; + __sigfillset (&new_act.sa_mask); + /* new_act.sa_flags = 0; */ /* Install new action handler for alarm and save old. */ if (sigaction (SIGALRM, &new_act, &saved_act) < 0) { @@ -119,34 +122,35 @@ lckpwdf (void) } /* Now make sure the alarm signal is not blocked. */ - sigemptyset (&new_set); + __sigemptyset (&new_set); sigaddset (&new_set, SIGALRM); +#if 1 + sigprocmask (SIG_UNBLOCK, &new_set, &saved_set); +#else /* never fails */ if (sigprocmask (SIG_UNBLOCK, &new_set, &saved_set) < 0) { sigaction (SIGALRM, &saved_act, NULL); close(lock_fd); lock_fd = -1; goto DONE; } +#endif /* Start timer. If we cannot get the lock in the specified time we get a signal. */ alarm (TIMEOUT); /* Try to get the lock. */ - memset (&fl, '\0', sizeof (struct flock)); - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; + memset (&fl, '\0', sizeof (fl)); + if (F_WRLCK) + fl.l_type = F_WRLCK; + if (SEEK_SET) + fl.l_whence = SEEK_SET; result = fcntl (lock_fd, F_SETLKW, &fl); /* Clear alarm. */ alarm (0); - /* Restore old set of handled signals. We don't need to know - about the current one.*/ sigprocmask (SIG_SETMASK, &saved_set, NULL); - - /* Restore old action handler for alarm. We don't need to know - about the current one. */ sigaction (SIGALRM, &saved_act, NULL); if (result < 0) { diff --git a/libc/signal/sigempty.c b/libc/signal/sigempty.c index 96260fb92..56b62bc65 100644 --- a/libc/signal/sigempty.c +++ b/libc/signal/sigempty.c @@ -26,13 +26,15 @@ /* libc_hidden_proto(sigemptyset) */ int sigemptyset (sigset_t *set) { +#if 0 /* is it really required by standards?! */ if (set == NULL) { __set_errno (EINVAL); return -1; } +#endif - memset (set, 0, sizeof (sigset_t)); + __sigemptyset (set); return 0; } diff --git a/libc/signal/sigfillset.c b/libc/signal/sigfillset.c index 2f8fb8138..b0b093032 100644 --- a/libc/signal/sigfillset.c +++ b/libc/signal/sigfillset.c @@ -27,13 +27,15 @@ int sigfillset (sigset_t *set) { +#if 0 /* is it really required by standards?! */ if (set == NULL) { __set_errno (EINVAL); return -1; } +#endif - memset (set, 0xff, sizeof (sigset_t)); + __sigfillset (set); /* If the implementation uses a cancellation signal don't set the bit. */ #ifdef SIGCANCEL diff --git a/libc/signal/sigset-cvt-mask.h b/libc/signal/sigset-cvt-mask.h index 83be40a51..76dd01c7e 100644 --- a/libc/signal/sigset-cvt-mask.h +++ b/libc/signal/sigset-cvt-mask.h @@ -22,7 +22,9 @@ static __inline__ void __attribute__ ((unused)) sigset_set_old_mask (sigset_t *set, int mask) { - if (_SIGSET_NWORDS > 1) + if (_SIGSET_NWORDS == 2) /* typical */ + set->__val[1] = 0; + if (_SIGSET_NWORDS > 2) memset(set, 0, sizeof(*set)); set->__val[0] = (unsigned int) mask; } diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c index 9b2c32079..64a889f7b 100644 --- a/libc/signal/sigwait.c +++ b/libc/signal/sigwait.c @@ -56,12 +56,12 @@ int __sigwait (const sigset_t *set, int *sig) int this; /* Prepare set. */ - sigfillset (&tmp_mask); + __sigfillset (&tmp_mask); /* Unblock all signals in the SET and register our nice handler. */ action.sa_handler = ignore_signal; action.sa_flags = 0; - sigfillset (&action.sa_mask); /* Block all signals for handler. */ + __sigfillset (&action.sa_mask); /* Block all signals for handler. */ /* Make sure we recognize error conditions by setting WAS_SIG to a value which does not describe a legal signal number. */ diff --git a/libc/sysdeps/linux/alpha/sigprocmask.c b/libc/sysdeps/linux/alpha/sigprocmask.c index 5728418b5..e143f61e3 100644 --- a/libc/sysdeps/linux/alpha/sigprocmask.c +++ b/libc/sysdeps/linux/alpha/sigprocmask.c @@ -51,7 +51,9 @@ sigprocmask (int how, const sigset_t *set, sigset_t *oset) if (oset) { - if (_SIGSET_NWORDS > 1) + if (_SIGSET_NWORDS == 2) /* typical */ + oset->__val[1] = 0; + if (_SIGSET_NWORDS > 2) memset(oset, 0, sizeof(*oset)); oset->__val[0] = result; } diff --git a/libc/sysdeps/linux/common/bits/sigset.h b/libc/sysdeps/linux/common/bits/sigset.h index 14497671d..964b09178 100644 --- a/libc/sysdeps/linux/common/bits/sigset.h +++ b/libc/sysdeps/linux/common/bits/sigset.h @@ -30,10 +30,9 @@ typedef int __sig_atomic_t; */ # define _SIGSET_NWORDS (64 / (8 * sizeof (unsigned long int))) -typedef struct - { - unsigned long int __val[_SIGSET_NWORDS]; - } __sigset_t; +typedef struct { + unsigned long int __val[_SIGSET_NWORDS]; +} __sigset_t; #endif @@ -59,47 +58,91 @@ typedef struct /* Return the word index for SIG. */ # define __sigword(sig) ((unsigned)((sig) - 1) / (8 * sizeof (unsigned long int))) +/* gcc 4.3.1 is not clever enough to optimize for _SIGSET_NWORDS == 1 and 2, + * which are about the only values which can be there */ + # if defined __GNUC__ && __GNUC__ >= 2 # define __sigemptyset(set) \ - (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ - sigset_t *__set = (set); \ - while (--__cnt >= 0) __set->__val[__cnt] = 0; \ - 0; })) +(__extension__ ({ \ + sigset_t *__set = (set); \ + if (_SIGSET_NWORDS <= 2) { \ + __set->__val[0] = 0; \ + if (_SIGSET_NWORDS == 2) \ + __set->__val[1] = 0; \ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + while (--__cnt >= 0) __set->__val[__cnt] = 0; \ + } \ + 0; \ +})) # define __sigfillset(set) \ - (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ - sigset_t *__set = (set); \ - while (--__cnt >= 0) __set->__val[__cnt] = ~0UL; \ - 0; })) +(__extension__ ({ \ + sigset_t *__set = (set); \ + if (_SIGSET_NWORDS <= 2) { \ + __set->__val[0] = ~0UL; \ + if (_SIGSET_NWORDS == 2) \ + __set->__val[1] = ~0UL; \ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + while (--__cnt >= 0) __set->__val[__cnt] = ~0UL; \ + } \ + 0; \ +})) # ifdef __USE_GNU /* The POSIX does not specify for handling the whole signal set in one command. This is often wanted and so we define three more functions here. */ # define __sigisemptyset(set) \ - (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ - const sigset_t *__set = (set); \ - int __ret = __set->__val[--__cnt]; \ - while (!__ret && --__cnt >= 0) \ - __ret = __set->__val[__cnt]; \ - __ret == 0; })) +(__extension__ ({ \ + long __ret; \ + const sigset_t *__set = (set); \ + if (_SIGSET_NWORDS == 1) { \ + __ret = __set->__val[0]; \ + } else if (_SIGSET_NWORDS == 2) { \ + __ret = __set->__val[0] | __set->__val[1]; \ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + __ret = __set->__val[--__cnt]; \ + while (!__ret && --__cnt >= 0) \ + __ret = __set->__val[__cnt]; \ + } \ + __ret == 0; \ +})) # define __sigandset(dest, left, right) \ - (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ - sigset_t *__dest = (dest); \ - const sigset_t *__left = (left); \ - const sigset_t *__right = (right); \ - while (--__cnt >= 0) \ - __dest->__val[__cnt] = (__left->__val[__cnt] \ - & __right->__val[__cnt]); \ - 0; })) +(__extension__ ({ \ + sigset_t *__dest = (dest); \ + const sigset_t *__left = (left); \ + const sigset_t *__right = (right); \ + if (_SIGSET_NWORDS <= 2) { \ + __dest->__val[0] = __left->__val[0] & __right->__val[0];\ + if (_SIGSET_NWORDS == 2) \ + __dest->__val[1] = __left->__val[1] & __right->__val[1];\ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + while (--__cnt >= 0) \ + __dest->__val[__cnt] = (__left->__val[__cnt] \ + & __right->__val[__cnt]); \ + } \ + 0; \ +})) # define __sigorset(dest, left, right) \ - (__extension__ ({ int __cnt = _SIGSET_NWORDS; \ - sigset_t *__dest = (dest); \ - const sigset_t *__left = (left); \ - const sigset_t *__right = (right); \ - while (--__cnt >= 0) \ - __dest->__val[__cnt] = (__left->__val[__cnt] \ - | __right->__val[__cnt]); \ - 0; })) +(__extension__ ({ \ + sigset_t *__dest = (dest); \ + const sigset_t *__left = (left); \ + const sigset_t *__right = (right); \ + if (_SIGSET_NWORDS <= 2) { \ + __dest->__val[0] = __left->__val[0] | __right->__val[0];\ + if (_SIGSET_NWORDS == 2) \ + __dest->__val[1] = __left->__val[1] | __right->__val[1];\ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + while (--__cnt >= 0) \ + __dest->__val[__cnt] = (__left->__val[__cnt] \ + | __right->__val[__cnt]); \ + } \ + 0; \ +})) # endif # endif @@ -114,14 +157,14 @@ extern int __sigdelset (__sigset_t *, int); libc_hidden_proto(__sigdelset) # ifdef __USE_EXTERN_INLINES -# define __SIGSETFN(NAME, BODY, CONST) \ - _EXTERN_INLINE int \ - NAME (CONST __sigset_t *__set, int __sig) \ - { \ - unsigned long int __mask = __sigmask (__sig); \ - unsigned long int __word = __sigword (__sig); \ - return BODY; \ - } +# define __SIGSETFN(NAME, BODY, CONST) \ +_EXTERN_INLINE int \ +NAME (CONST __sigset_t *__set, int __sig) \ +{ \ + unsigned long int __mask = __sigmask (__sig); \ + unsigned long int __word = __sigword (__sig); \ + return BODY; \ +} __SIGSETFN (__sigismember, (__set->__val[__word] & __mask) ? 1 : 0, __const) __SIGSETFN (__sigaddset, ((__set->__val[__word] |= __mask), 0), ) diff --git a/libc/sysdeps/linux/common/ssp.c b/libc/sysdeps/linux/common/ssp.c index c244c6220..fadf6077b 100644 --- a/libc/sysdeps/linux/common/ssp.c +++ b/libc/sysdeps/linux/common/ssp.c @@ -51,14 +51,14 @@ static void block_signals(void) struct sigaction sa; sigset_t mask; - sigfillset(&mask); + __sigfillset(&mask); sigdelset(&mask, SSP_SIGTYPE); /* Block all signal handlers */ sigprocmask(SIG_BLOCK, &mask, NULL); /* except SSP_SIGTYPE */ /* Make the default handler associated with the signal handler */ memset(&sa, 0, sizeof(sa)); - sigfillset(&sa.sa_mask); /* Block all signals */ + __sigfillset(&sa.sa_mask); /* Block all signals */ /* sa.sa_flags = 0; - memset did it */ if (SIG_DFL) /* if it's constant zero, it's already done */ sa.sa_handler = SIG_DFL; -- cgit v1.2.3