#define _XOPEN_SOURCE 600L
#include <ucontext.h>
#include <errno.h>
#if defined(__x86_64__) || defined(__i386__)
#include <sys/resource.h>
#include <stddef.h>
#include <stdint.h>
#include <signal.h>
extern int __sigaltstack(const stack_t * __restrict, stack_t * __restrict);
#ifdef __DYNAMIC__
extern int __in_sigtramp;
#endif
__attribute__((visibility("hidden")))
mcontext_t
getmcontext(ucontext_t *uctx, void *sp)
{
mcontext_t mctx = (mcontext_t)&uctx->__mcontext_data;
size_t stacksize = 0;
stack_t stack;
uctx->uc_stack.ss_sp = sp;
uctx->uc_stack.ss_flags = 0;
if (0 == __sigaltstack(NULL, &stack)) {
if (stack.ss_flags & SS_ONSTACK) {
uctx->uc_stack = stack;
stacksize = stack.ss_size;
}
}
if (stacksize == 0) {
struct rlimit rlim;
if (0 == getrlimit(RLIMIT_STACK, &rlim))
stacksize = rlim.rlim_cur;
}
uctx->uc_stack.ss_size = stacksize;
if (uctx->uc_mcontext != mctx) {
uctx->uc_mcontext = mctx;
#ifdef __DYNAMIC__
uctx->uc_link = (ucontext_t*)(uintptr_t)__in_sigtramp;
#else
uctx->uc_link = 0;
#endif
}
sigprocmask(0, NULL, &uctx->uc_sigmask);
return mctx;
}
#else
int
getcontext(ucontext_t *u)
{
errno = ENOTSUP;
return -1;
}
#endif