1 /* __sigset_t manipulators.  Linux version.
2    Copyright (C) 1991-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #ifndef _SIGSETOPS_H
20 #define _SIGSETOPS_H 1
21 
22 #include <signal.h>
23 #include <limits.h>
24 #include <libc-pointer-arith.h>
25 
26 /* Return a mask that includes the bit for SIG only.  */
27 #define __sigmask(sig) \
28   (1UL << (((sig) - 1) % ULONG_WIDTH))
29 
30 /* Return the word index for SIG.  */
31 static inline unsigned long int
__sigword(int sig)32 __sigword (int sig)
33 {
34   return (sig - 1) / ULONG_WIDTH;
35 }
36 
37 /* Linux sig* functions only handle up to __NSIG_WORDS words instead of
38    full _SIGSET_NWORDS sigset size.  The signal numbers are 1-based, and
39    bit 0 of a signal mask is for signal 1.  */
40 #define __NSIG_WORDS (ALIGN_UP ((_NSIG - 1), ULONG_WIDTH) / ULONG_WIDTH)
41 _Static_assert (__NSIG_WORDS <= _SIGSET_NWORDS,
42 		"__NSIG_WORDS > _SIGSET_WORDS");
43 
44 /* This macro is used on syscall that takes a sigset_t to specify the expected
45    size in bytes.  As for glibc, kernel sigset is implemented as an array of
46    unsigned long.  */
47 #define __NSIG_BYTES (__NSIG_WORDS * (ULONG_WIDTH / UCHAR_WIDTH))
48 
49 static inline void
__sigemptyset(sigset_t * set)50 __sigemptyset (sigset_t *set)
51 {
52   int cnt = __NSIG_WORDS;
53   while (--cnt >= 0)
54    set->__val[cnt] = 0;
55 }
56 
57 static inline void
__sigfillset(sigset_t * set)58 __sigfillset (sigset_t *set)
59 {
60   int cnt = __NSIG_WORDS;
61   while (--cnt >= 0)
62    set->__val[cnt] = ~0UL;
63 }
64 
65 static inline int
__sigisemptyset(const sigset_t * set)66 __sigisemptyset (const sigset_t *set)
67 {
68   int cnt = __NSIG_WORDS;
69   int ret = set->__val[--cnt];
70   while (ret == 0 && --cnt >= 0)
71     ret = set->__val[cnt];
72   return ret == 0;
73 }
74 
75 static inline void
__sigandset(sigset_t * dest,const sigset_t * left,const sigset_t * right)76 __sigandset (sigset_t *dest, const sigset_t *left, const sigset_t *right)
77 {
78   int cnt = __NSIG_WORDS;
79   while (--cnt >= 0)
80     dest->__val[cnt] = left->__val[cnt] & right->__val[cnt];
81 }
82 
83 static inline void
__sigorset(sigset_t * dest,const sigset_t * left,const sigset_t * right)84 __sigorset (sigset_t *dest, const sigset_t *left, const sigset_t *right)
85 {
86   int cnt = __NSIG_WORDS;
87   while (--cnt >= 0)
88     dest->__val[cnt] = left->__val[cnt] | right->__val[cnt];
89 }
90 
91 static inline int
__sigismember(const sigset_t * set,int sig)92 __sigismember (const sigset_t *set, int sig)
93 {
94   unsigned long int mask = __sigmask (sig);
95   unsigned long int word = __sigword (sig);
96   return set->__val[word] & mask ? 1 : 0;
97 }
98 
99 static inline void
__sigaddset(sigset_t * set,int sig)100 __sigaddset (sigset_t *set, int sig)
101 {
102   unsigned long int mask = __sigmask (sig);
103   unsigned long int word = __sigword (sig);
104   set->__val[word] |= mask;
105 }
106 
107 static inline void
__sigdelset(sigset_t * set,int sig)108 __sigdelset (sigset_t *set, int sig)
109 {
110   unsigned long int mask = __sigmask (sig);
111   unsigned long int word = __sigword (sig);
112   set->__val[word] &= ~mask;
113 }
114 
115 #endif /* bits/sigsetops.h */
116