mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
linux: Fix __NSIG_WORDS and add __NSIG_BYTES
The __NSIG_WORDS value is based on minimum number of words to hold the maximum number of signals supported by the architecture. This patch also adds __NSIG_BYTES, which is the number of bytes required to represent the supported number of signals. It is used in syscalls which takes a sigset_t. Checked on x86_64-linux-gnu and i686-linux-gnu. Tested-by: Carlos O'Donell <carlos@redhat.com> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
@ -2,6 +2,8 @@
|
|||||||
# include <signal/signal.h>
|
# include <signal/signal.h>
|
||||||
|
|
||||||
# ifndef _ISOMAC
|
# ifndef _ISOMAC
|
||||||
|
# include <sigsetops.h>
|
||||||
|
|
||||||
libc_hidden_proto (sigemptyset)
|
libc_hidden_proto (sigemptyset)
|
||||||
libc_hidden_proto (sigfillset)
|
libc_hidden_proto (sigfillset)
|
||||||
libc_hidden_proto (sigaddset)
|
libc_hidden_proto (sigaddset)
|
||||||
|
@ -281,7 +281,7 @@ __pthread_initialize_minimal_internal (void)
|
|||||||
__sigaddset (&sa.sa_mask, SIGCANCEL);
|
__sigaddset (&sa.sa_mask, SIGCANCEL);
|
||||||
__sigaddset (&sa.sa_mask, SIGSETXID);
|
__sigaddset (&sa.sa_mask, SIGSETXID);
|
||||||
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &sa.sa_mask,
|
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
|
/* Get the size of the static and alignment requirements for the TLS
|
||||||
block. */
|
block. */
|
||||||
|
@ -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. */
|
/* We know that realtime signals are available if NPTL is used. */
|
||||||
int result = INTERNAL_SYSCALL_CALL (rt_sigprocmask, how, newmask,
|
int result = INTERNAL_SYSCALL_CALL (rt_sigprocmask, how, newmask,
|
||||||
oldmask, _NSIG / 8);
|
oldmask, __NSIG_BYTES);
|
||||||
|
|
||||||
return (INTERNAL_SYSCALL_ERROR_P (result)
|
return (INTERNAL_SYSCALL_ERROR_P (result)
|
||||||
? INTERNAL_SYSCALL_ERRNO (result)
|
? INTERNAL_SYSCALL_ERRNO (result)
|
||||||
|
@ -31,7 +31,8 @@ __aio_start_notify_thread (void)
|
|||||||
{
|
{
|
||||||
sigset_t ss;
|
sigset_t ss;
|
||||||
sigemptyset (&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
|
extern inline int
|
||||||
@ -52,12 +53,14 @@ __aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
|
|||||||
sigset_t ss;
|
sigset_t ss;
|
||||||
sigset_t oss;
|
sigset_t oss;
|
||||||
sigfillset (&ss);
|
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);
|
int ret = pthread_create (threadp, &attr, tf, arg);
|
||||||
|
|
||||||
/* Restore the signal mask. */
|
/* 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);
|
(void) pthread_attr_destroy (&attr);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -38,6 +38,6 @@ int epoll_pwait (int epfd, struct epoll_event *events,
|
|||||||
const sigset_t *set)
|
const sigset_t *set)
|
||||||
{
|
{
|
||||||
return SYSCALL_CANCEL (epoll_pwait, epfd, events, maxevents,
|
return SYSCALL_CANCEL (epoll_pwait, epfd, events, maxevents,
|
||||||
timeout, set, _NSIG / 8);
|
timeout, set, __NSIG_BYTES);
|
||||||
}
|
}
|
||||||
libc_hidden_def (epoll_pwait)
|
libc_hidden_def (epoll_pwait)
|
||||||
|
@ -68,7 +68,7 @@ static inline void
|
|||||||
__libc_signal_block_all (sigset_t *set)
|
__libc_signal_block_all (sigset_t *set)
|
||||||
{
|
{
|
||||||
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &sigall_set, set,
|
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &sigall_set, set,
|
||||||
_NSIG / 8);
|
__NSIG_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Block all application signals (excluding internal glibc ones). */
|
/* Block all application signals (excluding internal glibc ones). */
|
||||||
@ -78,7 +78,7 @@ __libc_signal_block_app (sigset_t *set)
|
|||||||
sigset_t allset = sigall_set;
|
sigset_t allset = sigall_set;
|
||||||
__clear_internal_signals (&allset);
|
__clear_internal_signals (&allset);
|
||||||
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &allset, set,
|
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &allset, set,
|
||||||
_NSIG / 8);
|
__NSIG_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Block only SIGTIMER and return the previous set on SET. */
|
/* Block only SIGTIMER and return the previous set on SET. */
|
||||||
@ -86,7 +86,7 @@ static inline void
|
|||||||
__libc_signal_block_sigtimer (sigset_t *set)
|
__libc_signal_block_sigtimer (sigset_t *set)
|
||||||
{
|
{
|
||||||
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &sigtimer_set, 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. */
|
/* Unblock only SIGTIMER and return the previous set on SET. */
|
||||||
@ -94,7 +94,7 @@ static inline void
|
|||||||
__libc_signal_unblock_sigtimer (sigset_t *set)
|
__libc_signal_unblock_sigtimer (sigset_t *set)
|
||||||
{
|
{
|
||||||
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &sigtimer_set, set,
|
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &sigtimer_set, set,
|
||||||
_NSIG / 8);
|
__NSIG_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore current process signal mask. */
|
/* Restore current process signal mask. */
|
||||||
@ -102,7 +102,7 @@ static inline void
|
|||||||
__libc_signal_restore_set (const sigset_t *set)
|
__libc_signal_restore_set (const sigset_t *set)
|
||||||
{
|
{
|
||||||
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, set, NULL,
|
INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_SETMASK, set, NULL,
|
||||||
_NSIG / 8);
|
__NSIG_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used to communicate with signal handler. */
|
/* Used to communicate with signal handler. */
|
||||||
|
@ -41,11 +41,12 @@ __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout,
|
|||||||
# ifndef __NR_ppoll_time64
|
# ifndef __NR_ppoll_time64
|
||||||
# define __NR_ppoll_time64 __NR_ppoll
|
# define __NR_ppoll_time64 __NR_ppoll
|
||||||
# endif
|
# endif
|
||||||
return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask, _NSIG / 8);
|
return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
|
||||||
|
__NSIG_BYTES);
|
||||||
#else
|
#else
|
||||||
# ifdef __NR_ppoll_time64
|
# ifdef __NR_ppoll_time64
|
||||||
int ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
|
int ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
|
||||||
_NSIG / 8);
|
__NSIG_BYTES);
|
||||||
if (ret >= 0 || errno != ENOSYS)
|
if (ret >= 0 || errno != ENOSYS)
|
||||||
return ret;
|
return ret;
|
||||||
# endif
|
# 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,
|
return SYSCALL_CANCEL (ppoll, fds, nfds, timeout ? &ts32 : NULL, sigmask,
|
||||||
_NSIG / 8);
|
__NSIG_BYTES);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|||||||
} data;
|
} data;
|
||||||
|
|
||||||
data.ss = (__syscall_ulong_t) (uintptr_t) sigmask;
|
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,
|
return SYSCALL_CANCEL (pselect6, nfds, readfds, writefds, exceptfds,
|
||||||
timeout, &data);
|
timeout, &data);
|
||||||
|
@ -57,7 +57,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
|
|||||||
real size of the user-level sigset_t. */
|
real size of the user-level sigset_t. */
|
||||||
result = INLINE_SYSCALL_CALL (rt_sigaction, sig,
|
result = INLINE_SYSCALL_CALL (rt_sigaction, sig,
|
||||||
act ? &kact : NULL,
|
act ? &kact : NULL,
|
||||||
oact ? &koact : NULL, STUB (act, _NSIG / 8));
|
oact ? &koact : NULL, STUB (act,
|
||||||
|
__NSIG_BYTES));
|
||||||
|
|
||||||
if (oact && result >= 0)
|
if (oact && result >= 0)
|
||||||
{
|
{
|
||||||
|
@ -24,5 +24,5 @@
|
|||||||
int
|
int
|
||||||
signalfd (int fd, const sigset_t *mask, int flags)
|
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);
|
||||||
}
|
}
|
||||||
|
@ -24,5 +24,5 @@
|
|||||||
int
|
int
|
||||||
sigpending (sigset_t *set)
|
sigpending (sigset_t *set)
|
||||||
{
|
{
|
||||||
return INLINE_SYSCALL (rt_sigpending, 2, set, _NSIG / 8);
|
return INLINE_SYSCALL_CALL (rt_sigpending, set, __NSIG_BYTES);
|
||||||
}
|
}
|
||||||
|
@ -20,23 +20,31 @@
|
|||||||
#define _SIGSETOPS_H 1
|
#define _SIGSETOPS_H 1
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <libc-pointer-arith.h>
|
||||||
|
|
||||||
/* Return a mask that includes the bit for SIG only. */
|
/* Return a mask that includes the bit for SIG only. */
|
||||||
# define __sigmask(sig) \
|
#define __sigmask(sig) \
|
||||||
(((unsigned long int) 1) << (((sig) - 1) % (8 * sizeof (unsigned long int))))
|
(1UL << (((sig) - 1) % ULONG_WIDTH))
|
||||||
|
|
||||||
/* Return the word index for SIG. */
|
/* Return the word index for SIG. */
|
||||||
static inline unsigned long int
|
static inline unsigned long int
|
||||||
__sigword (int sig)
|
__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
|
/* Linux sig* functions only handle up to __NSIG_WORDS words instead of
|
||||||
full _SIGSET_NWORDS sigset size. The signal numbers are 1-based, and
|
full _SIGSET_NWORDS sigset size. The signal numbers are 1-based, and
|
||||||
bit 0 of a signal mask is for signal 1. */
|
bit 0 of a signal mask is for signal 1. */
|
||||||
|
#define __NSIG_WORDS (ALIGN_UP ((_NSIG - 1), ULONG_WIDTH) / ULONG_WIDTH)
|
||||||
|
_Static_assert (__NSIG_WORDS <= _SIGSET_NWORDS,
|
||||||
|
"__NSIG_WORDS > _SIGSET_WORDS");
|
||||||
|
|
||||||
# define __NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int )))
|
/* 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
|
static inline void
|
||||||
__sigemptyset (sigset_t *set)
|
__sigemptyset (sigset_t *set)
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
int
|
int
|
||||||
__sigsuspend (const sigset_t *set)
|
__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)
|
libc_hidden_def (__sigsuspend)
|
||||||
weak_alias (__sigsuspend, sigsuspend)
|
weak_alias (__sigsuspend, sigsuspend)
|
||||||
|
@ -26,7 +26,8 @@ __sigtimedwait (const sigset_t *set, siginfo_t *info,
|
|||||||
{
|
{
|
||||||
/* XXX The size argument hopefully will have to be changed to the
|
/* XXX The size argument hopefully will have to be changed to the
|
||||||
real size of the user-level sigset_t. */
|
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
|
/* The kernel generates a SI_TKILL code in si_code in case tkill is
|
||||||
used. tkill is transparently used in raise(). Since having
|
used. tkill is transparently used in raise(). Since having
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <bits/types/__sigset_t.h>
|
#include <bits/types/__sigset_t.h>
|
||||||
#include <libc-pointer-arith.h>
|
#include <libc-pointer-arith.h>
|
||||||
|
#include <sigsetops.h>
|
||||||
|
|
||||||
/* <setjmp/setjmp.h> has
|
/* <setjmp/setjmp.h> has
|
||||||
|
|
||||||
@ -113,11 +114,9 @@ typedef union
|
|||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#define _SIGPROCMASK_NSIG_WORDS (_NSIG / (8 * sizeof (unsigned long int)))
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
unsigned long int __val[_SIGPROCMASK_NSIG_WORDS];
|
unsigned long int __val[__NSIG_WORDS];
|
||||||
} __sigprocmask_sigset_t;
|
} __sigprocmask_sigset_t;
|
||||||
|
|
||||||
extern jmp_buf ___buf;
|
extern jmp_buf ___buf;
|
||||||
|
Reference in New Issue
Block a user