Message ID | 20200313194827.4467-4-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | [v2,1/4] nptl: Move pthread_sigmask implementation to libc | expand |
Ping. On 13/03/2020 16:48, Adhemerval Zanella wrote: > The upper bits of the sigset_t s not fully initialized in the signal > mask calls that return information from kernel (sigprocmask, > sigpending, and pthread_sigmask), since the exported sigset_t size > (1024 bits) is larger than Linux support one (64 or 128 bits). > It might make sigisemptyset/sigorset/sigandset fail if the mask > is filled prior the call. > > This patch changes the internal signal function to handle up to > supported Linux signal number (_NSIG), the remaining bits are > untouched. > > Checked on x86_64-linux-gnu and i686-linux-gnu. > --- > nptl/Makefile | 2 +- > nptl/pthread_sigmask.c | 7 +- > nptl/tst-signal8.c | 62 ++++++++++++ > signal/Makefile | 1 + > signal/sigsetops.c | 12 +-- > signal/tst-sigisemptyset.c | 95 ++++++++++++++++++ > sysdeps/unix/sysv/linux/sigpending.c | 6 +- > sysdeps/unix/sysv/linux/sigsetops.h | 143 +++++++++++++-------------- > 8 files changed, 236 insertions(+), 92 deletions(-) > create mode 100644 nptl/tst-signal8.c > create mode 100644 signal/tst-sigisemptyset.c > > diff --git a/nptl/Makefile b/nptl/Makefile > index 4816fa254e..33fa03807e 100644 > --- a/nptl/Makefile > +++ b/nptl/Makefile > @@ -293,7 +293,7 @@ tests = tst-attr2 tst-attr3 tst-default-attr \ > tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \ > tst-flock1 tst-flock2 \ > tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \ > - tst-signal6 \ > + tst-signal6 tst-signal8 \ > tst-exec1 tst-exec2 tst-exec3 tst-exec4 tst-exec5 \ > tst-exit1 tst-exit2 tst-exit3 \ > tst-stdio1 tst-stdio2 \ > diff --git a/nptl/pthread_sigmask.c b/nptl/pthread_sigmask.c > index c6c6e83c08..d266d296c5 100644 > --- a/nptl/pthread_sigmask.c > +++ b/nptl/pthread_sigmask.c > @@ -29,12 +29,11 @@ __pthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask) > /* The only thing we have to make sure here is that SIGCANCEL and > SIGSETXID is not blocked. */ > if (newmask != NULL > - && (__builtin_expect (__sigismember (newmask, SIGCANCEL), 0) > - || __builtin_expect (__sigismember (newmask, SIGSETXID), 0))) > + && (__glibc_unlikely (__sigismember (newmask, SIGCANCEL)) > + || __glibc_unlikely (__sigismember (newmask, SIGSETXID)))) > { > local_newmask = *newmask; > - __sigdelset (&local_newmask, SIGCANCEL); > - __sigdelset (&local_newmask, SIGSETXID); > + __clear_internal_signals (&local_newmask); > newmask = &local_newmask; > } > > diff --git a/nptl/tst-signal8.c b/nptl/tst-signal8.c > new file mode 100644 > index 0000000000..9da7e5ef07 > --- /dev/null > +++ b/nptl/tst-signal8.c > @@ -0,0 +1,62 @@ > +/* Tests for sigisemptyset and pthread_sigmask. > + Copyright (C) 2020 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <signal.h> > + > +#include <support/check.h> > +#include <support/xthread.h> > + > +static void * > +tf (void *arg) > +{ > + { > + sigset_t set; > + sigemptyset (&set); > + TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0); > + TEST_COMPARE (sigisemptyset (&set), 1); > + } > + > + { > + sigset_t set; > + sigfillset (&set); > + TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0); > + TEST_COMPARE (sigisemptyset (&set), 1); > + } > + > + return NULL; > +} > + > +static int > +do_test (void) > +{ > + /* Ensure current SIG_BLOCK mask empty. */ > + { > + sigset_t set; > + sigemptyset (&set); > + TEST_COMPARE (sigprocmask (SIG_BLOCK, &set, 0), 0); > + } > + > + { > + pthread_t thr = xpthread_create (NULL, tf, NULL); > + xpthread_join (thr); > + } > + > + return 0; > +} > + > +#include <support/test-driver.c> > diff --git a/signal/Makefile b/signal/Makefile > index 37de438bba..f3c19e2992 100644 > --- a/signal/Makefile > +++ b/signal/Makefile > @@ -49,6 +49,7 @@ tests := tst-signal tst-sigset tst-sigsimple tst-raise tst-sigset2 \ > tst-sigwait-eintr tst-sigaction \ > tst-minsigstksz-1 tst-minsigstksz-2 tst-minsigstksz-3 \ > tst-minsigstksz-3a tst-minsigstksz-4 \ > + tst-sigisemptyset > > include ../Rules > > diff --git a/signal/sigsetops.c b/signal/sigsetops.c > index eb89e6780e..1165377876 100644 > --- a/signal/sigsetops.c > +++ b/signal/sigsetops.c > @@ -26,28 +26,28 @@ > > int > attribute_compat_text_section > -(__sigismember) (const __sigset_t *set, int sig) > +__sigismember_compat (const __sigset_t *set, int sig) > { > return __sigismember (set, sig); > } > -compat_symbol (libc, __sigismember, __sigismember, GLIBC_2_0); > +compat_symbol (libc, __sigismember_compat, __sigismember, GLIBC_2_0); > > int > attribute_compat_text_section > -(__sigaddset) (__sigset_t *set, int sig) > +__sigaddset_compat (__sigset_t *set, int sig) > { > __sigaddset (set, sig); > return 0; > } > -compat_symbol (libc, __sigaddset, __sigaddset, GLIBC_2_0); > +compat_symbol (libc, __sigaddset_compat, __sigaddset, GLIBC_2_0); > > int > attribute_compat_text_section > -(__sigdelset) (__sigset_t *set, int sig) > +__sigdelset_compat (__sigset_t *set, int sig) > { > __sigdelset (set, sig); > return 0; > } > -compat_symbol (libc, __sigdelset, __sigdelset, GLIBC_2_0); > +compat_symbol (libc, __sigdelset_compat, __sigdelset, GLIBC_2_0); > > #endif > diff --git a/signal/tst-sigisemptyset.c b/signal/tst-sigisemptyset.c > new file mode 100644 > index 0000000000..9ed95496f2 > --- /dev/null > +++ b/signal/tst-sigisemptyset.c > @@ -0,0 +1,95 @@ > +/* Tests for sigisemptyset/sigorset/sigandset. > + Copyright (C) 2020 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#include <signal.h> > + > +#include <support/check.h> > + > +static int > +do_test (void) > +{ > + { > + sigset_t set; > + sigemptyset (&set); > + TEST_COMPARE (sigisemptyset (&set), 1); > + } > + > + { > + sigset_t set; > + sigfillset (&set); > + TEST_COMPARE (sigisemptyset (&set), 0); > + } > + > + { > + sigset_t setfill, setempty, set; > + sigfillset (&setfill); > + sigemptyset (&setempty); > + > + sigorset (&set, &setfill, &setempty); > + TEST_COMPARE (sigisemptyset (&set), 0); > + > + sigandset (&set, &setfill, &setempty); > + TEST_COMPARE (sigisemptyset (&set), 1); > + } > + > + /* Ensure current SIG_BLOCK mask empty. */ > + { > + sigset_t set; > + sigemptyset (&set); > + TEST_COMPARE (sigprocmask (SIG_BLOCK, &set, 0), 0); > + } > + > + { > + sigset_t set; > + sigemptyset (&set); > + TEST_COMPARE (sigprocmask (SIG_BLOCK, 0, &set), 0); > + TEST_COMPARE (sigisemptyset (&set), 1); > + } > + > + { > + sigset_t set; > + sigfillset (&set); > + TEST_COMPARE (sigprocmask (SIG_BLOCK, 0, &set), 0); > + TEST_COMPARE (sigisemptyset (&set), 1); > + } > + > + /* Block all signals. */ > + { > + sigset_t set; > + sigfillset (&set); > + TEST_COMPARE (sigprocmask (SIG_BLOCK, &set, 0), 0); > + } > + > + { > + sigset_t set; > + sigemptyset (&set); > + TEST_COMPARE (sigpending (&set), 0); > + TEST_COMPARE (sigisemptyset (&set), 1); > + } > + > + { > + sigset_t set; > + sigfillset (&set); > + TEST_COMPARE (sigpending (&set), 0); > + TEST_COMPARE (sigisemptyset (&set), 1); > + } > + > + return 0; > +} > + > +#include <support/test-driver.c> > diff --git a/sysdeps/unix/sysv/linux/sigpending.c b/sysdeps/unix/sysv/linux/sigpending.c > index f6bedb5182..458a3cf99e 100644 > --- a/sysdeps/unix/sysv/linux/sigpending.c > +++ b/sysdeps/unix/sysv/linux/sigpending.c > @@ -15,13 +15,9 @@ > License along with the GNU C Library; if not, see > <https://www.gnu.org/licenses/>. */ > > -#include <errno.h> > #include <signal.h> > -#include <unistd.h> > - > #include <sysdep.h> > -#include <sys/syscall.h> > - > +#include <sigsetops.h> > > /* Change the set of blocked signals to SET, > wait until a signal arrives, and restore the set of blocked signals. */ > diff --git a/sysdeps/unix/sysv/linux/sigsetops.h b/sysdeps/unix/sysv/linux/sigsetops.h > index cb97c98b10..f6ca34c842 100644 > --- a/sysdeps/unix/sysv/linux/sigsetops.h > +++ b/sysdeps/unix/sysv/linux/sigsetops.h > @@ -28,81 +28,72 @@ > /* Return the word index for SIG. */ > # define __sigword(sig) (((sig) - 1) / (8 * sizeof (unsigned long int))) > > -# define __sigemptyset(set) \ > - (__extension__ ({ \ > - int __cnt = _SIGSET_NWORDS; \ > - sigset_t *__set = (set); \ > - while (--__cnt >= 0) \ > - __set->__val[__cnt] = 0; \ > - (void)0; \ > - })) > - > -# define __sigfillset(set) \ > - (__extension__ ({ \ > - int __cnt = _SIGSET_NWORDS; \ > - sigset_t *__set = (set); \ > - while (--__cnt >= 0) \ > - __set->__val[__cnt] = ~0UL; \ > - (void)0; \ > - })) > - > -# 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; \ > - })) > - > -# 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]); \ > - (void)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]); \ > - (void)0; \ > - })) > - > -/* These macros needn't check for a bogus signal number; > - error checking is done in the non-__ versions. */ > -# define __sigismember(set, sig) \ > - (__extension__ ({ \ > - unsigned long int __mask = __sigmask (sig); \ > - unsigned long int __word = __sigword (sig); \ > - (set)->__val[__word] & __mask ? 1 : 0; \ > - })) > - > -# define __sigaddset(set, sig) \ > - (__extension__ ({ \ > - unsigned long int __mask = __sigmask (sig); \ > - unsigned long int __word = __sigword (sig); \ > - (set)->__val[__word] |= __mask; \ > - (void)0; \ > - })) > - > -# define __sigdelset(set, sig) \ > - (__extension__ ({ \ > - unsigned long int __mask = __sigmask (sig); \ > - unsigned long int __word = __sigword (sig); \ > - (set)->__val[__word] &= ~__mask; \ > - (void)0; \ > - })) > +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) > + > +static inline void > +__sigemptyset (sigset_t *set) > +{ > + int cnt = __NSIG_WORDS; > + while (--cnt >= 0) > + set->__val[cnt] = 0; > +} > + > +static inline void > +__sigfillset (sigset_t *set) > +{ > + int cnt = __NSIG_WORDS; > + while (--cnt >= 0) > + set->__val[cnt] = ~0UL; > +} > + > +static inline int > +__sigisemptyset (const sigset_t *set) > +{ > + int cnt = __NSIG_WORDS; > + int ret = set->__val[--cnt]; > + while (ret == 0 && --cnt >= 0) > + ret = set->__val[cnt]; > + return ret == 0; > +} > + > +static inline void > +__sigandset (sigset_t *dest, const sigset_t *left, const sigset_t *right) > +{ > + int cnt = __NSIG_WORDS; > + while (--cnt >= 0) > + dest->__val[cnt] = left->__val[cnt] & right->__val[cnt]; > +} > + > +static inline void > +__sigorset (sigset_t *dest, const sigset_t *left, const sigset_t *right) > +{ > + int cnt = __NSIG_WORDS; > + while (--cnt >= 0) > + dest->__val[cnt] = left->__val[cnt] | right->__val[cnt]; > +} > + > +static inline int > +__sigismember (const sigset_t *set, int sig) > +{ > + unsigned long int mask = __sigmask (sig); > + unsigned long int word = __sigword (sig); > + return set->__val[word] & mask ? 1 : 0; > +} > + > +static inline void > +__sigaddset (sigset_t *set, int sig) > +{ > + unsigned long int mask = __sigmask (sig); > + unsigned long int word = __sigword (sig); > + set->__val[word] |= mask; > +} > + > +static inline void > +__sigdelset (sigset_t *set, int sig) > +{ > + unsigned long int mask = __sigmask (sig); > + unsigned long int word = __sigword (sig); > + set->__val[word] &= ~mask; > +} > > #endif /* bits/sigsetops.h */ >
* Adhemerval Zanella via Libc-alpha: > The upper bits of the sigset_t s not fully initialized in the signal > mask calls that return information from kernel (sigprocmask, > sigpending, and pthread_sigmask), since the exported sigset_t size > (1024 bits) is larger than Linux support one (64 or 128 bits). > It might make sigisemptyset/sigorset/sigandset fail if the mask > is filled prior the call. > > This patch changes the internal signal function to handle up to > supported Linux signal number (_NSIG), the remaining bits are > untouched. Sorry, I have trouble what the intended outcome of this change is. What is the expected behavior here? We have an overly large sigset_t, but only signal numbers from 0 to NSIG - 1 (inclusive) are valid in all function calls?
On 21/04/2020 09:53, Florian Weimer wrote: > * Adhemerval Zanella via Libc-alpha: > >> The upper bits of the sigset_t s not fully initialized in the signal >> mask calls that return information from kernel (sigprocmask, >> sigpending, and pthread_sigmask), since the exported sigset_t size >> (1024 bits) is larger than Linux support one (64 or 128 bits). >> It might make sigisemptyset/sigorset/sigandset fail if the mask >> is filled prior the call. >> >> This patch changes the internal signal function to handle up to >> supported Linux signal number (_NSIG), the remaining bits are >> untouched. > > Sorry, I have trouble what the intended outcome of this change is. > > What is the expected behavior here? We have an overly large sigset_t, > but only signal numbers from 0 to NSIG - 1 (inclusive) are valid in > all function calls? > The bug report link to a stackoverflow example, which simplified is: #define _GNU_SOURCE #include <stdio.h> #include <signal.h> int main (int argc, char *argv[]) { sigset_t set; sigfillset (&set); sigprocmask (SIG_BLOCK, NULL, &set); printf ("%d\n", sigisemptyset (&set)); return 0; } The main issue is GNU extensions sigisemptyset/sigorset/sigandset operates on full internal signal bits where kernel only updates up to _NSIG signals.
* Adhemerval Zanella: > On 21/04/2020 09:53, Florian Weimer wrote: >> * Adhemerval Zanella via Libc-alpha: >> >>> The upper bits of the sigset_t s not fully initialized in the signal >>> mask calls that return information from kernel (sigprocmask, >>> sigpending, and pthread_sigmask), since the exported sigset_t size >>> (1024 bits) is larger than Linux support one (64 or 128 bits). >>> It might make sigisemptyset/sigorset/sigandset fail if the mask >>> is filled prior the call. >>> >>> This patch changes the internal signal function to handle up to >>> supported Linux signal number (_NSIG), the remaining bits are >>> untouched. >> >> Sorry, I have trouble what the intended outcome of this change is. >> >> What is the expected behavior here? We have an overly large sigset_t, >> but only signal numbers from 0 to NSIG - 1 (inclusive) are valid in >> all function calls? >> > > The bug report link to a stackoverflow example, which simplified is: > > #define _GNU_SOURCE > #include <stdio.h> > #include <signal.h> > int > main (int argc, char *argv[]) > { > sigset_t set; > sigfillset (&set); > sigprocmask (SIG_BLOCK, NULL, &set); > printf ("%d\n", sigisemptyset (&set)); > return 0; > } > > The main issue is GNU extensions sigisemptyset/sigorset/sigandset > operates on full internal signal bits where kernel only updates > up to _NSIG signals. I get that, but what do you want to do to fix it? It's not entirely clear from the changes in the patch.
On 21/04/2020 10:14, Florian Weimer wrote: > * Adhemerval Zanella: > >> On 21/04/2020 09:53, Florian Weimer wrote: >>> * Adhemerval Zanella via Libc-alpha: >>> >>>> The upper bits of the sigset_t s not fully initialized in the signal >>>> mask calls that return information from kernel (sigprocmask, >>>> sigpending, and pthread_sigmask), since the exported sigset_t size >>>> (1024 bits) is larger than Linux support one (64 or 128 bits). >>>> It might make sigisemptyset/sigorset/sigandset fail if the mask >>>> is filled prior the call. >>>> >>>> This patch changes the internal signal function to handle up to >>>> supported Linux signal number (_NSIG), the remaining bits are >>>> untouched. >>> >>> Sorry, I have trouble what the intended outcome of this change is. >>> >>> What is the expected behavior here? We have an overly large sigset_t, >>> but only signal numbers from 0 to NSIG - 1 (inclusive) are valid in >>> all function calls? >>> >> >> The bug report link to a stackoverflow example, which simplified is: >> >> #define _GNU_SOURCE >> #include <stdio.h> >> #include <signal.h> >> int >> main (int argc, char *argv[]) >> { >> sigset_t set; >> sigfillset (&set); >> sigprocmask (SIG_BLOCK, NULL, &set); >> printf ("%d\n", sigisemptyset (&set)); >> return 0; >> } >> >> The main issue is GNU extensions sigisemptyset/sigorset/sigandset >> operates on full internal signal bits where kernel only updates >> up to _NSIG signals. > > I get that, but what do you want to do to fix it? > > It's not entirely clear from the changes in the patch. > Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS when manipulating sigset_t masks.
* Adhemerval Zanella: > On 21/04/2020 10:14, Florian Weimer wrote: > Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS > when manipulating sigset_t masks. Hmm. __NSIG_WORDS is defined like this: > +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) This gives us two words for _NSIG == 65. Is this correct?
On 21/04/2020 10:47, Florian Weimer wrote: > * Adhemerval Zanella: > >> On 21/04/2020 10:14, Florian Weimer wrote: >> Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS >> when manipulating sigset_t masks. > > Hmm. __NSIG_WORDS is defined like this: > >> +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) > > This gives us two words for _NSIG == 65. Is this correct? > Two words (32-bits) for all 64-bit architectures, except mips64 that defined _NSIG as 128 as requires 4 words. And 4 words for all 32-bit architectures and 8 for mips32.
* Adhemerval Zanella: > On 21/04/2020 10:47, Florian Weimer wrote: >> * Adhemerval Zanella: >> >>> On 21/04/2020 10:14, Florian Weimer wrote: >>> Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS >>> when manipulating sigset_t masks. >> >> Hmm. __NSIG_WORDS is defined like this: >> >>> +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) >> >> This gives us two words for _NSIG == 65. Is this correct? > > Two words (32-bits) for all 64-bit architectures, sizeof (unsigned long int) is 8 on 64-bit. 65 / (8 * 8) is 1. I assume that for _NSIG == 65, the signal numbers from 0 to 64 are all valid and can be manipulated using sigaddset etc. This suggests to me that we need three 32-bit longs and two 64-bit longs. Sorry, maybe I'm confused, I'm not feeling too well this week.
On 21/04/2020 11:07, Florian Weimer wrote: > * Adhemerval Zanella: > >> On 21/04/2020 10:47, Florian Weimer wrote: >>> * Adhemerval Zanella: >>> >>>> On 21/04/2020 10:14, Florian Weimer wrote: >>>> Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS >>>> when manipulating sigset_t masks. >>> >>> Hmm. __NSIG_WORDS is defined like this: >>> >>>> +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) >>> >>> This gives us two words for _NSIG == 65. Is this correct? >> >> Two words (32-bits) for all 64-bit architectures, > > sizeof (unsigned long int) is 8 on 64-bit. 65 / (8 * 8) is 1. > > I assume that for _NSIG == 65, the signal numbers from 0 to 64 are all > valid and can be manipulated using sigaddset etc. This suggests to me > that we need three 32-bit longs and two 64-bit longs. Indeed my mistake here, I was reading the value as the required words the maximum accessed index. > > Sorry, maybe I'm confused, I'm not feeling too well this week. > I hope you get better soon.
* Adhemerval Zanella: > On 21/04/2020 11:07, Florian Weimer wrote: >> * Adhemerval Zanella: >> >>> On 21/04/2020 10:47, Florian Weimer wrote: >>>> * Adhemerval Zanella: >>>> >>>>> On 21/04/2020 10:14, Florian Weimer wrote: >>>>> Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS >>>>> when manipulating sigset_t masks. >>>> >>>> Hmm. __NSIG_WORDS is defined like this: >>>> >>>>> +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) >>>> >>>> This gives us two words for _NSIG == 65. Is this correct? >>> >>> Two words (32-bits) for all 64-bit architectures, >> >> sizeof (unsigned long int) is 8 on 64-bit. 65 / (8 * 8) is 1. >> >> I assume that for _NSIG == 65, the signal numbers from 0 to 64 are all >> valid and can be manipulated using sigaddset etc. This suggests to me >> that we need three 32-bit longs and two 64-bit longs. > > Indeed my mistake here, I was reading the value as the required words > the maximum accessed index. Ahh. Please put also a comment into sigsetops.h how this is supposed to work, that is, which signal numbers are expected to be valid.
On 21/04/2020 11:35, Florian Weimer wrote: > * Adhemerval Zanella: > >> On 21/04/2020 11:07, Florian Weimer wrote: >>> * Adhemerval Zanella: >>> >>>> On 21/04/2020 10:47, Florian Weimer wrote: >>>>> * Adhemerval Zanella: >>>>> >>>>>> On 21/04/2020 10:14, Florian Weimer wrote: >>>>>> Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS >>>>>> when manipulating sigset_t masks. >>>>> >>>>> Hmm. __NSIG_WORDS is defined like this: >>>>> >>>>>> +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) >>>>> >>>>> This gives us two words for _NSIG == 65. Is this correct? >>>> >>>> Two words (32-bits) for all 64-bit architectures, >>> >>> sizeof (unsigned long int) is 8 on 64-bit. 65 / (8 * 8) is 1. >>> >>> I assume that for _NSIG == 65, the signal numbers from 0 to 64 are all >>> valid and can be manipulated using sigaddset etc. This suggests to me >>> that we need three 32-bit longs and two 64-bit longs. >> >> Indeed my mistake here, I was reading the value as the required words >> the maximum accessed index. > > Ahh. Please put also a comment into sigsetops.h how this is supposed > to work, that is, which signal numbers are expected to be valid. > Alright. I will do it.
On Apr 21 2020, Adhemerval Zanella via Libc-alpha wrote: > On 21/04/2020 11:07, Florian Weimer wrote: >> * Adhemerval Zanella: >> >>> On 21/04/2020 10:47, Florian Weimer wrote: >>>> * Adhemerval Zanella: >>>> >>>>> On 21/04/2020 10:14, Florian Weimer wrote: >>>>> Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS >>>>> when manipulating sigset_t masks. >>>> >>>> Hmm. __NSIG_WORDS is defined like this: >>>> >>>>> +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) >>>> >>>> This gives us two words for _NSIG == 65. Is this correct? >>> >>> Two words (32-bits) for all 64-bit architectures, >> >> sizeof (unsigned long int) is 8 on 64-bit. 65 / (8 * 8) is 1. >> >> I assume that for _NSIG == 65, the signal numbers from 0 to 64 are all >> valid and can be manipulated using sigaddset etc. This suggests to me >> that we need three 32-bit longs and two 64-bit longs. > > Indeed my mistake here, I was reading the value as the required words > the maximum accessed index. Note that signal numbers are 1-based, and bit 0 of a signal mask is for signal 1. Andreas.
* Andreas Schwab: > On Apr 21 2020, Adhemerval Zanella via Libc-alpha wrote: > >> On 21/04/2020 11:07, Florian Weimer wrote: >>> * Adhemerval Zanella: >>> >>>> On 21/04/2020 10:47, Florian Weimer wrote: >>>>> * Adhemerval Zanella: >>>>> >>>>>> On 21/04/2020 10:14, Florian Weimer wrote: >>>>>> Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS >>>>>> when manipulating sigset_t masks. >>>>> >>>>> Hmm. __NSIG_WORDS is defined like this: >>>>> >>>>>> +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) >>>>> >>>>> This gives us two words for _NSIG == 65. Is this correct? >>>> >>>> Two words (32-bits) for all 64-bit architectures, >>> >>> sizeof (unsigned long int) is 8 on 64-bit. 65 / (8 * 8) is 1. >>> >>> I assume that for _NSIG == 65, the signal numbers from 0 to 64 are all >>> valid and can be manipulated using sigaddset etc. This suggests to me >>> that we need three 32-bit longs and two 64-bit longs. >> >> Indeed my mistake here, I was reading the value as the required words >> the maximum accessed index. > > Note that signal numbers are 1-based, and bit 0 of a signal mask is for > signal 1. Right, all the more reason to spell this out in a top-level comment in the header file.
On 21/04/2020 14:28, Florian Weimer wrote: > * Andreas Schwab: > >> On Apr 21 2020, Adhemerval Zanella via Libc-alpha wrote: >> >>> On 21/04/2020 11:07, Florian Weimer wrote: >>>> * Adhemerval Zanella: >>>> >>>>> On 21/04/2020 10:47, Florian Weimer wrote: >>>>>> * Adhemerval Zanella: >>>>>> >>>>>>> On 21/04/2020 10:14, Florian Weimer wrote: >>>>>>> Only handle __NSIG_WORDS on linux sigsetopts.h instead of _SIGSET_NWORDS >>>>>>> when manipulating sigset_t masks. >>>>>> >>>>>> Hmm. __NSIG_WORDS is defined like this: >>>>>> >>>>>>> +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) >>>>>> >>>>>> This gives us two words for _NSIG == 65. Is this correct? >>>>> >>>>> Two words (32-bits) for all 64-bit architectures, >>>> >>>> sizeof (unsigned long int) is 8 on 64-bit. 65 / (8 * 8) is 1. >>>> >>>> I assume that for _NSIG == 65, the signal numbers from 0 to 64 are all >>>> valid and can be manipulated using sigaddset etc. This suggests to me >>>> that we need three 32-bit longs and two 64-bit longs. >>> >>> Indeed my mistake here, I was reading the value as the required words >>> the maximum accessed index. >> >> Note that signal numbers are 1-based, and bit 0 of a signal mask is for >> signal 1. > > Right, all the more reason to spell this out in a top-level comment in > the header file. > I have added the following comment on linux sigsetopts.h: /* Linux sig* functions only handle up to __NSIG_WORDS words instead of full _SIGSET_NWORDS sigset size. The signal numbers are 1-based, and bit 0 of a signal mask is for signal 1. */
On Apr 21 2020, Adhemerval Zanella wrote: > I have added the following comment on linux sigsetopts.h: > > /* Linux sig* functions only handle up to __NSIG_WORDS words instead of > full _SIGSET_NWORDS sigset size. The signal numbers are 1-based, and > bit 0 of a signal mask is for signal 1. */ You forgot to fix __NSIG_WORDS. Andreas.
On 21/04/2020 15:40, Andreas Schwab wrote: > On Apr 21 2020, Adhemerval Zanella wrote: > >> I have added the following comment on linux sigsetopts.h: >> >> /* Linux sig* functions only handle up to __NSIG_WORDS words instead of >> full _SIGSET_NWORDS sigset size. The signal numbers are 1-based, and >> bit 0 of a signal mask is for signal 1. */ > > You forgot to fix __NSIG_WORDS. Hum what exactly? I missing to see what might be missing here. Is the related to comment or the __NSIG_WORDS value itself?
On Apr 21 2020, Adhemerval Zanella wrote: > On 21/04/2020 15:40, Andreas Schwab wrote: >> On Apr 21 2020, Adhemerval Zanella wrote: >> >>> I have added the following comment on linux sigsetopts.h: >>> >>> /* Linux sig* functions only handle up to __NSIG_WORDS words instead of >>> full _SIGSET_NWORDS sigset size. The signal numbers are 1-based, and >>> bit 0 of a signal mask is for signal 1. */ >> >> You forgot to fix __NSIG_WORDS. > > Hum what exactly? I missing to see what might be missing here. Is the > related to comment or the __NSIG_WORDS value itself? The problem really is that _NSIG is bogus, it is actually the number of signals plus one. That doesn't change the value of __NSIG_WORDS, but if there would actually be 65 signals then __NSIG_WORDS would be too small. Note also that mips has the wrong value for __SIGRTMAX (it should be 128). Andreas.
* Andreas Schwab: > On Apr 21 2020, Adhemerval Zanella wrote: > >> On 21/04/2020 15:40, Andreas Schwab wrote: >>> On Apr 21 2020, Adhemerval Zanella wrote: >>> >>>> I have added the following comment on linux sigsetopts.h: >>>> >>>> /* Linux sig* functions only handle up to __NSIG_WORDS words instead of >>>> full _SIGSET_NWORDS sigset size. The signal numbers are 1-based, and >>>> bit 0 of a signal mask is for signal 1. */ >>> >>> You forgot to fix __NSIG_WORDS. >> >> Hum what exactly? I missing to see what might be missing here. Is the >> related to comment or the __NSIG_WORDS value itself? > > The problem really is that _NSIG is bogus, it is actually the number of > signals plus one. That doesn't change the value of __NSIG_WORDS, but if > there would actually be 65 signals then __NSIG_WORDS would be too small. > > Note also that mips has the wrong value for __SIGRTMAX (it should be > 128). Adhemerval, if you address this, please also fix these whitespace issue: +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) (Space before define (it's not nested) and after “unsigned long int”.)
> Il giorno 22 apr 2020, alle ore 05:32, Florian Weimer <fw@deneb.enyo.de> ha scritto: > > * Andreas Schwab: > >>> On Apr 21 2020, Adhemerval Zanella wrote: >>> >>> On 21/04/2020 15:40, Andreas Schwab wrote: >>>> On Apr 21 2020, Adhemerval Zanella wrote: >>>> >>>>> I have added the following comment on linux sigsetopts.h: >>>>> >>>>> /* Linux sig* functions only handle up to __NSIG_WORDS words instead of >>>>> full _SIGSET_NWORDS sigset size. The signal numbers are 1-based, and >>>>> bit 0 of a signal mask is for signal 1. */ >>>> >>>> You forgot to fix __NSIG_WORDS. >>> >>> Hum what exactly? I missing to see what might be missing here. Is the >>> related to comment or the __NSIG_WORDS value itself? >> >> The problem really is that _NSIG is bogus, it is actually the number of >> signals plus one. That doesn't change the value of __NSIG_WORDS, but if >> there would actually be 65 signals then __NSIG_WORDS would be too small. >> >> Note also that mips has the wrong value for __SIGRTMAX (it should be >> 128). > > Adhemerval, if you address this, please also fix these whitespace > issue: > > +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) > > (Space before define (it's not nested) and after “unsigned long int”.) I will check this out.
diff --git a/nptl/Makefile b/nptl/Makefile index 4816fa254e..33fa03807e 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -293,7 +293,7 @@ tests = tst-attr2 tst-attr3 tst-default-attr \ tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \ tst-flock1 tst-flock2 \ tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \ - tst-signal6 \ + tst-signal6 tst-signal8 \ tst-exec1 tst-exec2 tst-exec3 tst-exec4 tst-exec5 \ tst-exit1 tst-exit2 tst-exit3 \ tst-stdio1 tst-stdio2 \ diff --git a/nptl/pthread_sigmask.c b/nptl/pthread_sigmask.c index c6c6e83c08..d266d296c5 100644 --- a/nptl/pthread_sigmask.c +++ b/nptl/pthread_sigmask.c @@ -29,12 +29,11 @@ __pthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask) /* The only thing we have to make sure here is that SIGCANCEL and SIGSETXID is not blocked. */ if (newmask != NULL - && (__builtin_expect (__sigismember (newmask, SIGCANCEL), 0) - || __builtin_expect (__sigismember (newmask, SIGSETXID), 0))) + && (__glibc_unlikely (__sigismember (newmask, SIGCANCEL)) + || __glibc_unlikely (__sigismember (newmask, SIGSETXID)))) { local_newmask = *newmask; - __sigdelset (&local_newmask, SIGCANCEL); - __sigdelset (&local_newmask, SIGSETXID); + __clear_internal_signals (&local_newmask); newmask = &local_newmask; } diff --git a/nptl/tst-signal8.c b/nptl/tst-signal8.c new file mode 100644 index 0000000000..9da7e5ef07 --- /dev/null +++ b/nptl/tst-signal8.c @@ -0,0 +1,62 @@ +/* Tests for sigisemptyset and pthread_sigmask. + Copyright (C) 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <signal.h> + +#include <support/check.h> +#include <support/xthread.h> + +static void * +tf (void *arg) +{ + { + sigset_t set; + sigemptyset (&set); + TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0); + TEST_COMPARE (sigisemptyset (&set), 1); + } + + { + sigset_t set; + sigfillset (&set); + TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0); + TEST_COMPARE (sigisemptyset (&set), 1); + } + + return NULL; +} + +static int +do_test (void) +{ + /* Ensure current SIG_BLOCK mask empty. */ + { + sigset_t set; + sigemptyset (&set); + TEST_COMPARE (sigprocmask (SIG_BLOCK, &set, 0), 0); + } + + { + pthread_t thr = xpthread_create (NULL, tf, NULL); + xpthread_join (thr); + } + + return 0; +} + +#include <support/test-driver.c> diff --git a/signal/Makefile b/signal/Makefile index 37de438bba..f3c19e2992 100644 --- a/signal/Makefile +++ b/signal/Makefile @@ -49,6 +49,7 @@ tests := tst-signal tst-sigset tst-sigsimple tst-raise tst-sigset2 \ tst-sigwait-eintr tst-sigaction \ tst-minsigstksz-1 tst-minsigstksz-2 tst-minsigstksz-3 \ tst-minsigstksz-3a tst-minsigstksz-4 \ + tst-sigisemptyset include ../Rules diff --git a/signal/sigsetops.c b/signal/sigsetops.c index eb89e6780e..1165377876 100644 --- a/signal/sigsetops.c +++ b/signal/sigsetops.c @@ -26,28 +26,28 @@ int attribute_compat_text_section -(__sigismember) (const __sigset_t *set, int sig) +__sigismember_compat (const __sigset_t *set, int sig) { return __sigismember (set, sig); } -compat_symbol (libc, __sigismember, __sigismember, GLIBC_2_0); +compat_symbol (libc, __sigismember_compat, __sigismember, GLIBC_2_0); int attribute_compat_text_section -(__sigaddset) (__sigset_t *set, int sig) +__sigaddset_compat (__sigset_t *set, int sig) { __sigaddset (set, sig); return 0; } -compat_symbol (libc, __sigaddset, __sigaddset, GLIBC_2_0); +compat_symbol (libc, __sigaddset_compat, __sigaddset, GLIBC_2_0); int attribute_compat_text_section -(__sigdelset) (__sigset_t *set, int sig) +__sigdelset_compat (__sigset_t *set, int sig) { __sigdelset (set, sig); return 0; } -compat_symbol (libc, __sigdelset, __sigdelset, GLIBC_2_0); +compat_symbol (libc, __sigdelset_compat, __sigdelset, GLIBC_2_0); #endif diff --git a/signal/tst-sigisemptyset.c b/signal/tst-sigisemptyset.c new file mode 100644 index 0000000000..9ed95496f2 --- /dev/null +++ b/signal/tst-sigisemptyset.c @@ -0,0 +1,95 @@ +/* Tests for sigisemptyset/sigorset/sigandset. + Copyright (C) 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <signal.h> + +#include <support/check.h> + +static int +do_test (void) +{ + { + sigset_t set; + sigemptyset (&set); + TEST_COMPARE (sigisemptyset (&set), 1); + } + + { + sigset_t set; + sigfillset (&set); + TEST_COMPARE (sigisemptyset (&set), 0); + } + + { + sigset_t setfill, setempty, set; + sigfillset (&setfill); + sigemptyset (&setempty); + + sigorset (&set, &setfill, &setempty); + TEST_COMPARE (sigisemptyset (&set), 0); + + sigandset (&set, &setfill, &setempty); + TEST_COMPARE (sigisemptyset (&set), 1); + } + + /* Ensure current SIG_BLOCK mask empty. */ + { + sigset_t set; + sigemptyset (&set); + TEST_COMPARE (sigprocmask (SIG_BLOCK, &set, 0), 0); + } + + { + sigset_t set; + sigemptyset (&set); + TEST_COMPARE (sigprocmask (SIG_BLOCK, 0, &set), 0); + TEST_COMPARE (sigisemptyset (&set), 1); + } + + { + sigset_t set; + sigfillset (&set); + TEST_COMPARE (sigprocmask (SIG_BLOCK, 0, &set), 0); + TEST_COMPARE (sigisemptyset (&set), 1); + } + + /* Block all signals. */ + { + sigset_t set; + sigfillset (&set); + TEST_COMPARE (sigprocmask (SIG_BLOCK, &set, 0), 0); + } + + { + sigset_t set; + sigemptyset (&set); + TEST_COMPARE (sigpending (&set), 0); + TEST_COMPARE (sigisemptyset (&set), 1); + } + + { + sigset_t set; + sigfillset (&set); + TEST_COMPARE (sigpending (&set), 0); + TEST_COMPARE (sigisemptyset (&set), 1); + } + + return 0; +} + +#include <support/test-driver.c> diff --git a/sysdeps/unix/sysv/linux/sigpending.c b/sysdeps/unix/sysv/linux/sigpending.c index f6bedb5182..458a3cf99e 100644 --- a/sysdeps/unix/sysv/linux/sigpending.c +++ b/sysdeps/unix/sysv/linux/sigpending.c @@ -15,13 +15,9 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ -#include <errno.h> #include <signal.h> -#include <unistd.h> - #include <sysdep.h> -#include <sys/syscall.h> - +#include <sigsetops.h> /* Change the set of blocked signals to SET, wait until a signal arrives, and restore the set of blocked signals. */ diff --git a/sysdeps/unix/sysv/linux/sigsetops.h b/sysdeps/unix/sysv/linux/sigsetops.h index cb97c98b10..f6ca34c842 100644 --- a/sysdeps/unix/sysv/linux/sigsetops.h +++ b/sysdeps/unix/sysv/linux/sigsetops.h @@ -28,81 +28,72 @@ /* Return the word index for SIG. */ # define __sigword(sig) (((sig) - 1) / (8 * sizeof (unsigned long int))) -# define __sigemptyset(set) \ - (__extension__ ({ \ - int __cnt = _SIGSET_NWORDS; \ - sigset_t *__set = (set); \ - while (--__cnt >= 0) \ - __set->__val[__cnt] = 0; \ - (void)0; \ - })) - -# define __sigfillset(set) \ - (__extension__ ({ \ - int __cnt = _SIGSET_NWORDS; \ - sigset_t *__set = (set); \ - while (--__cnt >= 0) \ - __set->__val[__cnt] = ~0UL; \ - (void)0; \ - })) - -# 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; \ - })) - -# 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]); \ - (void)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]); \ - (void)0; \ - })) - -/* These macros needn't check for a bogus signal number; - error checking is done in the non-__ versions. */ -# define __sigismember(set, sig) \ - (__extension__ ({ \ - unsigned long int __mask = __sigmask (sig); \ - unsigned long int __word = __sigword (sig); \ - (set)->__val[__word] & __mask ? 1 : 0; \ - })) - -# define __sigaddset(set, sig) \ - (__extension__ ({ \ - unsigned long int __mask = __sigmask (sig); \ - unsigned long int __word = __sigword (sig); \ - (set)->__val[__word] |= __mask; \ - (void)0; \ - })) - -# define __sigdelset(set, sig) \ - (__extension__ ({ \ - unsigned long int __mask = __sigmask (sig); \ - unsigned long int __word = __sigword (sig); \ - (set)->__val[__word] &= ~__mask; \ - (void)0; \ - })) +# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int ))) + +static inline void +__sigemptyset (sigset_t *set) +{ + int cnt = __NSIG_WORDS; + while (--cnt >= 0) + set->__val[cnt] = 0; +} + +static inline void +__sigfillset (sigset_t *set) +{ + int cnt = __NSIG_WORDS; + while (--cnt >= 0) + set->__val[cnt] = ~0UL; +} + +static inline int +__sigisemptyset (const sigset_t *set) +{ + int cnt = __NSIG_WORDS; + int ret = set->__val[--cnt]; + while (ret == 0 && --cnt >= 0) + ret = set->__val[cnt]; + return ret == 0; +} + +static inline void +__sigandset (sigset_t *dest, const sigset_t *left, const sigset_t *right) +{ + int cnt = __NSIG_WORDS; + while (--cnt >= 0) + dest->__val[cnt] = left->__val[cnt] & right->__val[cnt]; +} + +static inline void +__sigorset (sigset_t *dest, const sigset_t *left, const sigset_t *right) +{ + int cnt = __NSIG_WORDS; + while (--cnt >= 0) + dest->__val[cnt] = left->__val[cnt] | right->__val[cnt]; +} + +static inline int +__sigismember (const sigset_t *set, int sig) +{ + unsigned long int mask = __sigmask (sig); + unsigned long int word = __sigword (sig); + return set->__val[word] & mask ? 1 : 0; +} + +static inline void +__sigaddset (sigset_t *set, int sig) +{ + unsigned long int mask = __sigmask (sig); + unsigned long int word = __sigword (sig); + set->__val[word] |= mask; +} + +static inline void +__sigdelset (sigset_t *set, int sig) +{ + unsigned long int mask = __sigmask (sig); + unsigned long int word = __sigword (sig); + set->__val[word] &= ~mask; +} #endif /* bits/sigsetops.h */