📄 signal_user.c
字号:
/* * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>#include <errno.h>#include <stdarg.h>#include <string.h>#include <sys/mman.h>#include "user_util.h"#include "kern_util.h"#include "user.h"#include "signal_user.h"#include "signal_kern.h"#include "sysdep/sigcontext.h"#include "sigcontext.h"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 set_handler(int sig, void (*handler)(int), int flags, ...){ struct sigaction action; va_list ap; 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");}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));}/* Both here and in set/get_signal we don't touch SIGPROF, because we must not * disable profiling; it's safe because the profiling code does not interact * with the kernel code at all.*/static void change_signals(int type){ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGVTALRM); sigaddset(&mask, SIGALRM); sigaddset(&mask, SIGIO); if(sigprocmask(type, &mask, NULL) < 0) panic("Failed to change signal mask - errno = %d", errno);}void block_signals(void){ change_signals(SIG_BLOCK);}void unblock_signals(void){ change_signals(SIG_UNBLOCK);}/* 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 SIGVTALRM_BIT 1static int enable_mask(sigset_t *mask){ int sigs; sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; return(sigs);}int get_signals(void){ sigset_t mask; if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) panic("Failed to get signal mask"); return(enable_mask(&mask));}int set_signals(int enable){ sigset_t mask; int ret; sigemptyset(&mask); if(enable & (1 << SIGIO_BIT)) sigaddset(&mask, SIGIO); if(enable & (1 << SIGVTALRM_BIT)){ sigaddset(&mask, SIGVTALRM); sigaddset(&mask, SIGALRM); } /* This is safe - sigprocmask is guaranteed to copy locally the * value of new_set, do his work and then, at the end, write to * old_set. */ if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) panic("Failed to enable signals"); ret = enable_mask(&mask); sigemptyset(&mask); if((enable & (1 << SIGIO_BIT)) == 0) sigaddset(&mask, SIGIO); if((enable & (1 << SIGVTALRM_BIT)) == 0){ sigaddset(&mask, SIGVTALRM); sigaddset(&mask, SIGALRM); } if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) panic("Failed to block signals"); return(ret);}/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-file-style: "linux" * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -