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" 15ab1c0cc7c96c17ea903ca6d3e42e7d2696b32b6cAl Viro#include "sysdep/mcontext.h" 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1775ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dikevoid (*sig_info[NSIG])(int, struct uml_pt_regs *) = { 1875ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGTRAP] = relay_signal, 1975ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGFPE] = relay_signal, 2075ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGILL] = relay_signal, 2175ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGWINCH] = winch, 2275ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGBUS] = bus_handler, 2375ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGSEGV] = segv_handler, 2475ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGIO] = sigio_handler, 2575ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike [SIGVTALRM] = timer_handler }; 2675ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 27248b74c79ebb9fb55e146797a808836d90418c4bAl Virostatic void sig_handler_common(int sig, mcontext_t *mc) 2875ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike{ 29e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike struct uml_pt_regs r; 30e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike int save_errno = errno; 3175ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 32e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike r.is_user = 0; 3375ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike if (sig == SIGSEGV) { 34e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike /* For segfaults, we want the data from the sigcontext. */ 35ab1c0cc7c96c17ea903ca6d3e42e7d2696b32b6cAl Viro get_regs_from_mc(&r, mc); 36248b74c79ebb9fb55e146797a808836d90418c4bAl Viro GET_FAULTINFO_FROM_MC(r.faultinfo, mc); 37e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike } 3875ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 39e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike /* enable signals if sig isn't IRQ signal */ 4075ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) 4175ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike unblock_signals(); 4275ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 43e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike (*sig_info[sig])(sig, &r); 4475ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 4575ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike errno = save_errno; 4675ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike} 4775ada8ffe08cef9b506a796ba6f9ce2071dcf0d7Jeff Dike 48ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike/* 4961b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike * These are the asynchronous signals. SIGPROF is excluded because we want to 501d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * be able to profile all of UML, not just the non-critical sections. If 511d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * profiling is not thread-safe, then that is not my problem. We can disable 521d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * profiling when SMP is enabled in that case. 531d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 541d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGIO_BIT 0 551d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGIO_MASK (1 << SIGIO_BIT) 561d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 571d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGVTALRM_BIT 1 581d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) 591d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 60fce8c41c9f68b9af36f3076bae8f1d469a6e7aabJeff Dikestatic int signals_enabled; 61cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dikestatic unsigned int signals_pending; 621d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 63248b74c79ebb9fb55e146797a808836d90418c4bAl Virovoid sig_handler(int sig, mcontext_t *mc) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 651d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike int enabled; 661d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 671d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike enabled = signals_enabled; 68ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!enabled && (sig == SIGIO)) { 69cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike signals_pending |= SIGIO_MASK; 701d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return; 711d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike } 721d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 731d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike block_signals(); 741d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 75248b74c79ebb9fb55e146797a808836d90418c4bAl Viro sig_handler_common(sig, mc); 761d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 771d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike set_signals(enabled); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 80248b74c79ebb9fb55e146797a808836d90418c4bAl Virostatic void real_alarm_handler(mcontext_t *mc) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8277bf4400319db9d2a8af6b00c2be6faa0f3d07cbJeff Dike struct uml_pt_regs regs; 832ea5bc5e5bb51492f189bba44045e0de7decf4a0Jeff Dike 84248b74c79ebb9fb55e146797a808836d90418c4bAl Viro if (mc != NULL) 85ab1c0cc7c96c17ea903ca6d3e42e7d2696b32b6cAl Viro get_regs_from_mc(®s, mc); 8677bf4400319db9d2a8af6b00c2be6faa0f3d07cbJeff Dike regs.is_user = 0; 872ea5bc5e5bb51492f189bba44045e0de7decf4a0Jeff Dike unblock_signals(); 8861b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike timer_handler(SIGVTALRM, ®s); 891d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike} 901d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 91248b74c79ebb9fb55e146797a808836d90418c4bAl Virovoid alarm_handler(int sig, mcontext_t *mc) 921d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike{ 931d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike int enabled; 941d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 951d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike enabled = signals_enabled; 96ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!signals_enabled) { 97cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike signals_pending |= SIGVTALRM_MASK; 981d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return; 991d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike } 1001d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 1011d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike block_signals(); 1021d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 103248b74c79ebb9fb55e146797a808836d90418c4bAl Viro real_alarm_handler(mc); 1041d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike set_signals(enabled); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10778a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dikevoid timer_init(void) 10878a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike{ 10900361683ce562402a189362f43370a459b166645Al Viro set_handler(SIGVTALRM); 11078a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike} 11178a26e25ce4837a03ac3b6c32cdae1958e547639Jeff Dike 1120805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid set_sigstack(void *sig_stack, int size) 1130805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 1140805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov stack_t stack = ((stack_t) { .ss_flags = 0, 1150805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov .ss_sp = (__ptr_t) sig_stack, 1160805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov .ss_size = size - sizeof(void *) }); 1170805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 118ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (sigaltstack(&stack, NULL) != 0) 1190805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov panic("enabling signal stack failed, errno = %d\n", errno); 1200805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 1210805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 122248b74c79ebb9fb55e146797a808836d90418c4bAl Virostatic void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { 12300361683ce562402a189362f43370a459b166645Al Viro [SIGSEGV] = sig_handler, 12400361683ce562402a189362f43370a459b166645Al Viro [SIGBUS] = sig_handler, 12500361683ce562402a189362f43370a459b166645Al Viro [SIGILL] = sig_handler, 12600361683ce562402a189362f43370a459b166645Al Viro [SIGFPE] = sig_handler, 12700361683ce562402a189362f43370a459b166645Al Viro [SIGTRAP] = sig_handler, 12800361683ce562402a189362f43370a459b166645Al Viro 12900361683ce562402a189362f43370a459b166645Al Viro [SIGIO] = sig_handler, 13000361683ce562402a189362f43370a459b166645Al Viro [SIGWINCH] = sig_handler, 13100361683ce562402a189362f43370a459b166645Al Viro [SIGVTALRM] = alarm_handler 13200361683ce562402a189362f43370a459b166645Al Viro}; 1334b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike 134248b74c79ebb9fb55e146797a808836d90418c4bAl Viro 135248b74c79ebb9fb55e146797a808836d90418c4bAl Virostatic void hard_handler(int sig, siginfo_t *info, void *p) 136c14b84949e127560084c7c56b365931c71c60768Jeff Dike{ 137248b74c79ebb9fb55e146797a808836d90418c4bAl Viro struct ucontext *uc = p; 138248b74c79ebb9fb55e146797a808836d90418c4bAl Viro mcontext_t *mc = &uc->uc_mcontext; 139508a92741a105e2e3d466cd727fb73154ebf08deJeff Dike unsigned long pending = 1UL << sig; 140c14b84949e127560084c7c56b365931c71c60768Jeff Dike 141c14b84949e127560084c7c56b365931c71c60768Jeff Dike do { 142c14b84949e127560084c7c56b365931c71c60768Jeff Dike int nested, bail; 143c14b84949e127560084c7c56b365931c71c60768Jeff Dike 144c14b84949e127560084c7c56b365931c71c60768Jeff Dike /* 145c14b84949e127560084c7c56b365931c71c60768Jeff Dike * pending comes back with one bit set for each 146c14b84949e127560084c7c56b365931c71c60768Jeff Dike * interrupt that arrived while setting up the stack, 147c14b84949e127560084c7c56b365931c71c60768Jeff Dike * plus a bit for this interrupt, plus the zero bit is 148c14b84949e127560084c7c56b365931c71c60768Jeff Dike * set if this is a nested interrupt. 149c14b84949e127560084c7c56b365931c71c60768Jeff Dike * If bail is true, then we interrupted another 150c14b84949e127560084c7c56b365931c71c60768Jeff Dike * handler setting up the stack. In this case, we 151c14b84949e127560084c7c56b365931c71c60768Jeff Dike * have to return, and the upper handler will deal 152c14b84949e127560084c7c56b365931c71c60768Jeff Dike * with this interrupt. 153c14b84949e127560084c7c56b365931c71c60768Jeff Dike */ 154508a92741a105e2e3d466cd727fb73154ebf08deJeff Dike bail = to_irq_stack(&pending); 155ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (bail) 156c14b84949e127560084c7c56b365931c71c60768Jeff Dike return; 157c14b84949e127560084c7c56b365931c71c60768Jeff Dike 158c14b84949e127560084c7c56b365931c71c60768Jeff Dike nested = pending & 1; 159c14b84949e127560084c7c56b365931c71c60768Jeff Dike pending &= ~1; 160c14b84949e127560084c7c56b365931c71c60768Jeff Dike 161ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike while ((sig = ffs(pending)) != 0){ 162c14b84949e127560084c7c56b365931c71c60768Jeff Dike sig--; 163c14b84949e127560084c7c56b365931c71c60768Jeff Dike pending &= ~(1 << sig); 164248b74c79ebb9fb55e146797a808836d90418c4bAl Viro (*handlers[sig])(sig, mc); 165c14b84949e127560084c7c56b365931c71c60768Jeff Dike } 166c14b84949e127560084c7c56b365931c71c60768Jeff Dike 167ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 168ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * Again, pending comes back with a mask of signals 169c14b84949e127560084c7c56b365931c71c60768Jeff Dike * that arrived while tearing down the stack. If this 170c14b84949e127560084c7c56b365931c71c60768Jeff Dike * is non-zero, we just go back, set up the stack 171c14b84949e127560084c7c56b365931c71c60768Jeff Dike * again, and handle the new interrupts. 172c14b84949e127560084c7c56b365931c71c60768Jeff Dike */ 173ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (!nested) 174c14b84949e127560084c7c56b365931c71c60768Jeff Dike pending = from_irq_stack(nested); 175ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike } while (pending); 176c14b84949e127560084c7c56b365931c71c60768Jeff Dike} 177c14b84949e127560084c7c56b365931c71c60768Jeff Dike 17800361683ce562402a189362f43370a459b166645Al Virovoid set_handler(int sig) 1790805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 1800805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov struct sigaction action; 181e87df986ed053d25dbd57b8b137edec5022874f8Al Viro int flags = SA_SIGINFO | SA_ONSTACK; 1821d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike sigset_t sig_mask; 1830805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 1847eb122555c8583e1601b7a620c5a88c1e06c3eacAl Viro action.sa_sigaction = hard_handler; 1854b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike 186e87df986ed053d25dbd57b8b137edec5022874f8Al Viro /* block irq ones */ 1870805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov sigemptyset(&action.sa_mask); 188e87df986ed053d25dbd57b8b137edec5022874f8Al Viro sigaddset(&action.sa_mask, SIGVTALRM); 189e87df986ed053d25dbd57b8b137edec5022874f8Al Viro sigaddset(&action.sa_mask, SIGIO); 190e87df986ed053d25dbd57b8b137edec5022874f8Al Viro sigaddset(&action.sa_mask, SIGWINCH); 1914b84c69b5f6c08a540e3683f1360a6cdef2806c7Jeff Dike 192e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike if (sig == SIGSEGV) 193e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike flags |= SA_NODEFER; 194e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike 195e87df986ed053d25dbd57b8b137edec5022874f8Al Viro if (sigismember(&action.sa_mask, sig)) 196e87df986ed053d25dbd57b8b137edec5022874f8Al Viro flags |= SA_RESTART; /* if it's an irq signal */ 197e87df986ed053d25dbd57b8b137edec5022874f8Al Viro 198e87df986ed053d25dbd57b8b137edec5022874f8Al Viro action.sa_flags = flags; 1990805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov action.sa_restorer = NULL; 200ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (sigaction(sig, &action, NULL) < 0) 2011d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike panic("sigaction failed - errno = %d\n", errno); 2021d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 2031d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike sigemptyset(&sig_mask); 2041d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike sigaddset(&sig_mask, sig); 205ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) 2061d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike panic("sigprocmask failed - errno = %d\n", errno); 2070805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2080805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2090805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovint change_sig(int signal, int on) 2100805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 211cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike sigset_t sigset; 2120805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2130805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov sigemptyset(&sigset); 2140805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov sigaddset(&sigset, signal); 215cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0) 216c9a3072d13e4b8a6549ecc1db6390a55c7ee2ddfWANG Cong return -errno; 217cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike 218cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike return 0; 2190805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2200805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2210805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid block_signals(void) 2220805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 2231d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike signals_enabled = 0; 224ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 225ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * This must return with signals disabled, so this barrier 22653b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * ensures that writes are flushed out before the return. 22753b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * This might matter if gcc figures out how to inline this and 22853b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * decides to shuffle this code into the caller. 22953b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike */ 230fce8c41c9f68b9af36f3076bae8f1d469a6e7aabJeff Dike barrier(); 2310805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2320805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2330805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovvoid unblock_signals(void) 2340805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 2351d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike int save_pending; 2360805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 237ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (signals_enabled == 1) 2381d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return; 2390805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 240ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 241ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * We loop because the IRQ handler returns with interrupts off. So, 2421d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * interrupts may have arrived and we need to re-enable them and 243cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike * recheck signals_pending. 2441d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 2455134d8fea06ab51459fd095d091d1e6f73a44553Jeff Dike while (1) { 246ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 247ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * Save and reset save_pending after enabling signals. This 248cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike * way, signals_pending won't be changed while we're reading it. 2491d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 2501d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike signals_enabled = 1; 2511d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 252ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 253cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike * Setting signals_enabled and reading signals_pending must 25453b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike * happen in this order. 25553b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike */ 256fce8c41c9f68b9af36f3076bae8f1d469a6e7aabJeff Dike barrier(); 25753b173327d283b9bdbfb0c3b6de6f0eb197819d6Jeff Dike 258cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike save_pending = signals_pending; 259fce8c41c9f68b9af36f3076bae8f1d469a6e7aabJeff Dike if (save_pending == 0) 2601d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return; 2611d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 262cfef8f34e7cf57f3d278ceda79c85112dec13dc6Jeff Dike signals_pending = 0; 2631d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 264ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 265ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * We have pending interrupts, so disable signals, as the 2661d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * handlers expect them off when they are called. They will 2671d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * be enabled again above. 2681d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 2691d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 2701d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike signals_enabled = 0; 2711d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 272ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike /* 273ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike * Deal with SIGIO first because the alarm handler might 2741d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * schedule, leaving the pending SIGIO stranded until we come 2751d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike * back here. 2761d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike */ 277ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (save_pending & SIGIO_MASK) 278e6a2d1f7024f93e4622cd7ba633666a63ccce49eJeff Dike sig_handler_common(SIGIO, NULL); 2791d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike 280ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (save_pending & SIGVTALRM_MASK) 28161b63c556c0877ee6d3832ee641bc427ff4d94d6Jeff Dike real_alarm_handler(NULL); 2821d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike } 2830805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2840805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2850805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovint get_signals(void) 2860805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 2871d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return signals_enabled; 2880805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 2890805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2900805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapovint set_signals(int enable) 2910805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov{ 2920805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov int ret; 293ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (signals_enabled == enable) 2941d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return enable; 2950805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 2961d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike ret = signals_enabled; 297ba180fd437156f7fd8cfb2fdd021d949eeef08d6Jeff Dike if (enable) 2981d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike unblock_signals(); 2991d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike else block_signals(); 3000805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov 3011d7173baf286c8b720f97f119ec92be43076ebdeJeff Dike return ret; 3020805d89c151b4800eade4c2f50d39c5253d7d054Gennady Sharapov} 303