1 //===-- Internal header for Linux signals -----------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_UTILS_H
10 #define LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_UTILS_H
12 #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
13 #include "src/__support/common.h"
17 #include <sys/syscall.h> // For syscall numbers.
19 namespace LIBC_NAMESPACE
{
21 // The POSIX definition of struct sigaction and the sigaction data structure
22 // expected by the rt_sigaction syscall differ in their definition. So, we
23 // define the equivalent of the what the kernel expects to help with making
24 // the rt_sigaction syscall.
26 // NOTE: Though the kernel definition does not have a union to include the
27 // handler taking siginfo_t * argument, one can set sa_handler to sa_sigaction
28 // if SA_SIGINFO is set in sa_flags.
29 struct KernelSigaction
{
30 using HandlerType
= void(int);
31 using SiginfoHandlerType
= void(int, siginfo_t
*, void *);
33 LIBC_INLINE KernelSigaction
&operator=(const struct sigaction
&sa
) {
34 sa_flags
= sa
.sa_flags
;
35 sa_restorer
= sa
.sa_restorer
;
37 if (sa_flags
& SA_SIGINFO
) {
38 sa_handler
= reinterpret_cast<HandlerType
*>(sa
.sa_sigaction
);
40 sa_handler
= sa
.sa_handler
;
45 LIBC_INLINE
operator struct sigaction() const {
47 sa
.sa_flags
= static_cast<int>(sa_flags
);
49 sa
.sa_restorer
= sa_restorer
;
50 if (sa_flags
& SA_SIGINFO
)
51 sa
.sa_sigaction
= reinterpret_cast<SiginfoHandlerType
*>(sa_handler
);
53 sa
.sa_handler
= sa_handler
;
57 HandlerType
*sa_handler
;
58 unsigned long sa_flags
;
59 void (*sa_restorer
)(void);
60 // Our public definition of sigset_t matches that of the kernel's definition.
61 // So, we can use the public sigset_t type here.
65 static constexpr size_t BITS_PER_SIGWORD
= sizeof(unsigned long) * 8;
67 LIBC_INLINE
constexpr sigset_t
full_set() { return sigset_t
{{-1UL}}; }
69 LIBC_INLINE
constexpr sigset_t
empty_set() { return sigset_t
{{0}}; }
71 // Set the bit corresponding to |signal| in |set|. Return true on success
72 // and false on failure. The function will fail if |signal| is greater than
74 LIBC_INLINE
constexpr bool add_signal(sigset_t
&set
, int signal
) {
75 if (signal
> NSIG
|| signal
<= 0)
77 size_t n
= size_t(signal
) - 1;
78 size_t word
= n
/ BITS_PER_SIGWORD
;
79 size_t bit
= n
% BITS_PER_SIGWORD
;
80 set
.__signals
[word
] |= (1UL << bit
);
84 // Reset the bit corresponding to |signal| in |set|. Return true on success
85 // and false on failure. The function will fail if |signal| is greater than
87 LIBC_INLINE
constexpr bool delete_signal(sigset_t
&set
, int signal
) {
88 if (signal
> NSIG
|| signal
<= 0)
90 size_t n
= size_t(signal
) - 1;
91 size_t word
= n
/ BITS_PER_SIGWORD
;
92 size_t bit
= n
% BITS_PER_SIGWORD
;
93 set
.__signals
[word
] &= ~(1UL << bit
);
97 LIBC_INLINE
int block_all_signals(sigset_t
&set
) {
98 sigset_t full
= full_set();
99 return LIBC_NAMESPACE::syscall_impl
<int>(SYS_rt_sigprocmask
, SIG_BLOCK
, &full
,
100 &set
, sizeof(sigset_t
));
103 LIBC_INLINE
int restore_signals(const sigset_t
&set
) {
104 return LIBC_NAMESPACE::syscall_impl
<int>(SYS_rt_sigprocmask
, SIG_SETMASK
,
105 &set
, nullptr, sizeof(sigset_t
));
108 } // namespace LIBC_NAMESPACE
110 #endif // LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_UTILS_H