1  /* __sigset_t manipulators.  Linux version.
       2     Copyright (C) 1991-2023 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
      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
      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
      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
      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
      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
      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
      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
     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
     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 */