diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2014-02-26 16:51:28 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2014-02-27 00:28:39 +0000 |
commit | 38593e942ad4b16b2c3c43ea521167368771cbfb (patch) | |
tree | 1d495359a95b84a1ffebddd5c4ad19a5fcd1f121 /tests | |
parent | d354130b3ac060051b55cda46c45ab5f5574548d (diff) | |
download | strace-38593e942ad4b16b2c3c43ea521167368771cbfb.tar.gz |
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.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/sigaction.awk | 22 | ||||
-rw-r--r-- | tests/sigaction.c | 12 |
2 files changed, 26 insertions, 8 deletions
diff --git a/tests/sigaction.awk b/tests/sigaction.awk index 2c4eab687..5bd056865 100644 --- a/tests/sigaction.awk +++ b/tests/sigaction.awk @@ -8,6 +8,11 @@ # the 1st is for any architecture with SA_RESTORER, including SPARC; # the 2nd is for any architecture without SA_RESTORER, including ALPHA. +BEGIN { + lines = 5 + fail = 0 +} + # Test 1. NR == 1 && /^rt_sigaction\(SIGUSR2, {SIG_IGN, \[HUP INT\], SA_RESTORER\|SA_RESTART, 0x[0-9a-f]+}, {SIG_DFL, \[\], 0}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next} NR == 1 && /^rt_sigaction\(SIGUSR2, {SIG_IGN, \[HUP INT\], SA_RESTART}, {SIG_DFL, \[\], 0}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next} @@ -20,17 +25,26 @@ NR == 2 && /^rt_sigaction\(SIGUSR2, {0x[0-9a-f]+, \[QUIT TERM\], SA_SIGINFO}, {S NR == 3 && /^rt_sigaction\(SIGUSR2, {SIG_DFL, \[\], SA_RESTORER, 0x[0-9a-f]+}, {0x[0-9a-f]+, \[QUIT TERM\], SA_RESTORER\|SA_SIGINFO, 0x[0-9a-f]+}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next} NR == 3 && /^rt_sigaction\(SIGUSR2, {SIG_DFL, \[\], 0}, {0x[0-9a-f]+, \[QUIT TERM\], SA_SIGINFO}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next} +# Test 4. +NR == 4 && /^rt_sigaction\(SIGUSR2, {SIG_DFL, ~\[HUP( ((RT|SIGRT)[^] ]+|[3-9][0-9]|1[0-9][0-9]))*\], SA_RESTORER, 0x[0-9a-f]+}, {SIG_DFL, \[\], SA_RESTORER, 0x[0-9a-f]+}, (0x[0-9a-f]+, )?(4|8|16)\) = 0$/ {next} +NR == 4 && /^rt_sigaction\(SIGUSR2, {SIG_DFL, ~\[HUP( ((RT|SIGRT)[^] ]+|[3-9][0-9]|1[0-9][0-9]))*\], 0}, {SIG_DFL, \[\], 0}, (4|8|16)(, 0x[0-9a-f]+)?\) = 0$/ {next} + # The last line. -NR == 4 && /^\+\+\+ exited with 0 \+\+\+$/ {next} +NR == lines && /^\+\+\+ exited with 0 \+\+\+$/ {next} { print "Line " NR " does not match: " $0 - exit 1 + fail=1 } END { - if (NR != 4) { - print "Expected 4 lines, found " NR " line(s)." + if (NR != lines) { + print "Expected " lines " lines, found " NR " line(s)." + print "" + exit 1 + } + if (fail) { + print "" exit 1 } } diff --git a/tests/sigaction.c b/tests/sigaction.c index 82666f9e5..b5f19b561 100644 --- a/tests/sigaction.c +++ b/tests/sigaction.c @@ -11,26 +11,30 @@ static void handle_signal(int no) int main(void) { - struct sigaction sa, sa1, sa2, sa3; + 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, &sa1)); + 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, &sa2)); + assert(!sigaction(SIGUSR2, &sa, &sa0)); sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - assert(!sigaction(SIGUSR2, &sa, &sa3)); + assert(!sigaction(SIGUSR2, &sa, &sa0)); + + sigfillset(&sa.sa_mask); + sigdelset(&sa.sa_mask, SIGHUP); + assert(!sigaction(SIGUSR2, &sa, &sa0)); return 0; } |