From patchwork Thu Apr 23 19:26:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 38854 Return-Path: X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x843.google.com (mail-qt1-x843.google.com [IPv6:2607:f8b0:4864:20::843]) by sourceware.org (Postfix) with ESMTPS id DF1C73959C26 for ; Thu, 23 Apr 2020 19:26:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org DF1C73959C26 Received: by mail-qt1-x843.google.com with SMTP id v26so297835qto.0 for ; Thu, 23 Apr 2020 12:26:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=KJZkkx0+KMlwIvKLDcHNBKQEqJ9HUwNdaoY0NQXVfbc=; b=Npz/4zi8gn+CUtQiqh035h4u9jlUXoLG94SNeX8MktU0/vfUllIsLZJ2Fg0iz4IM3G v3GMIHbSqii8AVEtdDr0Q5X7dDiYFfnSSUmQIqEmmnPuUssPFWsviFcWXCMowGk7ciOV FmXLFHawxIxiGlv+SUy5Qcvc6BF1BtjwhEKz9FWaSsXXgBgK7w4VO5Cg5jE3sGid4ORJ HHR21nmx3zBtNLOY150ZNbE8b/oUwLa6dSwOYkC5SQzQ7B8v5s3Thyr6xznEwaKPUvBK K+4EBz3mSuN5JPIC8SMZ+YqDz5bGc8EVsqm4E35I3LzFfZUXd30PyOvwKdIuuXThz2Vy bERw== X-Gm-Message-State: AGi0PubKItiPlNr+gIR2hGWP5T0QAUznKrD6Xi9nGV2bTz00GsLA/T/U yqtmWapVfK3JVtX8jwYo7OnzkaitnuB4Fw== X-Google-Smtp-Source: APiQypJpIrb9h5BJpKM7yAcZeRXwJNOWXPOqLhtuA/mUT/apS4EclrRwc7RaXuuQ8uX1SlEWIyTIxg== X-Received: by 2002:ac8:342d:: with SMTP id u42mr5651377qtb.255.1587669992842; Thu, 23 Apr 2020 12:26:32 -0700 (PDT) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id z90sm2212221qtd.75.2020.04.23.12.26.31 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Apr 2020 12:26:32 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH 3/3] linux: Fix __NSIG_WORDS and add __NSIG_BYTES Date: Thu, 23 Apr 2020 16:26:25 -0300 Message-Id: <20200423192625.21629-3-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200423192625.21629-1-adhemerval.zanella@linaro.org> References: <20200423192625.21629-1-adhemerval.zanella@linaro.org> X-Spam-Status: No, score=-25.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Apr 2020 19:26:35 -0000 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_create.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 ++--- 16 files changed, 44 insertions(+), 29 deletions(-) diff --git a/include/signal.h b/include/signal.h index 293258ad65..229b1eb352 100644 --- a/include/signal.h +++ b/include/signal.h @@ -2,6 +2,8 @@ # include # ifndef _ISOMAC +# include + 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 96b1444a01..ed450a09fd 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_create.c b/nptl/pthread_create.c index 7c752d0f99..479675e6a1 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -408,7 +408,7 @@ START_THREAD_DEFN __sigemptyset (&mask); __sigaddset (&mask, SIGCANCEL); INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &mask, - NULL, _NSIG / 8); + NULL, __NSIG_BYTES); } /* This is where the try/finally block should be created. For 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 +#include +#include /* 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 #include +#include /* has @@ -113,11 +114,9 @@ typedef union #include -#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;