diff mbox series

[v5,04/13] linux: Fix __NSIG_WORDS and add __NSIG_BYTES

Message ID 20200619134352.297146-4-adhemerval.zanella@linaro.org
State Committed
Headers show
Series [v5,01/13] signal: Add signum-{generic,arch}.h | expand

Commit Message

Adhemerval Zanella June 19, 2020, 1:43 p.m. UTC
The __NSIG_WORDS value is based on minimum number of words to hold
the maximum number of signal supported by the architecture.  Maximum
number of signals non multiple of word is rounded up.

This patch also adds __NSIG_BYTES, which is the number of bytes
required to represent the support number of signals.  It is used on
syscall which takes a sigset_t.

Checked on x86_64-linux-gnu and i686-linux-gnu.
---
 include/signal.h                           |  2 ++
 nptl/nptl-init.c                           |  2 +-
 nptl/pthread_sigmask.c                     |  2 +-
 sysdeps/unix/sysv/linux/aio_misc.h         |  9 ++++++---
 sysdeps/unix/sysv/linux/epoll_pwait.c      |  2 +-
 sysdeps/unix/sysv/linux/internal-signals.h | 10 +++++-----
 sysdeps/unix/sysv/linux/ppoll.c            |  7 ++++---
 sysdeps/unix/sysv/linux/pselect.c          |  2 +-
 sysdeps/unix/sysv/linux/sigaction.c        |  3 ++-
 sysdeps/unix/sysv/linux/signalfd.c         |  2 +-
 sysdeps/unix/sysv/linux/sigpending.c       |  2 +-
 sysdeps/unix/sysv/linux/sigsetops.h        | 18 +++++++++++++-----
 sysdeps/unix/sysv/linux/sigsuspend.c       |  2 +-
 sysdeps/unix/sysv/linux/sigtimedwait.c     |  3 ++-
 sysdeps/unix/sysv/linux/x86/setjmpP.h      |  5 ++---
 15 files changed, 43 insertions(+), 28 deletions(-)

Comments

Carlos O'Donell July 2, 2020, 7:08 p.m. UTC | #1
On 6/19/20 9:43 AM, Adhemerval Zanella wrote:
> The __NSIG_WORDS value is based on minimum number of words to hold
> the maximum number of signal supported by the architecture.  Maximum

s/signal/signals/g

> number of signals non multiple of word is rounded up.

^^^ This sentence needs rewriting for clarity in the commit message.
 
> This patch also adds __NSIG_BYTES, which is the number of bytes
> required to represent the support number of signals.  It is used on

s/support/supported/g, s/on/in/g

> syscall which takes a sigset_t.

s/sycall/syscalls/g

Conceptually I like changes like this which move from hard-coded values
like foo/8 to more concrete semantics e.g. use a value that represents
what you want to express (and not the result of some other computation).
 
> Checked on x86_64-linux-gnu and i686-linux-gnu.

OK for master with cleaned up commit message.

No regressions on x86_64 and i686.

Tested-by: Carlos O'Donell <carlos@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> ---
>  include/signal.h                           |  2 ++
>  nptl/nptl-init.c                           |  2 +-
>  nptl/pthread_sigmask.c                     |  2 +-
>  sysdeps/unix/sysv/linux/aio_misc.h         |  9 ++++++---
>  sysdeps/unix/sysv/linux/epoll_pwait.c      |  2 +-
>  sysdeps/unix/sysv/linux/internal-signals.h | 10 +++++-----
>  sysdeps/unix/sysv/linux/ppoll.c            |  7 ++++---
>  sysdeps/unix/sysv/linux/pselect.c          |  2 +-
>  sysdeps/unix/sysv/linux/sigaction.c        |  3 ++-
>  sysdeps/unix/sysv/linux/signalfd.c         |  2 +-
>  sysdeps/unix/sysv/linux/sigpending.c       |  2 +-
>  sysdeps/unix/sysv/linux/sigsetops.h        | 18 +++++++++++++-----
>  sysdeps/unix/sysv/linux/sigsuspend.c       |  2 +-
>  sysdeps/unix/sysv/linux/sigtimedwait.c     |  3 ++-
>  sysdeps/unix/sysv/linux/x86/setjmpP.h      |  5 ++---
>  15 files changed, 43 insertions(+), 28 deletions(-)
> 
> diff --git a/include/signal.h b/include/signal.h
> index aa68f45886..3d6315b741 100644
> --- a/include/signal.h
> +++ b/include/signal.h
> @@ -2,6 +2,8 @@
>  # include <signal/signal.h>
>  
>  # ifndef _ISOMAC
> +#  include <sigsetops.h>
> +

OK.

>  libc_hidden_proto (sigemptyset)
>  libc_hidden_proto (sigfillset)
>  libc_hidden_proto (sigaddset)
> diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
> index d4cf20e3d1..95c60a524a 100644
> --- a/nptl/nptl-init.c
> +++ b/nptl/nptl-init.c
> @@ -281,7 +281,7 @@ __pthread_initialize_minimal_internal (void)
>    __sigaddset (&sa.sa_mask, SIGCANCEL);
>    __sigaddset (&sa.sa_mask, SIGSETXID);
>    INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &sa.sa_mask,
> -			 NULL, _NSIG / 8);
> +			 NULL, __NSIG_BYTES);

OK.

>  
>    /* Get the size of the static and alignment requirements for the TLS
>       block.  */
> diff --git a/nptl/pthread_sigmask.c b/nptl/pthread_sigmask.c
> index d266d296c5..7b65ae1f27 100644
> --- a/nptl/pthread_sigmask.c
> +++ b/nptl/pthread_sigmask.c
> @@ -39,7 +39,7 @@ __pthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask)
>  
>    /* We know that realtime signals are available if NPTL is used.  */
>    int result = INTERNAL_SYSCALL_CALL (rt_sigprocmask, how, newmask,
> -				      oldmask, _NSIG / 8);
> +				      oldmask, __NSIG_BYTES);

OK.

>  
>    return (INTERNAL_SYSCALL_ERROR_P (result)
>  	  ? INTERNAL_SYSCALL_ERRNO (result)
> diff --git a/sysdeps/unix/sysv/linux/aio_misc.h b/sysdeps/unix/sysv/linux/aio_misc.h
> index 30c3cd778e..e31ca8edbe 100644
> --- a/sysdeps/unix/sysv/linux/aio_misc.h
> +++ b/sysdeps/unix/sysv/linux/aio_misc.h
> @@ -31,7 +31,8 @@ __aio_start_notify_thread (void)
>  {
>    sigset_t ss;
>    sigemptyset (&ss);
> -  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &ss, NULL, _NSIG / 8);
> +  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &ss, NULL,
> +			 __NSIG_BYTES);
>  }
>  
>  extern inline int
> @@ -52,12 +53,14 @@ __aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
>    sigset_t ss;
>    sigset_t oss;
>    sigfillset (&ss);
> -  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &ss, &oss, _NSIG / 8);
> +  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &ss, &oss,
> +			 __NSIG_BYTES);
>  
>    int ret = pthread_create (threadp, &attr, tf, arg);
>  
>    /* Restore the signal mask.  */
> -  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &oss, NULL, _NSIG / 8);
> +  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &oss, NULL,
> +			 __NSIG_BYTES);
>  
>    (void) pthread_attr_destroy (&attr);
>    return ret;
> diff --git a/sysdeps/unix/sysv/linux/epoll_pwait.c b/sysdeps/unix/sysv/linux/epoll_pwait.c
> index 66f04482c7..af6d0fd713 100644
> --- a/sysdeps/unix/sysv/linux/epoll_pwait.c
> +++ b/sysdeps/unix/sysv/linux/epoll_pwait.c
> @@ -38,6 +38,6 @@ int epoll_pwait (int epfd, struct epoll_event *events,
>  		 const sigset_t *set)
>  {
>    return SYSCALL_CANCEL (epoll_pwait, epfd, events, maxevents,
> -			 timeout, set, _NSIG / 8);
> +			 timeout, set, __NSIG_BYTES);
>  }
>  libc_hidden_def (epoll_pwait)
> diff --git a/sysdeps/unix/sysv/linux/internal-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
> index 3fbd4807d1..35f2de04c5 100644
> --- a/sysdeps/unix/sysv/linux/internal-signals.h
> +++ b/sysdeps/unix/sysv/linux/internal-signals.h
> @@ -68,7 +68,7 @@ static inline void
>  __libc_signal_block_all (sigset_t *set)
>  {
>    INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &sigall_set, set,
> -			 _NSIG / 8);
> +			 __NSIG_BYTES);
>  }
>  
>  /* Block all application signals (excluding internal glibc ones).  */
> @@ -78,7 +78,7 @@ __libc_signal_block_app (sigset_t *set)
>    sigset_t allset = sigall_set;
>    __clear_internal_signals (&allset);
>    INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &allset, set,
> -			 _NSIG / 8);
> +			 __NSIG_BYTES);
>  }
>  
>  /* Block only SIGTIMER and return the previous set on SET.  */
> @@ -86,7 +86,7 @@ static inline void
>  __libc_signal_block_sigtimer (sigset_t *set)
>  {
>    INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &sigtimer_set, set,
> -			 _NSIG / 8);
> +			 __NSIG_BYTES);
>  }
>  
>  /* Unblock only SIGTIMER and return the previous set on SET.  */
> @@ -94,7 +94,7 @@ static inline void
>  __libc_signal_unblock_sigtimer (sigset_t *set)
>  {
>    INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &sigtimer_set, set,
> -			 _NSIG / 8);
> +			 __NSIG_BYTES);
>  }
>  
>  /* Restore current process signal mask.  */
> @@ -102,7 +102,7 @@ static inline void
>  __libc_signal_restore_set (const sigset_t *set)
>  {
>    INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, set, NULL,
> -			 _NSIG / 8);
> +			 __NSIG_BYTES);
>  }
>  
>  /* Used to communicate with signal handler.  */
> diff --git a/sysdeps/unix/sysv/linux/ppoll.c b/sysdeps/unix/sysv/linux/ppoll.c
> index 4ffb23710e..0f15636cce 100644
> --- a/sysdeps/unix/sysv/linux/ppoll.c
> +++ b/sysdeps/unix/sysv/linux/ppoll.c
> @@ -41,11 +41,12 @@ __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout,
>  # ifndef __NR_ppoll_time64
>  #  define __NR_ppoll_time64 __NR_ppoll
>  # endif
> -  return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask, _NSIG / 8);
> +  return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
> +			 __NSIG_BYTES);
>  #else
>  # ifdef __NR_ppoll_time64
>    int ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
> -                            _NSIG / 8);
> +                            __NSIG_BYTES);
>    if (ret >= 0 || errno != ENOSYS)
>      return ret;
>  # endif
> @@ -62,7 +63,7 @@ __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout,
>      }
>  
>    return SYSCALL_CANCEL (ppoll, fds, nfds, timeout ? &ts32 : NULL, sigmask,
> -                         _NSIG / 8);
> +                         __NSIG_BYTES);
>  #endif
>  }
>  
> diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c
> index d7c6ff8fdb..304db03338 100644
> --- a/sysdeps/unix/sysv/linux/pselect.c
> +++ b/sysdeps/unix/sysv/linux/pselect.c
> @@ -43,7 +43,7 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
>    } data;
>  
>    data.ss = (__syscall_ulong_t) (uintptr_t) sigmask;
> -  data.ss_len = _NSIG / 8;
> +  data.ss_len = __NSIG_BYTES;
>  
>    return SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds,
>                           timeout, &data);
> diff --git a/sysdeps/unix/sysv/linux/sigaction.c b/sysdeps/unix/sysv/linux/sigaction.c
> index 4e6d11a6ae..f27349d552 100644
> --- a/sysdeps/unix/sysv/linux/sigaction.c
> +++ b/sysdeps/unix/sysv/linux/sigaction.c
> @@ -57,7 +57,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
>       real size of the user-level sigset_t.  */
>    result = INLINE_SYSCALL_CALL (rt_sigaction, sig,
>  				act ? &kact : NULL,
> -				oact ? &koact : NULL, STUB (act, _NSIG / 8));
> +				oact ? &koact : NULL, STUB (act,
> +							    __NSIG_BYTES));
>  
>    if (oact && result >= 0)
>      {
> diff --git a/sysdeps/unix/sysv/linux/signalfd.c b/sysdeps/unix/sysv/linux/signalfd.c
> index 64d7bccba9..71d91fdde5 100644
> --- a/sysdeps/unix/sysv/linux/signalfd.c
> +++ b/sysdeps/unix/sysv/linux/signalfd.c
> @@ -24,5 +24,5 @@
>  int
>  signalfd (int fd, const sigset_t *mask, int flags)
>  {
> -  return INLINE_SYSCALL (signalfd4, 4, fd, mask, _NSIG / 8, flags);
> +  return INLINE_SYSCALL (signalfd4, 4, fd, mask, __NSIG_BYTES, flags);
>  }
> diff --git a/sysdeps/unix/sysv/linux/sigpending.c b/sysdeps/unix/sysv/linux/sigpending.c
> index 458a3cf99e..8898fe8b34 100644
> --- a/sysdeps/unix/sysv/linux/sigpending.c
> +++ b/sysdeps/unix/sysv/linux/sigpending.c
> @@ -24,5 +24,5 @@
>  int
>  sigpending (sigset_t *set)
>  {
> -  return INLINE_SYSCALL (rt_sigpending, 2, set, _NSIG / 8);
> +  return INLINE_SYSCALL_CALL (rt_sigpending, set, __NSIG_BYTES);
>  }
> diff --git a/sysdeps/unix/sysv/linux/sigsetops.h b/sysdeps/unix/sysv/linux/sigsetops.h
> index db8f378cf0..3f29ead009 100644

OK. All above is just search and replace refactor.

> --- a/sysdeps/unix/sysv/linux/sigsetops.h
> +++ b/sysdeps/unix/sysv/linux/sigsetops.h
> @@ -20,23 +20,31 @@
>  #define _SIGSETOPS_H 1
>  
>  #include <signal.h>
> +#include <limits.h>
> +#include <libc-pointer-arith.h>

OK.

>  
>  /* Return a mask that includes the bit for SIG only.  */
> -# define __sigmask(sig) \
> -  (((unsigned long int) 1) << (((sig) - 1) % (8 * sizeof (unsigned long int))))
> +#define __sigmask(sig) \
> +  (1UL << (((sig) - 1) % ULONG_WIDTH))

OK.

>  
>  /* Return the word index for SIG.  */
>  static inline unsigned long int
>  __sigword (int sig)
>  {
> -  return (sig - 1) / (8 * sizeof (unsigned long int));
> +  return (sig - 1) / ULONG_WIDTH;

OK.

>  }
>  
>  /* 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.  */
> -
> -# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int )))
> +#define __NSIG_WORDS (ALIGN_UP ((_NSIG - 1), ULONG_WIDTH) / ULONG_WIDTH)
> +_Static_assert (__NSIG_WORDS <= _SIGSET_NWORDS,
> +		"__NSIG_WORDS > _SIGSET_WORDS");

OK.

> +
> +/* This macro is used on syscall that takes a sigset_t to specify the expected
> +   size in bytes.  As for glibc, kernel sigset is implemented as an array of
> +   unsigned long.  */
> +#define __NSIG_BYTES (__NSIG_WORDS * (ULONG_WIDTH / UCHAR_WIDTH))

OK.

>  
>  static inline void
>  __sigemptyset (sigset_t *set)
> diff --git a/sysdeps/unix/sysv/linux/sigsuspend.c b/sysdeps/unix/sysv/linux/sigsuspend.c
> index dd5df5af25..b4bf2ec4bc 100644
> --- a/sysdeps/unix/sysv/linux/sigsuspend.c
> +++ b/sysdeps/unix/sysv/linux/sigsuspend.c
> @@ -23,7 +23,7 @@
>  int
>  __sigsuspend (const sigset_t *set)
>  {
> -  return SYSCALL_CANCEL (rt_sigsuspend, set, _NSIG / 8);
> +  return SYSCALL_CANCEL (rt_sigsuspend, set, __NSIG_BYTES);
>  }
>  libc_hidden_def (__sigsuspend)
>  weak_alias (__sigsuspend, sigsuspend)
> diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
> index 6b3d8f705f..f2ef3aad45 100644
> --- a/sysdeps/unix/sysv/linux/sigtimedwait.c
> +++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
> @@ -26,7 +26,8 @@ __sigtimedwait (const sigset_t *set, siginfo_t *info,
>  {
>    /* XXX The size argument hopefully will have to be changed to the
>       real size of the user-level sigset_t.  */
> -  int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, timeout, _NSIG / 8);
> +  int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, timeout,
> +			       __NSIG_BYTES);
>  
>    /* The kernel generates a SI_TKILL code in si_code in case tkill is
>       used.  tkill is transparently used in raise().  Since having
> diff --git a/sysdeps/unix/sysv/linux/x86/setjmpP.h b/sysdeps/unix/sysv/linux/x86/setjmpP.h
> index 1783b8eb78..a5de31bfd6 100644
> --- a/sysdeps/unix/sysv/linux/x86/setjmpP.h
> +++ b/sysdeps/unix/sysv/linux/x86/setjmpP.h
> @@ -21,6 +21,7 @@
>  
>  #include <bits/types/__sigset_t.h>
>  #include <libc-pointer-arith.h>
> +#include <sigsetops.h>
>  
>  /* <setjmp/setjmp.h> has
>  
> @@ -113,11 +114,9 @@ typedef union
>  
>  #include <signal.h>
>  
> -#define _SIGPROCMASK_NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int)))
> -
>  typedef struct
>    {
> -    unsigned long int __val[_SIGPROCMASK_NSIG_WORDS];
> +    unsigned long int __val[__NSIG_WORDS];
>    } __sigprocmask_sigset_t;
>  
>  extern jmp_buf ___buf;
> 

OK.
Adhemerval Zanella July 3, 2020, 7:23 p.m. UTC | #2
On 02/07/2020 16:08, Carlos O'Donell wrote:
> On 6/19/20 9:43 AM, Adhemerval Zanella wrote:
>> The __NSIG_WORDS value is based on minimum number of words to hold
>> the maximum number of signal supported by the architecture.  Maximum
> 
> s/signal/signals/g

Ack.

> 
>> number of signals non multiple of word is rounded up.
> 
> ^^^ This sentence needs rewriting for clarity in the commit message.

In fact I think this setence is redundant, the first one already states
that __NSIG_WORDS is suffice to represent all the supported signals
and the rounding up should be implicit to obtain it. I removed the
confusing sentence.

>  
>> This patch also adds __NSIG_BYTES, which is the number of bytes
>> required to represent the support number of signals.  It is used on
> 
> s/support/supported/g, s/on/in/g

Ack.

> 
>> syscall which takes a sigset_t.
> 
> s/sycall/syscalls/g

Ack.

> 
> Conceptually I like changes like this which move from hard-coded values
> like foo/8 to more concrete semantics e.g. use a value that represents
> what you want to express (and not the result of some other computation).
>  
>> Checked on x86_64-linux-gnu and i686-linux-gnu.
> 
> OK for master with cleaned up commit message.
> 
> No regressions on x86_64 and i686.
> 
> Tested-by: Carlos O'Donell <carlos@redhat.com>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff mbox series

Patch

diff --git a/include/signal.h b/include/signal.h
index aa68f45886..3d6315b741 100644
--- a/include/signal.h
+++ b/include/signal.h
@@ -2,6 +2,8 @@ 
 # include <signal/signal.h>
 
 # ifndef _ISOMAC
+#  include <sigsetops.h>
+
 libc_hidden_proto (sigemptyset)
 libc_hidden_proto (sigfillset)
 libc_hidden_proto (sigaddset)
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
index d4cf20e3d1..95c60a524a 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -281,7 +281,7 @@  __pthread_initialize_minimal_internal (void)
   __sigaddset (&sa.sa_mask, SIGCANCEL);
   __sigaddset (&sa.sa_mask, SIGSETXID);
   INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &sa.sa_mask,
-			 NULL, _NSIG / 8);
+			 NULL, __NSIG_BYTES);
 
   /* Get the size of the static and alignment requirements for the TLS
      block.  */
diff --git a/nptl/pthread_sigmask.c b/nptl/pthread_sigmask.c
index d266d296c5..7b65ae1f27 100644
--- a/nptl/pthread_sigmask.c
+++ b/nptl/pthread_sigmask.c
@@ -39,7 +39,7 @@  __pthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask)
 
   /* We know that realtime signals are available if NPTL is used.  */
   int result = INTERNAL_SYSCALL_CALL (rt_sigprocmask, how, newmask,
-				      oldmask, _NSIG / 8);
+				      oldmask, __NSIG_BYTES);
 
   return (INTERNAL_SYSCALL_ERROR_P (result)
 	  ? INTERNAL_SYSCALL_ERRNO (result)
diff --git a/sysdeps/unix/sysv/linux/aio_misc.h b/sysdeps/unix/sysv/linux/aio_misc.h
index 30c3cd778e..e31ca8edbe 100644
--- a/sysdeps/unix/sysv/linux/aio_misc.h
+++ b/sysdeps/unix/sysv/linux/aio_misc.h
@@ -31,7 +31,8 @@  __aio_start_notify_thread (void)
 {
   sigset_t ss;
   sigemptyset (&ss);
-  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &ss, NULL, _NSIG / 8);
+  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &ss, NULL,
+			 __NSIG_BYTES);
 }
 
 extern inline int
@@ -52,12 +53,14 @@  __aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
   sigset_t ss;
   sigset_t oss;
   sigfillset (&ss);
-  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &ss, &oss, _NSIG / 8);
+  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &ss, &oss,
+			 __NSIG_BYTES);
 
   int ret = pthread_create (threadp, &attr, tf, arg);
 
   /* Restore the signal mask.  */
-  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &oss, NULL, _NSIG / 8);
+  INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, &oss, NULL,
+			 __NSIG_BYTES);
 
   (void) pthread_attr_destroy (&attr);
   return ret;
diff --git a/sysdeps/unix/sysv/linux/epoll_pwait.c b/sysdeps/unix/sysv/linux/epoll_pwait.c
index 66f04482c7..af6d0fd713 100644
--- a/sysdeps/unix/sysv/linux/epoll_pwait.c
+++ b/sysdeps/unix/sysv/linux/epoll_pwait.c
@@ -38,6 +38,6 @@  int epoll_pwait (int epfd, struct epoll_event *events,
 		 const sigset_t *set)
 {
   return SYSCALL_CANCEL (epoll_pwait, epfd, events, maxevents,
-			 timeout, set, _NSIG / 8);
+			 timeout, set, __NSIG_BYTES);
 }
 libc_hidden_def (epoll_pwait)
diff --git a/sysdeps/unix/sysv/linux/internal-signals.h b/sysdeps/unix/sysv/linux/internal-signals.h
index 3fbd4807d1..35f2de04c5 100644
--- a/sysdeps/unix/sysv/linux/internal-signals.h
+++ b/sysdeps/unix/sysv/linux/internal-signals.h
@@ -68,7 +68,7 @@  static inline void
 __libc_signal_block_all (sigset_t *set)
 {
   INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &sigall_set, set,
-			 _NSIG / 8);
+			 __NSIG_BYTES);
 }
 
 /* Block all application signals (excluding internal glibc ones).  */
@@ -78,7 +78,7 @@  __libc_signal_block_app (sigset_t *set)
   sigset_t allset = sigall_set;
   __clear_internal_signals (&allset);
   INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &allset, set,
-			 _NSIG / 8);
+			 __NSIG_BYTES);
 }
 
 /* Block only SIGTIMER and return the previous set on SET.  */
@@ -86,7 +86,7 @@  static inline void
 __libc_signal_block_sigtimer (sigset_t *set)
 {
   INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &sigtimer_set, set,
-			 _NSIG / 8);
+			 __NSIG_BYTES);
 }
 
 /* Unblock only SIGTIMER and return the previous set on SET.  */
@@ -94,7 +94,7 @@  static inline void
 __libc_signal_unblock_sigtimer (sigset_t *set)
 {
   INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &sigtimer_set, set,
-			 _NSIG / 8);
+			 __NSIG_BYTES);
 }
 
 /* Restore current process signal mask.  */
@@ -102,7 +102,7 @@  static inline void
 __libc_signal_restore_set (const sigset_t *set)
 {
   INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, set, NULL,
-			 _NSIG / 8);
+			 __NSIG_BYTES);
 }
 
 /* Used to communicate with signal handler.  */
diff --git a/sysdeps/unix/sysv/linux/ppoll.c b/sysdeps/unix/sysv/linux/ppoll.c
index 4ffb23710e..0f15636cce 100644
--- a/sysdeps/unix/sysv/linux/ppoll.c
+++ b/sysdeps/unix/sysv/linux/ppoll.c
@@ -41,11 +41,12 @@  __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout,
 # ifndef __NR_ppoll_time64
 #  define __NR_ppoll_time64 __NR_ppoll
 # endif
-  return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask, _NSIG / 8);
+  return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
+			 __NSIG_BYTES);
 #else
 # ifdef __NR_ppoll_time64
   int ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
-                            _NSIG / 8);
+                            __NSIG_BYTES);
   if (ret >= 0 || errno != ENOSYS)
     return ret;
 # endif
@@ -62,7 +63,7 @@  __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout,
     }
 
   return SYSCALL_CANCEL (ppoll, fds, nfds, timeout ? &ts32 : NULL, sigmask,
-                         _NSIG / 8);
+                         __NSIG_BYTES);
 #endif
 }
 
diff --git a/sysdeps/unix/sysv/linux/pselect.c b/sysdeps/unix/sysv/linux/pselect.c
index d7c6ff8fdb..304db03338 100644
--- a/sysdeps/unix/sysv/linux/pselect.c
+++ b/sysdeps/unix/sysv/linux/pselect.c
@@ -43,7 +43,7 @@  __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
   } data;
 
   data.ss = (__syscall_ulong_t) (uintptr_t) sigmask;
-  data.ss_len = _NSIG / 8;
+  data.ss_len = __NSIG_BYTES;
 
   return SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds,
                          timeout, &data);
diff --git a/sysdeps/unix/sysv/linux/sigaction.c b/sysdeps/unix/sysv/linux/sigaction.c
index 4e6d11a6ae..f27349d552 100644
--- a/sysdeps/unix/sysv/linux/sigaction.c
+++ b/sysdeps/unix/sysv/linux/sigaction.c
@@ -57,7 +57,8 @@  __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
      real size of the user-level sigset_t.  */
   result = INLINE_SYSCALL_CALL (rt_sigaction, sig,
 				act ? &kact : NULL,
-				oact ? &koact : NULL, STUB (act, _NSIG / 8));
+				oact ? &koact : NULL, STUB (act,
+							    __NSIG_BYTES));
 
   if (oact && result >= 0)
     {
diff --git a/sysdeps/unix/sysv/linux/signalfd.c b/sysdeps/unix/sysv/linux/signalfd.c
index 64d7bccba9..71d91fdde5 100644
--- a/sysdeps/unix/sysv/linux/signalfd.c
+++ b/sysdeps/unix/sysv/linux/signalfd.c
@@ -24,5 +24,5 @@ 
 int
 signalfd (int fd, const sigset_t *mask, int flags)
 {
-  return INLINE_SYSCALL (signalfd4, 4, fd, mask, _NSIG / 8, flags);
+  return INLINE_SYSCALL (signalfd4, 4, fd, mask, __NSIG_BYTES, flags);
 }
diff --git a/sysdeps/unix/sysv/linux/sigpending.c b/sysdeps/unix/sysv/linux/sigpending.c
index 458a3cf99e..8898fe8b34 100644
--- a/sysdeps/unix/sysv/linux/sigpending.c
+++ b/sysdeps/unix/sysv/linux/sigpending.c
@@ -24,5 +24,5 @@ 
 int
 sigpending (sigset_t *set)
 {
-  return INLINE_SYSCALL (rt_sigpending, 2, set, _NSIG / 8);
+  return INLINE_SYSCALL_CALL (rt_sigpending, set, __NSIG_BYTES);
 }
diff --git a/sysdeps/unix/sysv/linux/sigsetops.h b/sysdeps/unix/sysv/linux/sigsetops.h
index db8f378cf0..3f29ead009 100644
--- a/sysdeps/unix/sysv/linux/sigsetops.h
+++ b/sysdeps/unix/sysv/linux/sigsetops.h
@@ -20,23 +20,31 @@ 
 #define _SIGSETOPS_H 1
 
 #include <signal.h>
+#include <limits.h>
+#include <libc-pointer-arith.h>
 
 /* Return a mask that includes the bit for SIG only.  */
-# define __sigmask(sig) \
-  (((unsigned long int) 1) << (((sig) - 1) % (8 * sizeof (unsigned long int))))
+#define __sigmask(sig) \
+  (1UL << (((sig) - 1) % ULONG_WIDTH))
 
 /* Return the word index for SIG.  */
 static inline unsigned long int
 __sigword (int sig)
 {
-  return (sig - 1) / (8 * sizeof (unsigned long int));
+  return (sig - 1) / ULONG_WIDTH;
 }
 
 /* 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.  */
-
-# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int )))
+#define __NSIG_WORDS (ALIGN_UP ((_NSIG - 1), ULONG_WIDTH) / ULONG_WIDTH)
+_Static_assert (__NSIG_WORDS <= _SIGSET_NWORDS,
+		"__NSIG_WORDS > _SIGSET_WORDS");
+
+/* This macro is used on syscall that takes a sigset_t to specify the expected
+   size in bytes.  As for glibc, kernel sigset is implemented as an array of
+   unsigned long.  */
+#define __NSIG_BYTES (__NSIG_WORDS * (ULONG_WIDTH / UCHAR_WIDTH))
 
 static inline void
 __sigemptyset (sigset_t *set)
diff --git a/sysdeps/unix/sysv/linux/sigsuspend.c b/sysdeps/unix/sysv/linux/sigsuspend.c
index dd5df5af25..b4bf2ec4bc 100644
--- a/sysdeps/unix/sysv/linux/sigsuspend.c
+++ b/sysdeps/unix/sysv/linux/sigsuspend.c
@@ -23,7 +23,7 @@ 
 int
 __sigsuspend (const sigset_t *set)
 {
-  return SYSCALL_CANCEL (rt_sigsuspend, set, _NSIG / 8);
+  return SYSCALL_CANCEL (rt_sigsuspend, set, __NSIG_BYTES);
 }
 libc_hidden_def (__sigsuspend)
 weak_alias (__sigsuspend, sigsuspend)
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index 6b3d8f705f..f2ef3aad45 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -26,7 +26,8 @@  __sigtimedwait (const sigset_t *set, siginfo_t *info,
 {
   /* XXX The size argument hopefully will have to be changed to the
      real size of the user-level sigset_t.  */
-  int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, timeout, _NSIG / 8);
+  int result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, timeout,
+			       __NSIG_BYTES);
 
   /* The kernel generates a SI_TKILL code in si_code in case tkill is
      used.  tkill is transparently used in raise().  Since having
diff --git a/sysdeps/unix/sysv/linux/x86/setjmpP.h b/sysdeps/unix/sysv/linux/x86/setjmpP.h
index 1783b8eb78..a5de31bfd6 100644
--- a/sysdeps/unix/sysv/linux/x86/setjmpP.h
+++ b/sysdeps/unix/sysv/linux/x86/setjmpP.h
@@ -21,6 +21,7 @@ 
 
 #include <bits/types/__sigset_t.h>
 #include <libc-pointer-arith.h>
+#include <sigsetops.h>
 
 /* <setjmp/setjmp.h> has
 
@@ -113,11 +114,9 @@  typedef union
 
 #include <signal.h>
 
-#define _SIGPROCMASK_NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int)))
-
 typedef struct
   {
-    unsigned long int __val[_SIGPROCMASK_NSIG_WORDS];
+    unsigned long int __val[__NSIG_WORDS];
   } __sigprocmask_sigset_t;
 
 extern jmp_buf ___buf;