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>
51 typedef uint32_t sigset_t;
52 static inline int sigemptyset(sigset_t *ss)
57 static inline int sigfillset(sigset_t *ss)
70 static inline int sigaddset(sigset_t *ss,
const int signo)
72 if(signo >= 1 && signo <= 32)
74 *ss |= (1u << (signo - 1));
78 static inline int sigdelset(sigset_t *ss,
const int signo)
80 if(signo >= 1 && signo <= 32)
82 *ss &= ~(1u << (signo - 1));
86 static inline bool sigismember(
const sigset_t *ss,
const int signo)
88 return (signo >= 1 && signo <= 32) && (*ss & (1u << (signo - 1))) != 0;
95 "wg14_signals: Windows sigset_t must be at least "
96 "32 bits to hold the 32-signal bit set");
110#ifndef WG14_SIGNALS_DISABLE_SIGFENCE_MACRO
111#define WG14_SIGNALS_SIGFENCE_GLUE(x, y) x y
112#define WG14_SIGNALS_SIGFENCE_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, \
113 _7_, _8_, count, ...) \
115#define WG14_SIGNALS_SIGFENCE_EXPAND_ARGS(args) \
116 WG14_SIGNALS_SIGFENCE_RETURN_ARG_COUNT args
126#if defined(__GNUC__) || defined(__clang__)
127#define WG14_SIGNALS_HAVE_VA_OPT 1
128#elif defined(_MSC_VER) && defined(_MSVC_TRADITIONAL) && \
129(0 == _MSVC_TRADITIONAL)
130#if defined(__cplusplus)
131#if defined(_MSVC_LANG) && (_MSVC_LANG >= 202002L)
132#define WG14_SIGNALS_HAVE_VA_OPT 1
135#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
136#define WG14_SIGNALS_HAVE_VA_OPT 1
140#ifdef WG14_SIGNALS_HAVE_VA_OPT
141#define WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(...) \
142 WG14_SIGNALS_SIGFENCE_EXPAND_ARGS( \
143 (__VA_ARGS__ __VA_OPT__(, ) 8, 7, 6, 5, 4, 3, 2, 1, 0))
145#define WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(...) \
146 WG14_SIGNALS_SIGFENCE_EXPAND_ARGS((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
148#define WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO2(name, count) name##count
149#define WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO1(name, count) \
150 WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO2(name, count)
151#define WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO(name, count) \
152 WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO1(name, count)
153#define WG14_SIGNALS_SIGFENCE_CALL_OVERLOAD(name, ...) \
154 WG14_SIGNALS_SIGFENCE_GLUE( \
155 WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO( \
156 name, WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(__VA_ARGS__)), \
174 "wg14_signals: sigfence() argument counting is broken (requires __VA_OPT__ "
175 "on this compiler, or a counting-broken preprocessor)");
177#if (defined(__GNUC__) || defined(__clang__)) && !defined(DISABLE_INLINE_ASM)
185#define WG14_SIGNALS_SIGFENCE_IMPL_0() __asm__ volatile(";" : : : "memory")
186#define WG14_SIGNALS_SIGFENCE_IMPL_1(a) \
187 __asm__ volatile(";" : "+m"(a) : : "memory")
188#define WG14_SIGNALS_SIGFENCE_IMPL_2(a, b) \
189 __asm__ volatile(";" : "+m"(a), "+m"(b) : : "memory")
190#define WG14_SIGNALS_SIGFENCE_IMPL_3(a, b, c) \
191 __asm__ volatile(";" : "+m"(a), "+m"(b), "+m"(c) : : "memory")
192#define WG14_SIGNALS_SIGFENCE_IMPL_4(a, b, c, d) \
193 __asm__ volatile(";" : "+m"(a), "+m"(b), "+m"(c), "+m"(d) : : "memory")
194#define WG14_SIGNALS_SIGFENCE_IMPL_5(a, b, c, d, e) \
195 __asm__ volatile(";" \
196 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e) \
199#define WG14_SIGNALS_SIGFENCE_IMPL_6(a, b, c, d, e, f) \
200 __asm__ volatile(";" \
201 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e), "+m"(f) \
204#define WG14_SIGNALS_SIGFENCE_IMPL_7(a, b, c, d, e, f, g) \
205 __asm__ volatile(";" \
206 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e), "+m"(f), \
210#define WG14_SIGNALS_SIGFENCE_IMPL_8(a, b, c, d, e, f, g, h) \
211 __asm__ volatile(";" \
212 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e), "+m"(f), \
231 static void *
volatile WG14_SIGNALS_PREFIX(sigfence_sink)[9];
232#define WG14_SIGNALS_SIGFENCE_BARRIER() \
233 ((void) (WG14_SIGNALS_PREFIX(sigfence_sink)[8] = \
234 WG14_SIGNALS_PREFIX(sigfence_sink)[8]))
235#define WG14_SIGNALS_SIGFENCE_ESCAPE(a, i) \
238 WG14_SIGNALS_PREFIX(sigfence_sink)[(i)] = (void *) &(a); \
239 (void) *(volatile unsigned char *) &(a); \
241#define WG14_SIGNALS_SIGFENCE_IMPL_0() WG14_SIGNALS_SIGFENCE_BARRIER()
242#define WG14_SIGNALS_SIGFENCE_IMPL_1(a) \
245 WG14_SIGNALS_SIGFENCE_BARRIER(); \
246 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
247 WG14_SIGNALS_SIGFENCE_BARRIER(); \
249#define WG14_SIGNALS_SIGFENCE_IMPL_2(a, b) \
252 WG14_SIGNALS_SIGFENCE_BARRIER(); \
253 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
254 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
255 WG14_SIGNALS_SIGFENCE_BARRIER(); \
257#define WG14_SIGNALS_SIGFENCE_IMPL_3(a, b, c) \
260 WG14_SIGNALS_SIGFENCE_BARRIER(); \
261 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
262 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
263 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
264 WG14_SIGNALS_SIGFENCE_BARRIER(); \
266#define WG14_SIGNALS_SIGFENCE_IMPL_4(a, b, c, d) \
269 WG14_SIGNALS_SIGFENCE_BARRIER(); \
270 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
271 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
272 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
273 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
274 WG14_SIGNALS_SIGFENCE_BARRIER(); \
276#define WG14_SIGNALS_SIGFENCE_IMPL_5(a, b, c, d, e) \
279 WG14_SIGNALS_SIGFENCE_BARRIER(); \
280 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
281 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
282 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
283 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
284 WG14_SIGNALS_SIGFENCE_ESCAPE(e, 4); \
285 WG14_SIGNALS_SIGFENCE_BARRIER(); \
287#define WG14_SIGNALS_SIGFENCE_IMPL_6(a, b, c, d, e, f) \
290 WG14_SIGNALS_SIGFENCE_BARRIER(); \
291 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
292 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
293 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
294 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
295 WG14_SIGNALS_SIGFENCE_ESCAPE(e, 4); \
296 WG14_SIGNALS_SIGFENCE_ESCAPE(f, 5); \
297 WG14_SIGNALS_SIGFENCE_BARRIER(); \
299#define WG14_SIGNALS_SIGFENCE_IMPL_7(a, b, c, d, e, f, g) \
302 WG14_SIGNALS_SIGFENCE_BARRIER(); \
303 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
304 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
305 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
306 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
307 WG14_SIGNALS_SIGFENCE_ESCAPE(e, 4); \
308 WG14_SIGNALS_SIGFENCE_ESCAPE(f, 5); \
309 WG14_SIGNALS_SIGFENCE_ESCAPE(g, 6); \
310 WG14_SIGNALS_SIGFENCE_BARRIER(); \
312#define WG14_SIGNALS_SIGFENCE_IMPL_8(a, b, c, d, e, f, g, h) \
315 WG14_SIGNALS_SIGFENCE_BARRIER(); \
316 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
317 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
318 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
319 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
320 WG14_SIGNALS_SIGFENCE_ESCAPE(e, 4); \
321 WG14_SIGNALS_SIGFENCE_ESCAPE(f, 5); \
322 WG14_SIGNALS_SIGFENCE_ESCAPE(g, 6); \
323 WG14_SIGNALS_SIGFENCE_ESCAPE(h, 7); \
324 WG14_SIGNALS_SIGFENCE_BARRIER(); \
329#define sigfence(...) \
330 WG14_SIGNALS_SIGFENCE_CALL_OVERLOAD(WG14_SIGNALS_SIGFENCE_IMPL_, __VA_ARGS__)
335#pragma warning(disable : 4190)
337#if defined(__clang__) && defined(__cplusplus)
338#pragma clang diagnostic push
339#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
345 union WG14_SIGNALS_PREFIX(stdc_siginfo_value)
349#if defined(__cplusplus)
358 constexpr WG14_SIGNALS_PREFIX(stdc_siginfo_value)(
void *v)
377#elif defined(__FILC__)
397 struct WG14_SIGNALS_PREFIX(sig_global_state_tss_state_per_frame_t);
398 struct WG14_SIGNALS_PREFIX(sighandler_info);
399 struct WG14_SIGNALS_PREFIX(global_signal_decider_t);
404 struct WG14_SIGNALS_PREFIX(stdc_siginfo)
414 union WG14_SIGNALS_PREFIX(
427 struct WG14_SIGNALS_PREFIX(sig_global_state_tss_state_per_frame_t) *
430 struct WG14_SIGNALS_PREFIX(global_signal_decider_t) *
433 void *internal_win_state;
439 typedef union WG14_SIGNALS_PREFIX(stdc_siginfo_value)(WG14_SIGNALS_PREFIX(
444 typedef union WG14_SIGNALS_PREFIX(stdc_siginfo_value)(WG14_SIGNALS_PREFIX(
462 typedef enum WG14_SIGNALS_PREFIX(
sig_decision_t)(WG14_SIGNALS_PREFIX(
463 sig_decide_t))(
struct WG14_SIGNALS_PREFIX(stdc_siginfo) *);
558 union WG14_SIGNALS_PREFIX(stdc_siginfo_value)
561 struct WG14_SIGNALS_PREFIX(sig_global_state_tss_state_per_frame_t);
575 struct WG14_SIGNALS_PREFIX(stdc_siginfo) * rsi);
584 struct WG14_SIGNALS_PREFIX(stdc_siginfo) * rsi);
586#if defined(__clang__) && defined(__cplusplus)
587#pragma clang diagnostic pop
682 const sigset_t *guarded,
bool callfirst,
684 union WG14_SIGNALS_PREFIX(stdc_siginfo_value) value);
701#if WG14_SIGNALS_ENABLE_HEADER_ONLY
703#include "detail/impl/thrd_signal_handle_windows.c.ipp"
705#include "detail/impl/thrd_signal_handle_posix.c.ipp"
#define WG14_SIGNALS_STATIC_ASSERT(cond, msg)
Compile-time assertion, spelled _Static_assert in C11 and static_assert in C++11 (plans/ideas....
#define WG14_SIGNALS_EXTERN
A platform independent subset of siginfo_t.
int signo
The signal raised.
stdc_siginfo_context_t * raw_context
The OS specific ucontext_t (POSIX) or PCONTEXT (Windows).
struct sig_global_state_tss_state_per_frame_t * internal_local_decider
struct global_signal_decider_t * internal_global_decider
struct sighandler_info * internal_sighandler
bool internal_decider_is_abandoned
stdc_siginfo_error_code_t error_code
The system specific error code for this signal, the si_errno code (POSIX) or NTSTATUS code (Windows)....
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...
#define WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(...)
void sigdecider_abandon_resume(struct stdc_siginfo *rsi)
THREADSAFE ASYNC-SIGNAL-SAFE Undoes a prior call of sigdecider_abandon(). Do not call except from the...
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.
int stdc_siginfo_error_code_t
Typedef to a system specific error code type.
sig_decision_t
The decision taken by the decider function.
@ sig_decision_call_recovery
Thread local signal deciders only: reset the stack and local state to entry to sigguarded(),...
@ sig_decision_resume_execution
We have fixed the cause of the signal, please resume execution.
@ 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).
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,...
void sigdecider_abandon(struct stdc_siginfo *rsi)
THREADSAFE ASYNC-SIGNAL-SAFE Lets the decider machinery know you won't be returning into it....
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.