strace/tests/sigaction.c
Dmitry V. Levin 38593e942a Rewrite signal mask decoding without sigset_t
The sigset_t provided by libc is not quite convenient.
In glibc, sigset_t is an array with space for 1024 bits, which is much
more than required: all architectures supported by Linux have only 64
signals except MIPS, which has 128.
In bionic libc, LP32 sigset_t is only 4 bytes long, which is less than
necessary.

With this change, signal mask is decoded without use of intermediate
sigset_t structure, which saves us some cpu cycles in case of glibc with
its inflated sigset_t, and enables build with libcs where sigset_t is
broken.

Old implementation used to check each signal number in the given signal
mask twice using sigismember().
New implementation is based on popcount and next_set_bit() so it's
noticeably faster.

* configure.ac: Check for __builtin_popcount.
* signal.c: Ensure that NSIG >= 32.
(sprintsigmask, sprintsigmask_long, printsigmask): Remove.
(popcount32, sprintsigmask_n): New functions.
(tprintsigmask_addr, sprintsigmask_val, tprintsigmask_val): New macros.
(print_sigset_addr_len, sys_sigsetmask, sys_sigreturn, sys_siggetmask,
sys_sigsuspend, sys_sigprocmask, decode_new_sigaction): Update to use
new signal mask decoding interface.
* tests/sigaction.c (main): Add a test with almost filled signal mask.
* tests/sigaction.awk: Update.
2014-02-27 00:28:39 +00:00

41 lines
794 B
C

#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
static void handle_signal(int no)
{
_exit(128 + no);
}
int
main(void)
{
struct sigaction sa, sa0;
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGHUP);
sigaddset(&sa.sa_mask, SIGINT);
sa.sa_flags = SA_RESTART;
assert(!sigaction(SIGUSR2, &sa, &sa0));
sa.sa_handler = handle_signal;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGQUIT);
sigaddset(&sa.sa_mask, SIGTERM);
sa.sa_flags = SA_SIGINFO;
assert(!sigaction(SIGUSR2, &sa, &sa0));
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
assert(!sigaction(SIGUSR2, &sa, &sa0));
sigfillset(&sa.sa_mask);
sigdelset(&sa.sa_mask, SIGHUP);
assert(!sigaction(SIGUSR2, &sa, &sa0));
return 0;
}