linux/arch/um/os-Linux/signal.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004 PathScale, Inc
   3 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   4 * Licensed under the GPL
   5 */
   6
   7#include <stdlib.h>
   8#include <stdarg.h>
   9#include <errno.h>
  10#include <signal.h>
  11#include <strings.h>
  12#include "as-layout.h"
  13#include "kern_util.h"
  14#include "os.h"
  15#include "process.h"
  16#include "sysdep/barrier.h"
  17#include "sysdep/sigcontext.h"
  18#include "user.h"
  19
  20/* Copied from linux/compiler-gcc.h since we can't include it directly */
  21#define barrier() __asm__ __volatile__("": : :"memory")
  22
  23void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
  24        [SIGTRAP]       = relay_signal,
  25        [SIGFPE]        = relay_signal,
  26        [SIGILL]        = relay_signal,
  27        [SIGWINCH]      = winch,
  28        [SIGBUS]        = bus_handler,
  29        [SIGSEGV]       = segv_handler,
  30        [SIGIO]         = sigio_handler,
  31        [SIGVTALRM]     = timer_handler };
  32
  33static void sig_handler_common(int sig, struct sigcontext *sc)
  34{
  35        struct uml_pt_regs r;
  36        int save_errno = errno;
  37
  38        r.is_user = 0;
  39        if (sig == SIGSEGV) {
  40                /* For segfaults, we want the data from the sigcontext. */
  41                copy_sc(&r, sc);
  42                GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
  43        }
  44
  45        /* enable signals if sig isn't IRQ signal */
  46        if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
  47                unblock_signals();
  48
  49        (*sig_info[sig])(sig, &r);
  50
  51        errno = save_errno;
  52}
  53
  54/*
  55 * These are the asynchronous signals.  SIGPROF is excluded because we want to
  56 * be able to profile all of UML, not just the non-critical sections.  If
  57 * profiling is not thread-safe, then that is not my problem.  We can disable
  58 * profiling when SMP is enabled in that case.
  59 */
  60#define SIGIO_BIT 0
  61#define SIGIO_MASK (1 << SIGIO_BIT)
  62
  63#define SIGVTALRM_BIT 1
  64#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
  65
  66static int signals_enabled;
  67static unsigned int signals_pending;
  68
  69void sig_handler(int sig, struct sigcontext *sc)
  70{
  71        int enabled;
  72
  73        enabled = signals_enabled;
  74        if (!enabled && (sig == SIGIO)) {
  75                signals_pending |= SIGIO_MASK;
  76                return;
  77        }
  78
  79        block_signals();
  80
  81        sig_handler_common(sig, sc);
  82
  83        set_signals(enabled);
  84}
  85
  86static void real_alarm_handler(struct sigcontext *sc)
  87{
  88        struct uml_pt_regs regs;
  89
  90        if (sc != NULL)
  91                copy_sc(&regs, sc);
  92        regs.is_user = 0;
  93        unblock_signals();
  94        timer_handler(SIGVTALRM, &regs);
  95}
  96
  97void alarm_handler(int sig, struct sigcontext *sc)
  98{
  99        int enabled;
 100
 101        enabled = signals_enabled;
 102        if (!signals_enabled) {
 103                signals_pending |= SIGVTALRM_MASK;
 104                return;
 105        }
 106
 107        block_signals();
 108
 109        real_alarm_handler(sc);
 110        set_signals(enabled);
 111}
 112
 113void timer_init(void)
 114{
 115        set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
 116                    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
 117}
 118
 119void set_sigstack(void *sig_stack, int size)
 120{
 121        stack_t stack = ((stack_t) { .ss_flags  = 0,
 122                                     .ss_sp     = (__ptr_t) sig_stack,
 123                                     .ss_size   = size - sizeof(void *) });
 124
 125        if (sigaltstack(&stack, NULL) != 0)
 126                panic("enabling signal stack failed, errno = %d\n", errno);
 127}
 128
 129static void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
 130
 131void handle_signal(int sig, struct sigcontext *sc)
 132{
 133        unsigned long pending = 1UL << sig;
 134
 135        do {
 136                int nested, bail;
 137
 138                /*
 139                 * pending comes back with one bit set for each
 140                 * interrupt that arrived while setting up the stack,
 141                 * plus a bit for this interrupt, plus the zero bit is
 142                 * set if this is a nested interrupt.
 143                 * If bail is true, then we interrupted another
 144                 * handler setting up the stack.  In this case, we
 145                 * have to return, and the upper handler will deal
 146                 * with this interrupt.
 147                 */
 148                bail = to_irq_stack(&pending);
 149                if (bail)
 150                        return;
 151
 152                nested = pending & 1;
 153                pending &= ~1;
 154
 155                while ((sig = ffs(pending)) != 0){
 156                        sig--;
 157                        pending &= ~(1 << sig);
 158                        (*handlers[sig])(sig, sc);
 159                }
 160
 161                /*
 162                 * Again, pending comes back with a mask of signals
 163                 * that arrived while tearing down the stack.  If this
 164                 * is non-zero, we just go back, set up the stack
 165                 * again, and handle the new interrupts.
 166                 */
 167                if (!nested)
 168                        pending = from_irq_stack(nested);
 169        } while (pending);
 170}
 171
 172extern void hard_handler(int sig);
 173
 174void set_handler(int sig, void (*handler)(int), int flags, ...)
 175{
 176        struct sigaction action;
 177        va_list ap;
 178        sigset_t sig_mask;
 179        int mask;
 180
 181        handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
 182        action.sa_handler = hard_handler;
 183
 184        sigemptyset(&action.sa_mask);
 185
 186        va_start(ap, flags);
 187        while ((mask = va_arg(ap, int)) != -1)
 188                sigaddset(&action.sa_mask, mask);
 189        va_end(ap);
 190
 191        if (sig == SIGSEGV)
 192                flags |= SA_NODEFER;
 193
 194        action.sa_flags = flags;
 195        action.sa_restorer = NULL;
 196        if (sigaction(sig, &action, NULL) < 0)
 197                panic("sigaction failed - errno = %d\n", errno);
 198
 199        sigemptyset(&sig_mask);
 200        sigaddset(&sig_mask, sig);
 201        if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
 202                panic("sigprocmask failed - errno = %d\n", errno);
 203}
 204
 205int change_sig(int signal, int on)
 206{
 207        sigset_t sigset;
 208
 209        sigemptyset(&sigset);
 210        sigaddset(&sigset, signal);
 211        if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
 212                return -errno;
 213
 214        return 0;
 215}
 216
 217void block_signals(void)
 218{
 219        signals_enabled = 0;
 220        /*
 221         * This must return with signals disabled, so this barrier
 222         * ensures that writes are flushed out before the return.
 223         * This might matter if gcc figures out how to inline this and
 224         * decides to shuffle this code into the caller.
 225         */
 226        barrier();
 227}
 228
 229void unblock_signals(void)
 230{
 231        int save_pending;
 232
 233        if (signals_enabled == 1)
 234                return;
 235
 236        /*
 237         * We loop because the IRQ handler returns with interrupts off.  So,
 238         * interrupts may have arrived and we need to re-enable them and
 239         * recheck signals_pending.
 240         */
 241        while (1) {
 242                /*
 243                 * Save and reset save_pending after enabling signals.  This
 244                 * way, signals_pending won't be changed while we're reading it.
 245                 */
 246                signals_enabled = 1;
 247
 248                /*
 249                 * Setting signals_enabled and reading signals_pending must
 250                 * happen in this order.
 251                 */
 252                barrier();
 253
 254                save_pending = signals_pending;
 255                if (save_pending == 0)
 256                        return;
 257
 258                signals_pending = 0;
 259
 260                /*
 261                 * We have pending interrupts, so disable signals, as the
 262                 * handlers expect them off when they are called.  They will
 263                 * be enabled again above.
 264                 */
 265
 266                signals_enabled = 0;
 267
 268                /*
 269                 * Deal with SIGIO first because the alarm handler might
 270                 * schedule, leaving the pending SIGIO stranded until we come
 271                 * back here.
 272                 */
 273                if (save_pending & SIGIO_MASK)
 274                        sig_handler_common(SIGIO, NULL);
 275
 276                if (save_pending & SIGVTALRM_MASK)
 277                        real_alarm_handler(NULL);
 278        }
 279}
 280
 281int get_signals(void)
 282{
 283        return signals_enabled;
 284}
 285
 286int set_signals(int enable)
 287{
 288        int ret;
 289        if (signals_enabled == enable)
 290                return enable;
 291
 292        ret = signals_enabled;
 293        if (enable)
 294                unblock_signals();
 295        else block_signals();
 296
 297        return ret;
 298}
 299