signal.c
来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 261 行
C
261 行
/* * Copyright (C) 2004 PathScale, Inc * Licensed under the GPL */#include <signal.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <stdarg.h>#include <string.h>#include <sys/mman.h>#include "user_util.h"#include "user.h"#include "signal_kern.h"#include "sysdep/sigcontext.h"#include "sysdep/signal.h"#include "sigcontext.h"#include "mode.h"#include "os.h"/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to * be able to profile all of UML, not just the non-critical sections. If * profiling is not thread-safe, then that is not my problem. We can disable * profiling when SMP is enabled in that case. */#define SIGIO_BIT 0#define SIGIO_MASK (1 << SIGIO_BIT)#define SIGVTALRM_BIT 1#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)#define SIGALRM_BIT 2#define SIGALRM_MASK (1 << SIGALRM_BIT)static int signals_enabled = 1;static int pending = 0;void sig_handler(ARCH_SIGHDLR_PARAM){ struct sigcontext *sc; int enabled; /* Must be the first thing that this handler does - x86_64 stores * the sigcontext in %rdx, and we need to save it before it has a * chance to get trashed. */ ARCH_GET_SIGCONTEXT(sc, sig); enabled = signals_enabled; if(!enabled && (sig == SIGIO)){ pending |= SIGIO_MASK; return; } block_signals(); CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, sig, sc); set_signals(enabled);}extern int timer_irq_inited;static void real_alarm_handler(int sig, struct sigcontext *sc){ if(!timer_irq_inited){ signals_enabled = 1; return; } if(sig == SIGALRM) switch_timers(0); CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, sig, sc); if(sig == SIGALRM) switch_timers(1);}void alarm_handler(ARCH_SIGHDLR_PARAM){ struct sigcontext *sc; int enabled; ARCH_GET_SIGCONTEXT(sc, sig); enabled = signals_enabled; if(!signals_enabled){ if(sig == SIGVTALRM) pending |= SIGVTALRM_MASK; else pending |= SIGALRM_MASK; return; } block_signals(); real_alarm_handler(sig, sc); set_signals(enabled);}extern void do_boot_timer_handler(struct sigcontext * sc);void boot_timer_handler(ARCH_SIGHDLR_PARAM){ struct sigcontext *sc; int enabled; ARCH_GET_SIGCONTEXT(sc, sig); enabled = signals_enabled; if(!enabled){ if(sig == SIGVTALRM) pending |= SIGVTALRM_MASK; else pending |= SIGALRM_MASK; return; } block_signals(); do_boot_timer_handler(sc); set_signals(enabled);}void set_sigstack(void *sig_stack, int size){ stack_t stack = ((stack_t) { .ss_flags = 0, .ss_sp = (__ptr_t) sig_stack, .ss_size = size - sizeof(void *) }); if(sigaltstack(&stack, NULL) != 0) panic("enabling signal stack failed, errno = %d\n", errno);}void remove_sigstack(void){ stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, .ss_sp = NULL, .ss_size = 0 }); if(sigaltstack(&stack, NULL) != 0) panic("disabling signal stack failed, errno = %d\n", errno);}void set_handler(int sig, void (*handler)(int), int flags, ...){ struct sigaction action; va_list ap; sigset_t sig_mask; int mask; va_start(ap, flags); action.sa_handler = handler; sigemptyset(&action.sa_mask); while((mask = va_arg(ap, int)) != -1){ sigaddset(&action.sa_mask, mask); } va_end(ap); action.sa_flags = flags; action.sa_restorer = NULL; if(sigaction(sig, &action, NULL) < 0) panic("sigaction failed - errno = %d\n", errno); sigemptyset(&sig_mask); sigaddset(&sig_mask, sig); if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) panic("sigprocmask failed - errno = %d\n", errno);}int change_sig(int signal, int on){ sigset_t sigset, old; sigemptyset(&sigset); sigaddset(&sigset, signal); sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); return(!sigismember(&old, signal));}void block_signals(void){ signals_enabled = 0;}void unblock_signals(void){ int save_pending; if(signals_enabled == 1) return; /* We loop because the IRQ handler returns with interrupts off. So, * interrupts may have arrived and we need to re-enable them and * recheck pending. */ while(1){ /* Save and reset save_pending after enabling signals. This * way, pending won't be changed while we're reading it. */ signals_enabled = 1; save_pending = pending; if(save_pending == 0) return; pending = 0; /* We have pending interrupts, so disable signals, as the * handlers expect them off when they are called. They will * be enabled again above. */ signals_enabled = 0; /* Deal with SIGIO first because the alarm handler might * schedule, leaving the pending SIGIO stranded until we come * back here. */ if(save_pending & SIGIO_MASK) CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, SIGIO, NULL); if(save_pending & SIGALRM_MASK) real_alarm_handler(SIGALRM, NULL); if(save_pending & SIGVTALRM_MASK) real_alarm_handler(SIGVTALRM, NULL); }}int get_signals(void){ return signals_enabled;}int set_signals(int enable){ int ret; if(signals_enabled == enable) return enable; ret = signals_enabled; if(enable) unblock_signals(); else block_signals(); return ret;}void os_usr1_signal(int on){ change_sig(SIGUSR1, on);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?