1 /* 2 * Copyright (C) 2004 PathScale, Inc 3 * Licensed under the GPL 4 */ 5 6 #include <signal.h> 7 #include <stdio.h> 8 #include <unistd.h> 9 #include <stdlib.h> 10 #include <errno.h> 11 #include <stdarg.h> 12 #include <string.h> 13 #include <sys/mman.h> 14 #include "user_util.h" 15 #include "user.h" 16 #include "signal_kern.h" 17 #include "sysdep/sigcontext.h" 18 #include "sysdep/signal.h" 19 #include "sigcontext.h" 20 #include "mode.h" 21 #include "os.h" 22 23 /* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled 24 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to 25 * be able to profile all of UML, not just the non-critical sections. If 26 * profiling is not thread-safe, then that is not my problem. We can disable 27 * profiling when SMP is enabled in that case. 28 */ 29 #define SIGIO_BIT 0 30 #define SIGIO_MASK (1 << SIGIO_BIT) 31 32 #define SIGVTALRM_BIT 1 33 #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) 34 35 #define SIGALRM_BIT 2 36 #define SIGALRM_MASK (1 << SIGALRM_BIT) 37 38 static int signals_enabled = 1; 39 static int pending = 0; 40 41 void sig_handler(ARCH_SIGHDLR_PARAM) 42 { 43 struct sigcontext *sc; 44 int enabled; 45 46 /* Must be the first thing that this handler does - x86_64 stores 47 * the sigcontext in %rdx, and we need to save it before it has a 48 * chance to get trashed. 49 */ 50 51 ARCH_GET_SIGCONTEXT(sc, sig); 52 53 enabled = signals_enabled; 54 if(!enabled && (sig == SIGIO)){ 55 pending |= SIGIO_MASK; 56 return; 57 } 58 59 block_signals(); 60 61 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, 62 sig, sc); 63 64 set_signals(enabled); 65 } 66 67 extern int timer_irq_inited; 68 69 static void real_alarm_handler(int sig, struct sigcontext *sc) 70 { 71 if(!timer_irq_inited){ 72 signals_enabled = 1; 73 return; 74 } 75 76 if(sig == SIGALRM) 77 switch_timers(0); 78 79 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, 80 sig, sc); 81 82 if(sig == SIGALRM) 83 switch_timers(1); 84 85 } 86 87 void alarm_handler(ARCH_SIGHDLR_PARAM) 88 { 89 struct sigcontext *sc; 90 int enabled; 91 92 ARCH_GET_SIGCONTEXT(sc, sig); 93 94 enabled = signals_enabled; 95 if(!signals_enabled){ 96 if(sig == SIGVTALRM) 97 pending |= SIGVTALRM_MASK; 98 else pending |= SIGALRM_MASK; 99 100 return; 101 } 102 103 block_signals(); 104 105 real_alarm_handler(sig, sc); 106 set_signals(enabled); 107 } 108 109 extern void do_boot_timer_handler(struct sigcontext * sc); 110 111 void boot_timer_handler(ARCH_SIGHDLR_PARAM) 112 { 113 struct sigcontext *sc; 114 int enabled; 115 116 ARCH_GET_SIGCONTEXT(sc, sig); 117 118 enabled = signals_enabled; 119 if(!enabled){ 120 if(sig == SIGVTALRM) 121 pending |= SIGVTALRM_MASK; 122 else pending |= SIGALRM_MASK; 123 return; 124 } 125 126 block_signals(); 127 128 do_boot_timer_handler(sc); 129 set_signals(enabled); 130 } 131 132 void set_sigstack(void *sig_stack, int size) 133 { 134 stack_t stack = ((stack_t) { .ss_flags = 0, 135 .ss_sp = (__ptr_t) sig_stack, 136 .ss_size = size - sizeof(void *) }); 137 138 if(sigaltstack(&stack, NULL) != 0) 139 panic("enabling signal stack failed, errno = %d\n", errno); 140 } 141 142 void remove_sigstack(void) 143 { 144 stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, 145 .ss_sp = NULL, 146 .ss_size = 0 }); 147 148 if(sigaltstack(&stack, NULL) != 0) 149 panic("disabling signal stack failed, errno = %d\n", errno); 150 } 151 152 void set_handler(int sig, void (*handler)(int), int flags, ...) 153 { 154 struct sigaction action; 155 va_list ap; 156 sigset_t sig_mask; 157 int mask; 158 159 va_start(ap, flags); 160 action.sa_handler = handler; 161 sigemptyset(&action.sa_mask); 162 while((mask = va_arg(ap, int)) != -1){ 163 sigaddset(&action.sa_mask, mask); 164 } 165 va_end(ap); 166 action.sa_flags = flags; 167 action.sa_restorer = NULL; 168 if(sigaction(sig, &action, NULL) < 0) 169 panic("sigaction failed - errno = %d\n", errno); 170 171 sigemptyset(&sig_mask); 172 sigaddset(&sig_mask, sig); 173 if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) 174 panic("sigprocmask failed - errno = %d\n", errno); 175 } 176 177 int change_sig(int signal, int on) 178 { 179 sigset_t sigset, old; 180 181 sigemptyset(&sigset); 182 sigaddset(&sigset, signal); 183 sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); 184 return(!sigismember(&old, signal)); 185 } 186 187 void block_signals(void) 188 { 189 signals_enabled = 0; 190 } 191 192 void unblock_signals(void) 193 { 194 int save_pending; 195 196 if(signals_enabled == 1) 197 return; 198 199 /* We loop because the IRQ handler returns with interrupts off. So, 200 * interrupts may have arrived and we need to re-enable them and 201 * recheck pending. 202 */ 203 while(1){ 204 /* Save and reset save_pending after enabling signals. This 205 * way, pending won't be changed while we're reading it. 206 */ 207 signals_enabled = 1; 208 209 save_pending = pending; 210 if(save_pending == 0) 211 return; 212 213 pending = 0; 214 215 /* We have pending interrupts, so disable signals, as the 216 * handlers expect them off when they are called. They will 217 * be enabled again above. 218 */ 219 220 signals_enabled = 0; 221 222 /* Deal with SIGIO first because the alarm handler might 223 * schedule, leaving the pending SIGIO stranded until we come 224 * back here. 225 */ 226 if(save_pending & SIGIO_MASK) 227 CHOOSE_MODE_PROC(sig_handler_common_tt, 228 sig_handler_common_skas, SIGIO, NULL); 229 230 if(save_pending & SIGALRM_MASK) 231 real_alarm_handler(SIGALRM, NULL); 232 233 if(save_pending & SIGVTALRM_MASK) 234 real_alarm_handler(SIGVTALRM, NULL); 235 } 236 } 237 238 int get_signals(void) 239 { 240 return signals_enabled; 241 } 242 243 int set_signals(int enable) 244 { 245 int ret; 246 if(signals_enabled == enable) 247 return enable; 248 249 ret = signals_enabled; 250 if(enable) 251 unblock_signals(); 252 else block_signals(); 253 254 return ret; 255 } 256 257 void os_usr1_signal(int on) 258 { 259 change_sig(SIGUSR1, on); 260 } 261