[PATCH] UFS: inode->i_sem is not released in error path
[linux-2.6/verdex.git] / arch / um / os-Linux / signal.c
blobc1f46a0fef13d14c8740d80091fb18a2cf0690d7
1 /*
2 * Copyright (C) 2004 PathScale, Inc
3 * Licensed under the GPL
4 */
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 "kern_util.h"
16 #include "user.h"
17 #include "signal_kern.h"
18 #include "sysdep/sigcontext.h"
19 #include "sysdep/signal.h"
20 #include "sigcontext.h"
21 #include "time_user.h"
22 #include "mode.h"
24 void sig_handler(ARCH_SIGHDLR_PARAM)
26 struct sigcontext *sc;
28 ARCH_GET_SIGCONTEXT(sc, sig);
29 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
30 sig, sc);
33 extern int timer_irq_inited;
35 void alarm_handler(ARCH_SIGHDLR_PARAM)
37 struct sigcontext *sc;
39 ARCH_GET_SIGCONTEXT(sc, sig);
40 if(!timer_irq_inited) return;
42 if(sig == SIGALRM)
43 switch_timers(0);
45 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
46 sig, sc);
48 if(sig == SIGALRM)
49 switch_timers(1);
52 void set_sigstack(void *sig_stack, int size)
54 stack_t stack = ((stack_t) { .ss_flags = 0,
55 .ss_sp = (__ptr_t) sig_stack,
56 .ss_size = size - sizeof(void *) });
58 if(sigaltstack(&stack, NULL) != 0)
59 panic("enabling signal stack failed, errno = %d\n", errno);
62 void remove_sigstack(void)
64 stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
65 .ss_sp = NULL,
66 .ss_size = 0 });
68 if(sigaltstack(&stack, NULL) != 0)
69 panic("disabling signal stack failed, errno = %d\n", errno);
72 void set_handler(int sig, void (*handler)(int), int flags, ...)
74 struct sigaction action;
75 va_list ap;
76 int mask;
78 va_start(ap, flags);
79 action.sa_handler = handler;
80 sigemptyset(&action.sa_mask);
81 while((mask = va_arg(ap, int)) != -1){
82 sigaddset(&action.sa_mask, mask);
84 va_end(ap);
85 action.sa_flags = flags;
86 action.sa_restorer = NULL;
87 if(sigaction(sig, &action, NULL) < 0)
88 panic("sigaction failed");
91 int change_sig(int signal, int on)
93 sigset_t sigset, old;
95 sigemptyset(&sigset);
96 sigaddset(&sigset, signal);
97 sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
98 return(!sigismember(&old, signal));
101 /* Both here and in set/get_signal we don't touch SIGPROF, because we must not
102 * disable profiling; it's safe because the profiling code does not interact
103 * with the kernel code at all.*/
105 static void change_signals(int type)
107 sigset_t mask;
109 sigemptyset(&mask);
110 sigaddset(&mask, SIGVTALRM);
111 sigaddset(&mask, SIGALRM);
112 sigaddset(&mask, SIGIO);
113 if(sigprocmask(type, &mask, NULL) < 0)
114 panic("Failed to change signal mask - errno = %d", errno);
117 void block_signals(void)
119 change_signals(SIG_BLOCK);
122 void unblock_signals(void)
124 change_signals(SIG_UNBLOCK);
127 /* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
128 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
129 * be able to profile all of UML, not just the non-critical sections. If
130 * profiling is not thread-safe, then that is not my problem. We can disable
131 * profiling when SMP is enabled in that case.
133 #define SIGIO_BIT 0
134 #define SIGVTALRM_BIT 1
136 static int enable_mask(sigset_t *mask)
138 int sigs;
140 sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
141 sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
142 sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
143 return(sigs);
146 int get_signals(void)
148 sigset_t mask;
150 if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
151 panic("Failed to get signal mask");
152 return(enable_mask(&mask));
155 int set_signals(int enable)
157 sigset_t mask;
158 int ret;
160 sigemptyset(&mask);
161 if(enable & (1 << SIGIO_BIT))
162 sigaddset(&mask, SIGIO);
163 if(enable & (1 << SIGVTALRM_BIT)){
164 sigaddset(&mask, SIGVTALRM);
165 sigaddset(&mask, SIGALRM);
168 /* This is safe - sigprocmask is guaranteed to copy locally the
169 * value of new_set, do his work and then, at the end, write to
170 * old_set.
172 if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
173 panic("Failed to enable signals");
174 ret = enable_mask(&mask);
175 sigemptyset(&mask);
176 if((enable & (1 << SIGIO_BIT)) == 0)
177 sigaddset(&mask, SIGIO);
178 if((enable & (1 << SIGVTALRM_BIT)) == 0){
179 sigaddset(&mask, SIGVTALRM);
180 sigaddset(&mask, SIGALRM);
182 if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
183 panic("Failed to block signals");
185 return(ret);