signal.c revision c9a3072d13e4b8a6549ecc1db6390a55c7ee2ddf
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2004 PathScale, Inc
3ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Licensed under the GPL
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
70805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov#include <stdlib.h>
80805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov#include <stdarg.h>
9ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <errno.h>
10ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <signal.h>
11ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include <strings.h>
12cff65c4f0ea6662124bbb7bf3806e5df1c6d735dGennady Sharapov#include "os.h"
13ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include "sysdep/barrier.h"
14ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include "sysdep/sigcontext.h"
15ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include "user.h"
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike/*
1861b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike * These are the asynchronous signals.  SIGPROF is excluded because we want to
191d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * be able to profile all of UML, not just the non-critical sections.  If
201d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * profiling is not thread-safe, then that is not my problem.  We can disable
211d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * profiling when SMP is enabled in that case.
221d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */
231d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGIO_BIT 0
241d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGIO_MASK (1 << SIGIO_BIT)
251d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
261d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGVTALRM_BIT 1
271d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
281d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
29ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike/*
30ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * These are used by both the signal handlers and
3153b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * block/unblock_signals.  I don't want modifications cached in a
3253b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * register - they must go straight to memory.
3353b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike */
3453b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dikestatic volatile int signals_enabled = 1;
3553b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dikestatic volatile int pending = 0;
361d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
374b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dikevoid sig_handler(int sig, struct sigcontext *sc)
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
391d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	int enabled;
401d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
411d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	enabled = signals_enabled;
42ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (!enabled && (sig == SIGIO)) {
431d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		pending |= SIGIO_MASK;
441d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		return;
451d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	}
461d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
471d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	block_signals();
481d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
496aa802ce6acc9b1f0b34114b3f7c21c84872cc3aJeff Dike	sig_handler_common_skas(sig, sc);
501d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
511d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	set_signals(enabled);
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dikestatic void real_alarm_handler(struct sigcontext *sc)
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5677bf4400319db9d2a8af6b00c2be6faa0f3d07cbJeff Dike	struct uml_pt_regs regs;
572ea5bc5e5bb51492f189bba44045e0de7decf4a0Jeff Dike
58ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (sc != NULL)
592ea5bc5e5bb51492f189bba44045e0de7decf4a0Jeff Dike		copy_sc(&regs, sc);
6077bf4400319db9d2a8af6b00c2be6faa0f3d07cbJeff Dike	regs.is_user = 0;
612ea5bc5e5bb51492f189bba44045e0de7decf4a0Jeff Dike	unblock_signals();
6261b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike	timer_handler(SIGVTALRM, &regs);
631d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike}
641d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
654b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dikevoid alarm_handler(int sig, struct sigcontext *sc)
661d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike{
671d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	int enabled;
681d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
691d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	enabled = signals_enabled;
70ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (!signals_enabled) {
7161b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike		pending |= SIGVTALRM_MASK;
721d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		return;
731d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	}
741d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
751d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	block_signals();
761d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
7761b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike	real_alarm_handler(sc);
781d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	set_signals(enabled);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8178a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dikevoid timer_init(void)
8278a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike{
8378a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike	set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
8461b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
8578a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike}
8678a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike
870805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid set_sigstack(void *sig_stack, int size)
880805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{
890805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	stack_t stack = ((stack_t) { .ss_flags	= 0,
900805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov				     .ss_sp	= (__ptr_t) sig_stack,
910805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov				     .ss_size 	= size - sizeof(void *) });
920805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
93ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (sigaltstack(&stack, NULL) != 0)
940805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov		panic("enabling signal stack failed, errno = %d\n", errno);
950805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov}
960805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
970805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid remove_sigstack(void)
980805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{
990805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	stack_t stack = ((stack_t) { .ss_flags	= SS_DISABLE,
1000805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov				     .ss_sp	= NULL,
1010805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov				     .ss_size	= 0 });
1020805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
103ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (sigaltstack(&stack, NULL) != 0)
1040805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov		panic("disabling signal stack failed, errno = %d\n", errno);
1050805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov}
1060805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
1074b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dikevoid (*handlers[_NSIG])(int sig, struct sigcontext *sc);
1084b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike
109c14b84949e127560084c7c56b365931c71c60768Jeff Dikevoid handle_signal(int sig, struct sigcontext *sc)
110c14b84949e127560084c7c56b365931c71c60768Jeff Dike{
111508a92741a105e2e3d466cd727fb73154ebf08deJeff Dike	unsigned long pending = 1UL << sig;
112c14b84949e127560084c7c56b365931c71c60768Jeff Dike
113c14b84949e127560084c7c56b365931c71c60768Jeff Dike	do {
114c14b84949e127560084c7c56b365931c71c60768Jeff Dike		int nested, bail;
115c14b84949e127560084c7c56b365931c71c60768Jeff Dike
116c14b84949e127560084c7c56b365931c71c60768Jeff Dike		/*
117c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * pending comes back with one bit set for each
118c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * interrupt that arrived while setting up the stack,
119c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * plus a bit for this interrupt, plus the zero bit is
120c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * set if this is a nested interrupt.
121c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * If bail is true, then we interrupted another
122c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * handler setting up the stack.  In this case, we
123c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * have to return, and the upper handler will deal
124c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * with this interrupt.
125c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 */
126508a92741a105e2e3d466cd727fb73154ebf08deJeff Dike		bail = to_irq_stack(&pending);
127ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		if (bail)
128c14b84949e127560084c7c56b365931c71c60768Jeff Dike			return;
129c14b84949e127560084c7c56b365931c71c60768Jeff Dike
130c14b84949e127560084c7c56b365931c71c60768Jeff Dike		nested = pending & 1;
131c14b84949e127560084c7c56b365931c71c60768Jeff Dike		pending &= ~1;
132c14b84949e127560084c7c56b365931c71c60768Jeff Dike
133ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		while ((sig = ffs(pending)) != 0){
134c14b84949e127560084c7c56b365931c71c60768Jeff Dike			sig--;
135c14b84949e127560084c7c56b365931c71c60768Jeff Dike			pending &= ~(1 << sig);
136c14b84949e127560084c7c56b365931c71c60768Jeff Dike			(*handlers[sig])(sig, sc);
137c14b84949e127560084c7c56b365931c71c60768Jeff Dike		}
138c14b84949e127560084c7c56b365931c71c60768Jeff Dike
139ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		/*
140ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		 * Again, pending comes back with a mask of signals
141c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * that arrived while tearing down the stack.  If this
142c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * is non-zero, we just go back, set up the stack
143c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 * again, and handle the new interrupts.
144c14b84949e127560084c7c56b365931c71c60768Jeff Dike		 */
145ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		if (!nested)
146c14b84949e127560084c7c56b365931c71c60768Jeff Dike			pending = from_irq_stack(nested);
147ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	} while (pending);
148c14b84949e127560084c7c56b365931c71c60768Jeff Dike}
149c14b84949e127560084c7c56b365931c71c60768Jeff Dike
1504b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dikeextern void hard_handler(int sig);
1514b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike
1520805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid set_handler(int sig, void (*handler)(int), int flags, ...)
1530805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{
1540805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	struct sigaction action;
1550805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	va_list ap;
1561d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	sigset_t sig_mask;
1570805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	int mask;
1580805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
1594b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike	handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
1604b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike	action.sa_handler = hard_handler;
1614b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike
1620805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	sigemptyset(&action.sa_mask);
1634b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike
1644b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike	va_start(ap, flags);
165ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	while ((mask = va_arg(ap, int)) != -1)
1660805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov		sigaddset(&action.sa_mask, mask);
1670805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	va_end(ap);
1684b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike
1690805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	action.sa_flags = flags;
1700805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	action.sa_restorer = NULL;
171ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (sigaction(sig, &action, NULL) < 0)
1721d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		panic("sigaction failed - errno = %d\n", errno);
1731d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
1741d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	sigemptyset(&sig_mask);
1751d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	sigaddset(&sig_mask, sig);
176ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
1771d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		panic("sigprocmask failed - errno = %d\n", errno);
1780805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov}
1790805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
1800805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovint change_sig(int signal, int on)
1810805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{
1820805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	sigset_t sigset, old;
1830805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
1840805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	sigemptyset(&sigset);
1850805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	sigaddset(&sigset, signal);
186c9a3072d13e4b8a6549ecc1db6390a55c7ee2ddfWANG Cong	if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old) < 0)
187c9a3072d13e4b8a6549ecc1db6390a55c7ee2ddfWANG Cong		return -errno;
188ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	return !sigismember(&old, signal);
1890805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov}
1900805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
1910805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid block_signals(void)
1920805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{
1931d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	signals_enabled = 0;
194ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	/*
195ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	 * This must return with signals disabled, so this barrier
19653b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike	 * ensures that writes are flushed out before the return.
19753b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike	 * This might matter if gcc figures out how to inline this and
19853b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike	 * decides to shuffle this code into the caller.
19953b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike	 */
20053b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike	mb();
2010805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov}
2020805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
2030805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid unblock_signals(void)
2040805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{
2051d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	int save_pending;
2060805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
207ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (signals_enabled == 1)
2081d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		return;
2090805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
210ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	/*
211ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	 * We loop because the IRQ handler returns with interrupts off.  So,
2121d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	 * interrupts may have arrived and we need to re-enable them and
2131d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	 * recheck pending.
2141d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	 */
215ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	while(1) {
216ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		/*
217ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		 * Save and reset save_pending after enabling signals.  This
2181d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		 * way, pending won't be changed while we're reading it.
2191d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		 */
2201d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		signals_enabled = 1;
2211d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
222ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		/*
223ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		 * Setting signals_enabled and reading pending must
22453b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike		 * happen in this order.
22553b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike		 */
22653b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike		mb();
22753b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike
2281d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		save_pending = pending;
229ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		if (save_pending == 0) {
230ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike			/*
231ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike			 * This must return with signals enabled, so
23253b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike			 * this barrier ensures that writes are
23353b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike			 * flushed out before the return.  This might
23453b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike			 * matter if gcc figures out how to inline
23553b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike			 * this (unlikely, given its size) and decides
23653b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike			 * to shuffle this code into the caller.
23753b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike			 */
23853b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike			mb();
2391d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike			return;
24053b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike		}
2411d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
2421d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		pending = 0;
2431d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
244ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		/*
245ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		 * We have pending interrupts, so disable signals, as the
2461d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		 * handlers expect them off when they are called.  They will
2471d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		 * be enabled again above.
2481d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		 */
2491d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
2501d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		signals_enabled = 0;
2511d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
252ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		/*
253ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		 * Deal with SIGIO first because the alarm handler might
2541d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		 * schedule, leaving the pending SIGIO stranded until we come
2551d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		 * back here.
2561d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		 */
257ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		if (save_pending & SIGIO_MASK)
2586aa802ce6acc9b1f0b34114b3f7c21c84872cc3aJeff Dike			sig_handler_common_skas(SIGIO, NULL);
2591d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike
260ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike		if (save_pending & SIGVTALRM_MASK)
26161b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike			real_alarm_handler(NULL);
2621d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	}
2630805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov}
2640805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
2650805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovint get_signals(void)
2660805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{
2671d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	return signals_enabled;
2680805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov}
2690805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
2700805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovint set_signals(int enable)
2710805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{
2720805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov	int ret;
273ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (signals_enabled == enable)
2741d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		return enable;
2750805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
2761d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	ret = signals_enabled;
277ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike	if (enable)
2781d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike		unblock_signals();
2791d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	else block_signals();
2800805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov
2811d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike	return ret;
2820805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov}
283