1#ifndef ZTH_CONTEXT_SIGALTSTACK_H
2#define ZTH_CONTEXT_SIGALTSTACK_H
9#ifndef ZTH_CONTEXT_CONTEXT_H
10# error This file must be included by libzth/context/context.h.
15# ifdef ZTH_ENABLE_ASAN
16# error Invalid configuration combination sigaltstack with asan.
21# include <sys/types.h>
23# ifdef ZTH_HAVE_PTHREAD
26# define pthread_yield_np() pthread_yield()
29# define pthread_sigmask(...) sigprocmask(__VA_ARGS__)
30# define pthread_kill(...) kill(__VA_ARGS__)
31# define pthread_self() getpid()
32# define pthread_yield_np() sched_yield()
38static void context_global_init()
45 sigaddset(&sigs, SIGUSR1);
51 zth_abort(
"Cannot initialize signals; %s",
err(res).c_str());
70 static void context_trampoline(
int sig)
93 zth_dbg(context,
"Bootstrapping %p", context);
124 sa.sa_handler = &context_trampoline;
125 sigemptyset(&sa.sa_mask);
126 sa.sa_flags = SA_ONSTACK;
127 if(sigaction(SIGUSR1, &sa,
nullptr))
140 sa.sa_handler = SIG_DFL;
141 sigemptyset(&sa.sa_mask);
143 sigaction(SIGUSR1, &sa,
nullptr);
169 ss.ss_size = stack_.
size;
171# ifdef ZTH_USE_VALGRIND
173 VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(ss.ss_sp, ss.ss_size);
177 ss.ss_flags |= SS_AUTODISARM;
179 if(
unlikely(sigaltstack(&ss, &oss))) {
189 sigaddset(&sigs, SIGUSR1);
191 goto rollback_altstack;
195 goto rollback_altstack;
203 goto rollback_altstack;
209 if(
unlikely(sigaltstack(
nullptr, &ss))) {
211 goto rollback_altstack;
216# ifndef SS_AUTODISARM
218 ss.ss_flags = SS_DISABLE;
219 if(
unlikely(sigaltstack(&ss,
nullptr))) {
221 goto rollback_altstack;
225 if(
unlikely(!(oss.ss_flags & SS_DISABLE))) {
226 if(sigaltstack(&oss,
nullptr)) {
231# ifdef ZTH_HAVE_VALGRIND
232 else if(RUNNING_ON_VALGRIND) {
237 dss.ss_sp = dummyAltStack;
238 dss.ss_size =
sizeof(dummyAltStack);
240 if(
unlikely(sigaltstack(&dss,
nullptr))) {
246 VALGRIND_MAKE_MEM_DEFINED(ss.ss_sp, ss.ss_size);
258# ifdef ZTH_USE_VALGRIND
260 VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(ss.ss_sp, ss.ss_size);
264 if(
unlikely(sigaltstack(
nullptr, &oss))) {
278# ifdef ZTH_USE_VALGRIND
279 VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(ss.ss_sp, ss.ss_size);
281 if(!(oss.ss_flags & SS_DISABLE))
282 sigaltstack(&oss,
nullptr);
285 return res ? res : EINVAL;
292 siglongjmp(to.m_env, 1);
306# ifdef ZTH_HAVE_VALGRIND
307 static char dummyAltStack[MINSIGSTKSZ];
313# ifdef ZTH_HAVE_VALGRIND
314char 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.
Stack const & stackUsable() const noexcept
Return the start of the actual usable stack.
void destroy() noexcept
Destroy and cleanup context.
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.