20#ifndef WG14_SIGNALS_THREAD_LOCAL_SIGNAL_HANDLE_H
21#define WG14_SIGNALS_THREAD_LOCAL_SIGNAL_HANDLE_H
32#include <bits/types/siginfo_t.h>
43 typedef uint32_t sigset_t;
44 static inline void sigemptyset(sigset_t *ss)
48 static inline void sigfillset(sigset_t *ss)
52 static inline void sigaddset(sigset_t *ss,
const int signo)
54 *ss |= (1u << (signo - 1));
56 static inline void sigdelset(sigset_t *ss,
const int signo)
58 *ss &= ~(1u << (signo - 1));
60 static inline bool sigismember(
const sigset_t *ss,
const int signo)
62 return (*ss & (1u << (signo - 1))) != 0;
77#ifndef WG14_SIGNALS_DISABLE_SIGFENCE_MACRO
80#define SIGFENCE_GLUE(x, y) x y
81#define SIGFENCE_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, \
84#define SIGFENCE_EXPAND_ARGS(args) SIGFENCE_RETURN_ARG_COUNT args
85#define SIGFENCE_COUNT_ARGS_MAX8(...) \
86 SIGFENCE_EXPAND_ARGS((__VA_ARGS__ __VA_OPT__(, ) 8, 7, 6, 5, 4, 3, 2, 1, 0))
87#define SIGFENCE_OVERLOAD_MACRO2(name, count) name##count
88#define SIGFENCE_OVERLOAD_MACRO1(name, count) \
89 SIGFENCE_OVERLOAD_MACRO2(name, count)
90#define SIGFENCE_OVERLOAD_MACRO(name, count) \
91 SIGFENCE_OVERLOAD_MACRO1(name, count)
92#define SIGFENCE_CALL_OVERLOAD(name, ...) \
94 SIGFENCE_OVERLOAD_MACRO(name, SIGFENCE_COUNT_ARGS_MAX8(__VA_ARGS__)), \
97#if defined(__GNUC__) || defined(__clang__)
102#define SIGFENCE_IMPL_0() __asm__ volatile(";" : : : "memory")
103#define SIGFENCE_IMPL_1(a) __asm__ volatile(";" : "+m"(a) : : "memory")
104#define SIGFENCE_IMPL_2(a, b) \
105 __asm__ volatile(";" : "+m"(a), "+m"(b) : : "memory")
106#define SIGFENCE_IMPL_3(a, b, c) \
107 __asm__ volatile(";" : "+m"(a), "+m"(b), "+m"(c) : : "memory")
108#define SIGFENCE_IMPL_4(a, b, c, d) \
109 __asm__ volatile(";" : "+m"(a), "+m"(b), "+m"(c), "+m"(d) : : "memory")
110#define SIGFENCE_IMPL_5(a, b, c, d, e) \
111 __asm__ volatile(";" \
112 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e) \
115#define SIGFENCE_IMPL_6(a, b, c, d, e, f) \
116 __asm__ volatile(";" \
117 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e), "+m"(f) \
120#define SIGFENCE_IMPL_7(a, b, c, d, e, f, g) \
121 __asm__ volatile(";" \
122 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e), "+m"(f), \
126#define SIGFENCE_IMPL_8(a, b, c, d, e, f, g, h) \
127 __asm__ volatile(";" \
128 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e), "+m"(f), \
135#define SIGFENCE_IMPL_0() WG14_SIGNALS_PREFIX(sigfence_force_escaped)(0)
136#define SIGFENCE_IMPL_1(a) WG14_SIGNALS_PREFIX(sigfence_force_escaped)(0, &(a))
137#define SIGFENCE_IMPL_2(a, b) \
138 WG14_SIGNALS_PREFIX(sigfence_force_escaped)(0, &(a), &(b))
139#define SIGFENCE_IMPL_3(a, b, c) \
140 WG14_SIGNALS_PREFIX(sigfence_force_escaped)(0, &(a), &(b), &(c))
141#define SIGFENCE_IMPL_4(a, b, c, d) \
142 WG14_SIGNALS_PREFIX(sigfence_force_escaped)(0, &(a), &(b), &(c), &(d))
143#define SIGFENCE_IMPL_5(a, b, c, d, e) \
144 WG14_SIGNALS_PREFIX(sigfence_force_escaped)(0, &(a), &(b), &(c), &(d), &(e))
145#define SIGFENCE_IMPL_6(a, b, c, d, e, f) \
146 WG14_SIGNALS_PREFIX(sigfence_force_escaped)(0, &(a), &(b), &(c), &(d), &(e), \
148#define SIGFENCE_IMPL_7(a, b, c, d, e, f, g) \
149 WG14_SIGNALS_PREFIX(sigfence_force_escaped)(0, &(a), &(b), &(c), &(d), &(e), \
151#define SIGFENCE_IMPL_8(a, b, c, d, e, f, g, h) \
152 WG14_SIGNALS_PREFIX(sigfence_force_escaped)(0, &(a), &(b), &(c), &(d), &(e), \
157#define sigfence(...) SIGFENCE_CALL_OVERLOAD(SIGFENCE_IMPL_, __VA_ARGS__)
162#pragma warning(disable : 4190)
164#if defined(__clang__) && defined(__cplusplus)
165#pragma clang diagnostic push
166#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
172 union WG14_SIGNALS_PREFIX(stdc_siginfo_value)
176#if defined(__cplusplus)
185 constexpr WG14_SIGNALS_PREFIX(stdc_siginfo_value)(
void *v)
221 struct WG14_SIGNALS_PREFIX(stdc_siginfo)
229 union WG14_SIGNALS_PREFIX(
239 typedef union WG14_SIGNALS_PREFIX(stdc_siginfo_value)(WG14_SIGNALS_PREFIX(
244 typedef union WG14_SIGNALS_PREFIX(stdc_siginfo_value)(WG14_SIGNALS_PREFIX(
262 typedef enum WG14_SIGNALS_PREFIX(
sig_decision_t)(WG14_SIGNALS_PREFIX(
263 sig_decide_t))(
struct WG14_SIGNALS_PREFIX(stdc_siginfo) *);
353 union WG14_SIGNALS_PREFIX(stdc_siginfo_value)
355#if defined(__clang__) && defined(__cplusplus)
356#pragma clang diagnostic pop
447 const sigset_t *guarded,
bool callfirst,
449 union WG14_SIGNALS_PREFIX(stdc_siginfo_value) value);
463#if WG14_SIGNALS_ENABLE_HEADER_ONLY
465#include "detail/impl/thrd_signal_handle_windows.c.ipp"
467#include "detail/impl/thrd_signal_handle_posix.c.ipp"
#define WG14_SIGNALS_EXTERN
A platform independent subset of siginfo_t.
int signo
The signal raised.
thrd_raised_signal_error_code_t error_code
The system specific error code for this signal, the si_errno code (POSIX) or NTSTATUS code (Windows).
stdc_siginfo_context_t * raw_context
The OS specific ucontext_t (POSIX) or PCONTEXT (Windows).
void * addr
Memory location which caused fault, if appropriate.
union stdc_siginfo_value value
A user-defined value.
stdc_siginfo_siginfo_t * raw_info
The OS specific signal info.
int sigfillset_asynchronous_nondebug(sigset_t *set)
THREADSAFE ASYNC-SIGNAL-SAFE Fills the set of non-debug asynchronous signals for this platform.
struct __siginfo stdc_siginfo_siginfo_t
A placeholder type for an OS specific siginfo_t * (POSIX) or PEXCEPTION_RECORD (Windows).
void * siginstall(const sigset_t *guarded)
THREADSAFE Installs, and potentially enables, the global signal handlers for the signals specified by...
enum sig_decision_t sig_decide_t(struct stdc_siginfo *)
The type of the function called when a signal is raised. Returns a decision of how to handle the sign...
union stdc_siginfo_value sig_func_t(union stdc_siginfo_value)
The type of the guarded function.
int siguninstall(void *i)
THREADSAFE Uninstall a previously installed signal guard.
sig_decision_t
The decision taken by the decider function.
@ sig_decision_resume_execution
We have fixed the cause of the signal, please resume execution.
@ sig_decision_invoke_recovery
Thread local signal deciders only: reset the stack and local state to entry to sigguarded(),...
@ sig_decision_next_decider
We have decided to do nothing.
void * signal_decider_create(const sigset_t *guarded, bool callfirst, sig_decide_t decider, union stdc_siginfo_value value)
THREADSAFE NOT REENTRANT Create a global signal continuation decider. Threadsafe with respect to othe...
int sigfillset_asynchronous_debug(sigset_t *set)
THREADSAFE ASYNC-SIGNAL-SAFE Fille the set of debug asynchronous signals for this platform.
bool stdc_raise(int signo, stdc_siginfo_siginfo_t *raw_info, stdc_siginfo_context_t *raw_context)
THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Call OUR currently installed signal decider for a signal (POSIX)...
int signal_decider_destroy(void *decider)
THREADSAFE NOT REENTRANT Destroy a global signal continuation decider. Threadsafe with respect to oth...
int sigfillset_synchronous(sigset_t *set)
THREADSAFE ASYNC-SIGNAL-SAFE Fills the set of synchronous signals for this platform.
ucontext_t stdc_siginfo_context_t
A placeholder type for an OS specific ucontext_t (POSIX) or PCONTEXT (Windows).
void sigfence_force_escaped(int,...)
union stdc_siginfo_value sigguarded(const sigset_t *signals, sig_func_t guarded, sig_recover_t recovery, sig_decide_t decider, union stdc_siginfo_value value)
THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Installs a thread-local signal guard for the calling thread,...
int thrd_raised_signal_error_code_t
Typedef to a system specific error code type.
union stdc_siginfo_value sig_recover_t(const struct stdc_siginfo *)
The type of the function called to recover from a signal being raised in a guarded section.
int siguninstall_system(int version)
THREADSAFE Uninstall a previously system installed signal guard.