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