1 #ifndef ZTH_CONTEXT_SIGALTSTACK_H
2 #define ZTH_CONTEXT_SIGALTSTACK_H
12 #ifndef ZTH_CONTEXT_CONTEXT_H
13 # error This file must be included by libzth/context/context.h.
18 # ifdef ZTH_ENABLE_ASAN
19 # error Invalid configuration combination sigaltstack with asan.
24 # include <sys/types.h>
26 # ifdef ZTH_HAVE_PTHREAD
29 # define pthread_yield_np() pthread_yield()
32 # define pthread_sigmask(...) sigprocmask(__VA_ARGS__)
33 # define pthread_kill(...) kill(__VA_ARGS__)
34 # define pthread_self() getpid()
35 # define pthread_yield_np() sched_yield()
41 static void context_global_init()
48 sigaddset(&sigs, SIGUSR1);
54 zth_abort(
"Cannot initialize signals; %s",
err(res).c_str());
73 static void context_trampoline(
int sig)
96 zth_dbg(context,
"Bootstrapping %p", context);
127 sa.sa_handler = &context_trampoline;
128 sigemptyset(&sa.sa_mask);
129 sa.sa_flags = SA_ONSTACK;
130 if(sigaction(SIGUSR1, &sa,
nullptr))
143 sa.sa_handler = SIG_DFL;
144 sigemptyset(&sa.sa_mask);
146 sigaction(SIGUSR1, &sa,
nullptr);
172 ss.ss_size = stack_.
size;
174 # ifdef ZTH_USE_VALGRIND
176 VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(ss.ss_sp, ss.ss_size);
179 # ifdef SS_AUTODISARM
180 ss.ss_flags |= SS_AUTODISARM;
182 if(
unlikely(sigaltstack(&ss, &oss))) {
192 sigaddset(&sigs, SIGUSR1);
194 goto rollback_altstack;
198 goto rollback_altstack;
206 goto rollback_altstack;
212 if(
unlikely(sigaltstack(
nullptr, &ss))) {
214 goto rollback_altstack;
219 # ifndef SS_AUTODISARM
221 ss.ss_flags = SS_DISABLE;
222 if(
unlikely(sigaltstack(&ss,
nullptr))) {
224 goto rollback_altstack;
228 if(
unlikely(!(oss.ss_flags & SS_DISABLE))) {
229 if(sigaltstack(&oss,
nullptr)) {
234 # ifdef ZTH_HAVE_VALGRIND
235 else if(RUNNING_ON_VALGRIND) {
240 dss.ss_sp = dummyAltStack;
241 dss.ss_size =
sizeof(dummyAltStack);
243 if(
unlikely(sigaltstack(&dss,
nullptr))) {
249 VALGRIND_MAKE_MEM_DEFINED(ss.ss_sp, ss.ss_size);
261 # ifdef ZTH_USE_VALGRIND
263 VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(ss.ss_sp, ss.ss_size);
267 if(
unlikely(sigaltstack(
nullptr, &oss))) {
281 # ifdef ZTH_USE_VALGRIND
282 VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(ss.ss_sp, ss.ss_size);
284 if(!(oss.ss_flags & SS_DISABLE))
285 sigaltstack(&oss,
nullptr);
288 return res ? res : EINVAL;
295 siglongjmp(to.m_env, 1);
309 # ifdef ZTH_HAVE_VALGRIND
310 static char dummyAltStack[MINSIGSTKSZ];
316 # ifdef ZTH_HAVE_VALGRIND
317 char Context::dummyAltStack[MINSIGSTKSZ];
sigjmp_buf *volatile m_parent
impl::ContextArch< Context > base
sig_atomic_t volatile m_did_trampoline
static int init() noexcept
void context_switch(Context &to) noexcept
constexpr Context(ContextAttr const &attr) noexcept
static void deinit() noexcept
static void deinit() noexcept
Final system cleanup.
int create() noexcept
Create context.
ContextAttr & attr() noexcept
Return the context attributes, requested by the user.
void destroy() noexcept
Destroy and cleanup context.
Stack const & stackUsable() const noexcept
Return the start of the actual usable stack.
static int init() noexcept
One-time system initialization.
void zth_abort(char const *fmt,...)
Aborts the process after printing the given printf() formatted message.
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
#define ZTH_TLS_DEFINE(type, var, init)
#define ZTH_TLS_MEMBER(type, var)
#define ZTH_TLS_SET(var, value)
void context_entry(Context *context)
string err(int e)
Return a string like strerror() does, but as a zth::string.
#define pthread_sigmask(...)
#define pthread_kill(...)
#define pthread_yield_np()
static bool const Debug
This is a debug build when set to true.
static bool const EnableAssert
When true, enable zth_assert().
static bool const ContextSignals
Take POSIX signal into account when doing a context switch.
#define zth_assert(expr)
assert(), but better integrated in Zth.
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.