18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
48c2ecf20Sopenharmony_ci * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
58c2ecf20Sopenharmony_ci * Copyright (C) 2004 PathScale, Inc
68c2ecf20Sopenharmony_ci * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <stdlib.h>
108c2ecf20Sopenharmony_ci#include <stdarg.h>
118c2ecf20Sopenharmony_ci#include <errno.h>
128c2ecf20Sopenharmony_ci#include <signal.h>
138c2ecf20Sopenharmony_ci#include <string.h>
148c2ecf20Sopenharmony_ci#include <strings.h>
158c2ecf20Sopenharmony_ci#include <as-layout.h>
168c2ecf20Sopenharmony_ci#include <kern_util.h>
178c2ecf20Sopenharmony_ci#include <os.h>
188c2ecf20Sopenharmony_ci#include <sysdep/mcontext.h>
198c2ecf20Sopenharmony_ci#include <um_malloc.h>
208c2ecf20Sopenharmony_ci#include <sys/ucontext.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_civoid (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
238c2ecf20Sopenharmony_ci	[SIGTRAP]	= relay_signal,
248c2ecf20Sopenharmony_ci	[SIGFPE]	= relay_signal,
258c2ecf20Sopenharmony_ci	[SIGILL]	= relay_signal,
268c2ecf20Sopenharmony_ci	[SIGWINCH]	= winch,
278c2ecf20Sopenharmony_ci	[SIGBUS]	= bus_handler,
288c2ecf20Sopenharmony_ci	[SIGSEGV]	= segv_handler,
298c2ecf20Sopenharmony_ci	[SIGIO]		= sigio_handler,
308c2ecf20Sopenharmony_ci};
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	struct uml_pt_regs r;
358c2ecf20Sopenharmony_ci	int save_errno = errno;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	r.is_user = 0;
388c2ecf20Sopenharmony_ci	if (sig == SIGSEGV) {
398c2ecf20Sopenharmony_ci		/* For segfaults, we want the data from the sigcontext. */
408c2ecf20Sopenharmony_ci		get_regs_from_mc(&r, mc);
418c2ecf20Sopenharmony_ci		GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
428c2ecf20Sopenharmony_ci	}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	/* enable signals if sig isn't IRQ signal */
458c2ecf20Sopenharmony_ci	if ((sig != SIGIO) && (sig != SIGWINCH))
468c2ecf20Sopenharmony_ci		unblock_signals_trace();
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	(*sig_info[sig])(sig, si, &r);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	errno = save_errno;
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/*
548c2ecf20Sopenharmony_ci * These are the asynchronous signals.  SIGPROF is excluded because we want to
558c2ecf20Sopenharmony_ci * be able to profile all of UML, not just the non-critical sections.  If
568c2ecf20Sopenharmony_ci * profiling is not thread-safe, then that is not my problem.  We can disable
578c2ecf20Sopenharmony_ci * profiling when SMP is enabled in that case.
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_ci#define SIGIO_BIT 0
608c2ecf20Sopenharmony_ci#define SIGIO_MASK (1 << SIGIO_BIT)
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define SIGALRM_BIT 1
638c2ecf20Sopenharmony_ci#define SIGALRM_MASK (1 << SIGALRM_BIT)
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic int signals_enabled;
668c2ecf20Sopenharmony_cistatic unsigned int signals_pending;
678c2ecf20Sopenharmony_cistatic unsigned int signals_active = 0;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_civoid sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	int enabled;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	enabled = signals_enabled;
748c2ecf20Sopenharmony_ci	if (!enabled && (sig == SIGIO)) {
758c2ecf20Sopenharmony_ci		signals_pending |= SIGIO_MASK;
768c2ecf20Sopenharmony_ci		return;
778c2ecf20Sopenharmony_ci	}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	block_signals_trace();
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	sig_handler_common(sig, si, mc);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	set_signals_trace(enabled);
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic void timer_real_alarm_handler(mcontext_t *mc)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	struct uml_pt_regs regs;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	if (mc != NULL)
918c2ecf20Sopenharmony_ci		get_regs_from_mc(&regs, mc);
928c2ecf20Sopenharmony_ci	else
938c2ecf20Sopenharmony_ci		memset(&regs, 0, sizeof(regs));
948c2ecf20Sopenharmony_ci	timer_handler(SIGALRM, NULL, &regs);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_civoid timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	int enabled;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	enabled = signals_enabled;
1028c2ecf20Sopenharmony_ci	if (!signals_enabled) {
1038c2ecf20Sopenharmony_ci		signals_pending |= SIGALRM_MASK;
1048c2ecf20Sopenharmony_ci		return;
1058c2ecf20Sopenharmony_ci	}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	block_signals_trace();
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	signals_active |= SIGALRM_MASK;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	timer_real_alarm_handler(mc);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	signals_active &= ~SIGALRM_MASK;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	set_signals_trace(enabled);
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_civoid deliver_alarm(void) {
1198c2ecf20Sopenharmony_ci    timer_alarm_handler(SIGALRM, NULL, NULL);
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_civoid timer_set_signal_handler(void)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	set_handler(SIGALRM);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_civoid set_sigstack(void *sig_stack, int size)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	stack_t stack = {
1308c2ecf20Sopenharmony_ci		.ss_flags = 0,
1318c2ecf20Sopenharmony_ci		.ss_sp = sig_stack,
1328c2ecf20Sopenharmony_ci		.ss_size = size - sizeof(void *)
1338c2ecf20Sopenharmony_ci	};
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	if (sigaltstack(&stack, NULL) != 0)
1368c2ecf20Sopenharmony_ci		panic("enabling signal stack failed, errno = %d\n", errno);
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic void sigusr1_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	uml_pm_wake();
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_civoid register_pm_wake_signal(void)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	set_handler(SIGUSR1);
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistatic void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
1508c2ecf20Sopenharmony_ci	[SIGSEGV] = sig_handler,
1518c2ecf20Sopenharmony_ci	[SIGBUS] = sig_handler,
1528c2ecf20Sopenharmony_ci	[SIGILL] = sig_handler,
1538c2ecf20Sopenharmony_ci	[SIGFPE] = sig_handler,
1548c2ecf20Sopenharmony_ci	[SIGTRAP] = sig_handler,
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	[SIGIO] = sig_handler,
1578c2ecf20Sopenharmony_ci	[SIGWINCH] = sig_handler,
1588c2ecf20Sopenharmony_ci	[SIGALRM] = timer_alarm_handler,
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	[SIGUSR1] = sigusr1_handler,
1618c2ecf20Sopenharmony_ci};
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic void hard_handler(int sig, siginfo_t *si, void *p)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	ucontext_t *uc = p;
1668c2ecf20Sopenharmony_ci	mcontext_t *mc = &uc->uc_mcontext;
1678c2ecf20Sopenharmony_ci	unsigned long pending = 1UL << sig;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	do {
1708c2ecf20Sopenharmony_ci		int nested, bail;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci		/*
1738c2ecf20Sopenharmony_ci		 * pending comes back with one bit set for each
1748c2ecf20Sopenharmony_ci		 * interrupt that arrived while setting up the stack,
1758c2ecf20Sopenharmony_ci		 * plus a bit for this interrupt, plus the zero bit is
1768c2ecf20Sopenharmony_ci		 * set if this is a nested interrupt.
1778c2ecf20Sopenharmony_ci		 * If bail is true, then we interrupted another
1788c2ecf20Sopenharmony_ci		 * handler setting up the stack.  In this case, we
1798c2ecf20Sopenharmony_ci		 * have to return, and the upper handler will deal
1808c2ecf20Sopenharmony_ci		 * with this interrupt.
1818c2ecf20Sopenharmony_ci		 */
1828c2ecf20Sopenharmony_ci		bail = to_irq_stack(&pending);
1838c2ecf20Sopenharmony_ci		if (bail)
1848c2ecf20Sopenharmony_ci			return;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci		nested = pending & 1;
1878c2ecf20Sopenharmony_ci		pending &= ~1;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci		while ((sig = ffs(pending)) != 0){
1908c2ecf20Sopenharmony_ci			sig--;
1918c2ecf20Sopenharmony_ci			pending &= ~(1 << sig);
1928c2ecf20Sopenharmony_ci			(*handlers[sig])(sig, (struct siginfo *)si, mc);
1938c2ecf20Sopenharmony_ci		}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci		/*
1968c2ecf20Sopenharmony_ci		 * Again, pending comes back with a mask of signals
1978c2ecf20Sopenharmony_ci		 * that arrived while tearing down the stack.  If this
1988c2ecf20Sopenharmony_ci		 * is non-zero, we just go back, set up the stack
1998c2ecf20Sopenharmony_ci		 * again, and handle the new interrupts.
2008c2ecf20Sopenharmony_ci		 */
2018c2ecf20Sopenharmony_ci		if (!nested)
2028c2ecf20Sopenharmony_ci			pending = from_irq_stack(nested);
2038c2ecf20Sopenharmony_ci	} while (pending);
2048c2ecf20Sopenharmony_ci}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_civoid set_handler(int sig)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	struct sigaction action;
2098c2ecf20Sopenharmony_ci	int flags = SA_SIGINFO | SA_ONSTACK;
2108c2ecf20Sopenharmony_ci	sigset_t sig_mask;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	action.sa_sigaction = hard_handler;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	/* block irq ones */
2158c2ecf20Sopenharmony_ci	sigemptyset(&action.sa_mask);
2168c2ecf20Sopenharmony_ci	sigaddset(&action.sa_mask, SIGIO);
2178c2ecf20Sopenharmony_ci	sigaddset(&action.sa_mask, SIGWINCH);
2188c2ecf20Sopenharmony_ci	sigaddset(&action.sa_mask, SIGALRM);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	if (sig == SIGSEGV)
2218c2ecf20Sopenharmony_ci		flags |= SA_NODEFER;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	if (sigismember(&action.sa_mask, sig))
2248c2ecf20Sopenharmony_ci		flags |= SA_RESTART; /* if it's an irq signal */
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	action.sa_flags = flags;
2278c2ecf20Sopenharmony_ci	action.sa_restorer = NULL;
2288c2ecf20Sopenharmony_ci	if (sigaction(sig, &action, NULL) < 0)
2298c2ecf20Sopenharmony_ci		panic("sigaction failed - errno = %d\n", errno);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	sigemptyset(&sig_mask);
2328c2ecf20Sopenharmony_ci	sigaddset(&sig_mask, sig);
2338c2ecf20Sopenharmony_ci	if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
2348c2ecf20Sopenharmony_ci		panic("sigprocmask failed - errno = %d\n", errno);
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ciint change_sig(int signal, int on)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	sigset_t sigset;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	sigemptyset(&sigset);
2428c2ecf20Sopenharmony_ci	sigaddset(&sigset, signal);
2438c2ecf20Sopenharmony_ci	if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
2448c2ecf20Sopenharmony_ci		return -errno;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	return 0;
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_civoid block_signals(void)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	signals_enabled = 0;
2528c2ecf20Sopenharmony_ci	/*
2538c2ecf20Sopenharmony_ci	 * This must return with signals disabled, so this barrier
2548c2ecf20Sopenharmony_ci	 * ensures that writes are flushed out before the return.
2558c2ecf20Sopenharmony_ci	 * This might matter if gcc figures out how to inline this and
2568c2ecf20Sopenharmony_ci	 * decides to shuffle this code into the caller.
2578c2ecf20Sopenharmony_ci	 */
2588c2ecf20Sopenharmony_ci	barrier();
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_civoid unblock_signals(void)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	int save_pending;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	if (signals_enabled == 1)
2668c2ecf20Sopenharmony_ci		return;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	signals_enabled = 1;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	/*
2718c2ecf20Sopenharmony_ci	 * We loop because the IRQ handler returns with interrupts off.  So,
2728c2ecf20Sopenharmony_ci	 * interrupts may have arrived and we need to re-enable them and
2738c2ecf20Sopenharmony_ci	 * recheck signals_pending.
2748c2ecf20Sopenharmony_ci	 */
2758c2ecf20Sopenharmony_ci	while (1) {
2768c2ecf20Sopenharmony_ci		/*
2778c2ecf20Sopenharmony_ci		 * Save and reset save_pending after enabling signals.  This
2788c2ecf20Sopenharmony_ci		 * way, signals_pending won't be changed while we're reading it.
2798c2ecf20Sopenharmony_ci		 *
2808c2ecf20Sopenharmony_ci		 * Setting signals_enabled and reading signals_pending must
2818c2ecf20Sopenharmony_ci		 * happen in this order, so have the barrier here.
2828c2ecf20Sopenharmony_ci		 */
2838c2ecf20Sopenharmony_ci		barrier();
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci		save_pending = signals_pending;
2868c2ecf20Sopenharmony_ci		if (save_pending == 0)
2878c2ecf20Sopenharmony_ci			return;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci		signals_pending = 0;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci		/*
2928c2ecf20Sopenharmony_ci		 * We have pending interrupts, so disable signals, as the
2938c2ecf20Sopenharmony_ci		 * handlers expect them off when they are called.  They will
2948c2ecf20Sopenharmony_ci		 * be enabled again above. We need to trace this, as we're
2958c2ecf20Sopenharmony_ci		 * expected to be enabling interrupts already, but any more
2968c2ecf20Sopenharmony_ci		 * tracing that happens inside the handlers we call for the
2978c2ecf20Sopenharmony_ci		 * pending signals will mess up the tracing state.
2988c2ecf20Sopenharmony_ci		 */
2998c2ecf20Sopenharmony_ci		signals_enabled = 0;
3008c2ecf20Sopenharmony_ci		um_trace_signals_off();
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci		/*
3038c2ecf20Sopenharmony_ci		 * Deal with SIGIO first because the alarm handler might
3048c2ecf20Sopenharmony_ci		 * schedule, leaving the pending SIGIO stranded until we come
3058c2ecf20Sopenharmony_ci		 * back here.
3068c2ecf20Sopenharmony_ci		 *
3078c2ecf20Sopenharmony_ci		 * SIGIO's handler doesn't use siginfo or mcontext,
3088c2ecf20Sopenharmony_ci		 * so they can be NULL.
3098c2ecf20Sopenharmony_ci		 */
3108c2ecf20Sopenharmony_ci		if (save_pending & SIGIO_MASK)
3118c2ecf20Sopenharmony_ci			sig_handler_common(SIGIO, NULL, NULL);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci		/* Do not reenter the handler */
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci		if ((save_pending & SIGALRM_MASK) && (!(signals_active & SIGALRM_MASK)))
3168c2ecf20Sopenharmony_ci			timer_real_alarm_handler(NULL);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci		/* Rerun the loop only if there is still pending SIGIO and not in TIMER handler */
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci		if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
3218c2ecf20Sopenharmony_ci			return;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci		/* Re-enable signals and trace that we're doing so. */
3248c2ecf20Sopenharmony_ci		um_trace_signals_on();
3258c2ecf20Sopenharmony_ci		signals_enabled = 1;
3268c2ecf20Sopenharmony_ci	}
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ciint get_signals(void)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci	return signals_enabled;
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ciint set_signals(int enable)
3358c2ecf20Sopenharmony_ci{
3368c2ecf20Sopenharmony_ci	int ret;
3378c2ecf20Sopenharmony_ci	if (signals_enabled == enable)
3388c2ecf20Sopenharmony_ci		return enable;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	ret = signals_enabled;
3418c2ecf20Sopenharmony_ci	if (enable)
3428c2ecf20Sopenharmony_ci		unblock_signals();
3438c2ecf20Sopenharmony_ci	else block_signals();
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	return ret;
3468c2ecf20Sopenharmony_ci}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ciint set_signals_trace(int enable)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	int ret;
3518c2ecf20Sopenharmony_ci	if (signals_enabled == enable)
3528c2ecf20Sopenharmony_ci		return enable;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	ret = signals_enabled;
3558c2ecf20Sopenharmony_ci	if (enable)
3568c2ecf20Sopenharmony_ci		unblock_signals_trace();
3578c2ecf20Sopenharmony_ci	else
3588c2ecf20Sopenharmony_ci		block_signals_trace();
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	return ret;
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ciint os_is_signal_stack(void)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	stack_t ss;
3668c2ecf20Sopenharmony_ci	sigaltstack(NULL, &ss);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	return ss.ss_flags & SS_ONSTACK;
3698c2ecf20Sopenharmony_ci}
370