signal.c revision ab1c0cc7c96c17ea903ca6d3e42e7d2696b32b6c
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> 1275ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike#include "as-layout.h" 13edea138584d7586a3b93b6d5ab5ec021d18e11e9Jeff Dike#include "kern_util.h" 14cff65c4f0ea6662124bbb7bf3806e5df1c6d735dGennady Sharapov#include "os.h" 15fe2cc53ee013a4d4d0317d418e7019fe6533a5a8Jeff Dike#include "process.h" 16ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike#include "sysdep/barrier.h" 17ab1c0cc7c96c17ea903ca6d3e42e7d2696b32b6cAl Viro#include "sysdep/mcontext.h" 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1975ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dikevoid (*sig_info[NSIG])(int, struct uml_pt_regs *) = { 2075ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGTRAP] = relay_signal, 2175ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGFPE] = relay_signal, 2275ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGILL] = relay_signal, 2375ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGWINCH] = winch, 2475ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGBUS] = bus_handler, 2575ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGSEGV] = segv_handler, 2675ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGIO] = sigio_handler, 2775ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGVTALRM] = timer_handler }; 2875ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 29248b74c79ebb9fb55e146797a808836d90418c4bAl Virostatic void sig_handler_common(int sig, mcontext_t *mc) 3075ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike{ 31e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike struct uml_pt_regs r; 32e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike int save_errno = errno; 3375ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 34e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike r.is_user = 0; 3575ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike if (sig == SIGSEGV) { 36e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike /* For segfaults, we want the data from the sigcontext. */ 37ab1c0cc7c96c17ea903ca6d3e42e7d2696b32b6cAl Viro get_regs_from_mc(&r, mc); 38248b74c79ebb9fb55e146797a808836d90418c4bAl Viro GET_FAULTINFO_FROM_MC(r.faultinfo, mc); 39e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike } 4075ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 41e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike /* enable signals if sig isn't IRQ signal */ 4275ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) 4375ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike unblock_signals(); 4475ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 45e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike (*sig_info[sig])(sig, &r); 4675ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 4775ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike errno = save_errno; 4875ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike} 4975ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 50ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike/* 5161b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike * These are the asynchronous signals. SIGPROF is excluded because we want to 521d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * be able to profile all of UML, not just the non-critical sections. If 531d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * profiling is not thread-safe, then that is not my problem. We can disable 541d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * profiling when SMP is enabled in that case. 551d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 561d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGIO_BIT 0 571d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGIO_MASK (1 << SIGIO_BIT) 581d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 591d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGVTALRM_BIT 1 601d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) 611d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 62fce8c41c9f68b9af36f3076bae8f1d469a6e7aabJeff Dikestatic int signals_enabled; 63cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dikestatic unsigned int signals_pending; 641d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 65248b74c79ebb9fb55e146797a808836d90418c4bAl Virovoid sig_handler(int sig, mcontext_t *mc) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 671d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike int enabled; 681d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 691d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike enabled = signals_enabled; 70ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!enabled && (sig == SIGIO)) { 71cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike signals_pending |= SIGIO_MASK; 721d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return; 731d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike } 741d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 751d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike block_signals(); 761d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 77248b74c79ebb9fb55e146797a808836d90418c4bAl Viro sig_handler_common(sig, mc); 781d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 791d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike set_signals(enabled); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 82248b74c79ebb9fb55e146797a808836d90418c4bAl Virostatic void real_alarm_handler(mcontext_t *mc) 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8477bf4400319db9d2a8af6b00c2be6faa0f3d07cbJeff Dike struct uml_pt_regs regs; 852ea5bc5e5bb51492f189bba44045e0de7decf4a0Jeff Dike 86248b74c79ebb9fb55e146797a808836d90418c4bAl Viro if (mc != NULL) 87ab1c0cc7c96c17ea903ca6d3e42e7d2696b32b6cAl Viro get_regs_from_mc(®s, mc); 8877bf4400319db9d2a8af6b00c2be6faa0f3d07cbJeff Dike regs.is_user = 0; 892ea5bc5e5bb51492f189bba44045e0de7decf4a0Jeff Dike unblock_signals(); 9061b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike timer_handler(SIGVTALRM, ®s); 911d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike} 921d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 93248b74c79ebb9fb55e146797a808836d90418c4bAl Virovoid alarm_handler(int sig, mcontext_t *mc) 941d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike{ 951d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike int enabled; 961d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 971d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike enabled = signals_enabled; 98ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!signals_enabled) { 99cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike signals_pending |= SIGVTALRM_MASK; 1001d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return; 1011d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike } 1021d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 1031d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike block_signals(); 1041d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 105248b74c79ebb9fb55e146797a808836d90418c4bAl Viro real_alarm_handler(mc); 1061d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike set_signals(enabled); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10978a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dikevoid timer_init(void) 11078a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike{ 11100361683ce562402a189362f43370a459b166645Al Viro set_handler(SIGVTALRM); 11278a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike} 11378a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike 1140805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid set_sigstack(void *sig_stack, int size) 1150805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 1160805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov stack_t stack = ((stack_t) { .ss_flags = 0, 1170805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov .ss_sp = (__ptr_t) sig_stack, 1180805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov .ss_size = size - sizeof(void *) }); 1190805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 120ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (sigaltstack(&stack, NULL) != 0) 1210805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov panic("enabling signal stack failed, errno = %d\n", errno); 1220805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 1230805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 124248b74c79ebb9fb55e146797a808836d90418c4bAl Virostatic void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { 12500361683ce562402a189362f43370a459b166645Al Viro [SIGSEGV] = sig_handler, 12600361683ce562402a189362f43370a459b166645Al Viro [SIGBUS] = sig_handler, 12700361683ce562402a189362f43370a459b166645Al Viro [SIGILL] = sig_handler, 12800361683ce562402a189362f43370a459b166645Al Viro [SIGFPE] = sig_handler, 12900361683ce562402a189362f43370a459b166645Al Viro [SIGTRAP] = sig_handler, 13000361683ce562402a189362f43370a459b166645Al Viro 13100361683ce562402a189362f43370a459b166645Al Viro [SIGIO] = sig_handler, 13200361683ce562402a189362f43370a459b166645Al Viro [SIGWINCH] = sig_handler, 13300361683ce562402a189362f43370a459b166645Al Viro [SIGVTALRM] = alarm_handler 13400361683ce562402a189362f43370a459b166645Al Viro}; 1354b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike 136248b74c79ebb9fb55e146797a808836d90418c4bAl Viro 137248b74c79ebb9fb55e146797a808836d90418c4bAl Virostatic void hard_handler(int sig, siginfo_t *info, void *p) 138c14b84949e127560084c7c56b365931c71c60768Jeff Dike{ 139248b74c79ebb9fb55e146797a808836d90418c4bAl Viro struct ucontext *uc = p; 140248b74c79ebb9fb55e146797a808836d90418c4bAl Viro mcontext_t *mc = &uc->uc_mcontext; 141508a92741a105e2e3d466cd727fb73154ebf08deJeff Dike unsigned long pending = 1UL << sig; 142c14b84949e127560084c7c56b365931c71c60768Jeff Dike 143c14b84949e127560084c7c56b365931c71c60768Jeff Dike do { 144c14b84949e127560084c7c56b365931c71c60768Jeff Dike int nested, bail; 145c14b84949e127560084c7c56b365931c71c60768Jeff Dike 146c14b84949e127560084c7c56b365931c71c60768Jeff Dike /* 147c14b84949e127560084c7c56b365931c71c60768Jeff Dike * pending comes back with one bit set for each 148c14b84949e127560084c7c56b365931c71c60768Jeff Dike * interrupt that arrived while setting up the stack, 149c14b84949e127560084c7c56b365931c71c60768Jeff Dike * plus a bit for this interrupt, plus the zero bit is 150c14b84949e127560084c7c56b365931c71c60768Jeff Dike * set if this is a nested interrupt. 151c14b84949e127560084c7c56b365931c71c60768Jeff Dike * If bail is true, then we interrupted another 152c14b84949e127560084c7c56b365931c71c60768Jeff Dike * handler setting up the stack. In this case, we 153c14b84949e127560084c7c56b365931c71c60768Jeff Dike * have to return, and the upper handler will deal 154c14b84949e127560084c7c56b365931c71c60768Jeff Dike * with this interrupt. 155c14b84949e127560084c7c56b365931c71c60768Jeff Dike */ 156508a92741a105e2e3d466cd727fb73154ebf08deJeff Dike bail = to_irq_stack(&pending); 157ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (bail) 158c14b84949e127560084c7c56b365931c71c60768Jeff Dike return; 159c14b84949e127560084c7c56b365931c71c60768Jeff Dike 160c14b84949e127560084c7c56b365931c71c60768Jeff Dike nested = pending & 1; 161c14b84949e127560084c7c56b365931c71c60768Jeff Dike pending &= ~1; 162c14b84949e127560084c7c56b365931c71c60768Jeff Dike 163ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike while ((sig = ffs(pending)) != 0){ 164c14b84949e127560084c7c56b365931c71c60768Jeff Dike sig--; 165c14b84949e127560084c7c56b365931c71c60768Jeff Dike pending &= ~(1 << sig); 166248b74c79ebb9fb55e146797a808836d90418c4bAl Viro (*handlers[sig])(sig, mc); 167c14b84949e127560084c7c56b365931c71c60768Jeff Dike } 168c14b84949e127560084c7c56b365931c71c60768Jeff Dike 169ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 170ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * Again, pending comes back with a mask of signals 171c14b84949e127560084c7c56b365931c71c60768Jeff Dike * that arrived while tearing down the stack. If this 172c14b84949e127560084c7c56b365931c71c60768Jeff Dike * is non-zero, we just go back, set up the stack 173c14b84949e127560084c7c56b365931c71c60768Jeff Dike * again, and handle the new interrupts. 174c14b84949e127560084c7c56b365931c71c60768Jeff Dike */ 175ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!nested) 176c14b84949e127560084c7c56b365931c71c60768Jeff Dike pending = from_irq_stack(nested); 177ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike } while (pending); 178c14b84949e127560084c7c56b365931c71c60768Jeff Dike} 179c14b84949e127560084c7c56b365931c71c60768Jeff Dike 18000361683ce562402a189362f43370a459b166645Al Virovoid set_handler(int sig) 1810805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 1820805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov struct sigaction action; 183e87df986ed053d25dbd57b8b137edec5022874f8Al Viro int flags = SA_SIGINFO | SA_ONSTACK; 1841d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike sigset_t sig_mask; 1850805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 1867eb122555c8583e1601b7a620c5a88c1e06c3eacAl Viro action.sa_sigaction = hard_handler; 1874b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike 188e87df986ed053d25dbd57b8b137edec5022874f8Al Viro /* block irq ones */ 1890805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov sigemptyset(&action.sa_mask); 190e87df986ed053d25dbd57b8b137edec5022874f8Al Viro sigaddset(&action.sa_mask, SIGVTALRM); 191e87df986ed053d25dbd57b8b137edec5022874f8Al Viro sigaddset(&action.sa_mask, SIGIO); 192e87df986ed053d25dbd57b8b137edec5022874f8Al Viro sigaddset(&action.sa_mask, SIGWINCH); 1934b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike 194e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike if (sig == SIGSEGV) 195e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike flags |= SA_NODEFER; 196e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike 197e87df986ed053d25dbd57b8b137edec5022874f8Al Viro if (sigismember(&action.sa_mask, sig)) 198e87df986ed053d25dbd57b8b137edec5022874f8Al Viro flags |= SA_RESTART; /* if it's an irq signal */ 199e87df986ed053d25dbd57b8b137edec5022874f8Al Viro 200e87df986ed053d25dbd57b8b137edec5022874f8Al Viro action.sa_flags = flags; 2010805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov action.sa_restorer = NULL; 202ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (sigaction(sig, &action, NULL) < 0) 2031d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike panic("sigaction failed - errno = %d\n", errno); 2041d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 2051d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike sigemptyset(&sig_mask); 2061d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike sigaddset(&sig_mask, sig); 207ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) 2081d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike panic("sigprocmask failed - errno = %d\n", errno); 2090805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2100805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2110805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovint change_sig(int signal, int on) 2120805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 213cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike sigset_t sigset; 2140805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2150805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov sigemptyset(&sigset); 2160805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov sigaddset(&sigset, signal); 217cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0) 218c9a3072d13e4b8a6549ecc1db6390a55c7ee2ddfWANG Cong return -errno; 219cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike 220cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike return 0; 2210805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2220805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2230805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid block_signals(void) 2240805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 2251d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike signals_enabled = 0; 226ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 227ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * This must return with signals disabled, so this barrier 22853b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * ensures that writes are flushed out before the return. 22953b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * This might matter if gcc figures out how to inline this and 23053b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * decides to shuffle this code into the caller. 23153b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike */ 232fce8c41c9f68b9af36f3076bae8f1d469a6e7aabJeff Dike barrier(); 2330805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2340805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2350805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid unblock_signals(void) 2360805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 2371d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike int save_pending; 2380805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 239ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (signals_enabled == 1) 2401d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return; 2410805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 242ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 243ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * We loop because the IRQ handler returns with interrupts off. So, 2441d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * interrupts may have arrived and we need to re-enable them and 245cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike * recheck signals_pending. 2461d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 2475134d8fea06ab51459fd095d091d1e6f73a44553Jeff Dike while (1) { 248ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 249ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * Save and reset save_pending after enabling signals. This 250cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike * way, signals_pending won't be changed while we're reading it. 2511d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 2521d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike signals_enabled = 1; 2531d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 254ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 255cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike * Setting signals_enabled and reading signals_pending must 25653b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * happen in this order. 25753b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike */ 258fce8c41c9f68b9af36f3076bae8f1d469a6e7aabJeff Dike barrier(); 25953b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike 260cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike save_pending = signals_pending; 261fce8c41c9f68b9af36f3076bae8f1d469a6e7aabJeff Dike if (save_pending == 0) 2621d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return; 2631d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 264cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike signals_pending = 0; 2651d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 266ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 267ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * We have pending interrupts, so disable signals, as the 2681d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * handlers expect them off when they are called. They will 2691d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * be enabled again above. 2701d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 2711d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 2721d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike signals_enabled = 0; 2731d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 274ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 275ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * Deal with SIGIO first because the alarm handler might 2761d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * schedule, leaving the pending SIGIO stranded until we come 2771d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * back here. 2781d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 279ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (save_pending & SIGIO_MASK) 280e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike sig_handler_common(SIGIO, NULL); 2811d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 282ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (save_pending & SIGVTALRM_MASK) 28361b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike real_alarm_handler(NULL); 2841d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike } 2850805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2860805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2870805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovint get_signals(void) 2880805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 2891d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return signals_enabled; 2900805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2910805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2920805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovint set_signals(int enable) 2930805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 2940805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov int ret; 295ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (signals_enabled == enable) 2961d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return enable; 2970805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2981d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike ret = signals_enabled; 299ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (enable) 3001d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike unblock_signals(); 3011d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike else block_signals(); 3020805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 3031d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return ret; 3040805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 305