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 void set_sigstack(void *sig_stack, int size) 110 { 111 stack_t stack = ((stack_t) { .ss_flags = 0, 112 .ss_sp = (__ptr_t) sig_stack, 113 .ss_size = size - sizeof(void *) }); 114 115 if(sigaltstack(&stack, NULL) != 0) 116 panic("enabling signal stack failed, errno = %d\n", errno); 117 } 118 119 void remove_sigstack(void) 120 { 121 stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, 122 .ss_sp = NULL, 123 .ss_size = 0 }); 124 125 if(sigaltstack(&stack, NULL) != 0) 126 panic("disabling signal stack failed, errno = %d\n", errno); 127 } 128 129 void set_handler(int sig, void (*handler)(int), int flags, ...) 130 { 131 struct sigaction action; 132 va_list ap; 133 sigset_t sig_mask; 134 int mask; 135 136 va_start(ap, flags); 137 action.sa_handler = handler; 138 sigemptyset(&action.sa_mask); 139 while((mask = va_arg(ap, int)) != -1){ 140 sigaddset(&action.sa_mask, mask); 141 } 142 va_end(ap); 143 action.sa_flags = flags; 144 action.sa_restorer = NULL; 145 if(sigaction(sig, &action, NULL) < 0) 146 panic("sigaction failed - errno = %d\n", errno); 147 148 sigemptyset(&sig_mask); 149 sigaddset(&sig_mask, sig); 150 if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) 151 panic("sigprocmask failed - errno = %d\n", errno); 152 } 153 154 int change_sig(int signal, int on) 155 { 156 sigset_t sigset, old; 157 158 sigemptyset(&sigset); 159 sigaddset(&sigset, signal); 160 sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); 161 return(!sigismember(&old, signal)); 162 } 163 164 void block_signals(void) 165 { 166 signals_enabled = 0; 167 } 168 169 void unblock_signals(void) 170 { 171 int save_pending; 172 173 if(signals_enabled == 1) 174 return; 175 176 /* We loop because the IRQ handler returns with interrupts off. So, 177 * interrupts may have arrived and we need to re-enable them and 178 * recheck pending. 179 */ 180 while(1){ 181 /* Save and reset save_pending after enabling signals. This 182 * way, pending won't be changed while we're reading it. 183 */ 184 signals_enabled = 1; 185 186 save_pending = pending; 187 if(save_pending == 0) 188 return; 189 190 pending = 0; 191 192 /* We have pending interrupts, so disable signals, as the 193 * handlers expect them off when they are called. They will 194 * be enabled again above. 195 */ 196 197 signals_enabled = 0; 198 199 /* Deal with SIGIO first because the alarm handler might 200 * schedule, leaving the pending SIGIO stranded until we come 201 * back here. 202 */ 203 if(save_pending & SIGIO_MASK) 204 CHOOSE_MODE_PROC(sig_handler_common_tt, 205 sig_handler_common_skas, SIGIO, NULL); 206 207 if(save_pending & SIGALRM_MASK) 208 real_alarm_handler(SIGALRM, NULL); 209 210 if(save_pending & SIGVTALRM_MASK) 211 real_alarm_handler(SIGVTALRM, NULL); 212 } 213 } 214 215 int get_signals(void) 216 { 217 return signals_enabled; 218 } 219 220 int set_signals(int enable) 221 { 222 int ret; 223 if(signals_enabled == enable) 224 return enable; 225 226 ret = signals_enabled; 227 if(enable) 228 unblock_signals(); 229 else block_signals(); 230 231 return ret; 232 } 233 234 void os_usr1_signal(int on) 235 { 236 change_sig(SIGUSR1, on); 237 } 238