aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/signal_kern.c
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2006-01-19 11:39:33 -0500
committerAnton Altaparmakov <aia21@cantab.net>2006-01-19 11:39:33 -0500
commit944d79559d154c12becde0dab327016cf438f46c (patch)
tree50c101806f4d3b6585222dda060559eb4f3e005a /arch/um/kernel/signal_kern.c
parentd087e4bdd24ebe3ae3d0b265b6573ec901af4b4b (diff)
parent0f36b018b2e314d45af86449f1a97facb1fbe300 (diff)
Merge branch 'master' of /usr/src/ntfs-2.6/
Diffstat (limited to 'arch/um/kernel/signal_kern.c')
-rw-r--r--arch/um/kernel/signal_kern.c92
1 files changed, 35 insertions, 57 deletions
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 03618bd13d55..da17b7541e08 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -22,7 +22,6 @@
22#include "asm/ucontext.h" 22#include "asm/ucontext.h"
23#include "kern_util.h" 23#include "kern_util.h"
24#include "signal_kern.h" 24#include "signal_kern.h"
25#include "signal_user.h"
26#include "kern.h" 25#include "kern.h"
27#include "frame_kern.h" 26#include "frame_kern.h"
28#include "sigcontext.h" 27#include "sigcontext.h"
@@ -100,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
100 return err; 99 return err;
101} 100}
102 101
103static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) 102static int kern_do_signal(struct pt_regs *regs)
104{ 103{
105 struct k_sigaction ka_copy; 104 struct k_sigaction ka_copy;
106 siginfo_t info; 105 siginfo_t info;
106 sigset_t *oldset;
107 int sig, handled_sig = 0; 107 int sig, handled_sig = 0;
108 108
109 if (test_thread_flag(TIF_RESTORE_SIGMASK))
110 oldset = &current->saved_sigmask;
111 else
112 oldset = &current->blocked;
113
109 while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ 114 while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
110 handled_sig = 1; 115 handled_sig = 1;
111 /* Whee! Actually deliver the signal. */ 116 /* Whee! Actually deliver the signal. */
112 if(!handle_signal(regs, sig, &ka_copy, &info, oldset)) 117 if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
118 /* a signal was successfully delivered; the saved
119 * sigmask will have been stored in the signal frame,
120 * and will be restored by sigreturn, so we can simply
121 * clear the TIF_RESTORE_SIGMASK flag */
122 if (test_thread_flag(TIF_RESTORE_SIGMASK))
123 clear_thread_flag(TIF_RESTORE_SIGMASK);
113 break; 124 break;
125 }
114 } 126 }
115 127
116 /* Did we come from a system call? */ 128 /* Did we come from a system call? */
117 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ 129 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
118 /* Restart the system call - no handlers present */ 130 /* Restart the system call - no handlers present */
119 if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || 131 switch(PT_REGS_SYSCALL_RET(regs)){
120 PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || 132 case -ERESTARTNOHAND:
121 PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ 133 case -ERESTARTSYS:
134 case -ERESTARTNOINTR:
122 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); 135 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
123 PT_REGS_RESTART_SYSCALL(regs); 136 PT_REGS_RESTART_SYSCALL(regs);
124 } 137 break;
125 else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){ 138 case -ERESTART_RESTARTBLOCK:
126 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; 139 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
127 PT_REGS_RESTART_SYSCALL(regs); 140 PT_REGS_RESTART_SYSCALL(regs);
141 break;
128 } 142 }
129 } 143 }
130 144
@@ -138,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
138 if(current->ptrace & PT_DTRACE) 152 if(current->ptrace & PT_DTRACE)
139 current->thread.singlestep_syscall = 153 current->thread.singlestep_syscall =
140 is_syscall(PT_REGS_IP(&current->thread.regs)); 154 is_syscall(PT_REGS_IP(&current->thread.regs));
155
156 /* if there's no signal to deliver, we just put the saved sigmask
157 * back */
158 if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
159 clear_thread_flag(TIF_RESTORE_SIGMASK);
160 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
161 }
141 return(handled_sig); 162 return(handled_sig);
142} 163}
143 164
144int do_signal(void) 165int do_signal(void)
145{ 166{
146 return(kern_do_signal(&current->thread.regs, &current->blocked)); 167 return(kern_do_signal(&current->thread.regs));
147} 168}
148 169
149/* 170/*
@@ -151,63 +172,20 @@ int do_signal(void)
151 */ 172 */
152long sys_sigsuspend(int history0, int history1, old_sigset_t mask) 173long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
153{ 174{
154 sigset_t saveset;
155
156 mask &= _BLOCKABLE; 175 mask &= _BLOCKABLE;
157 spin_lock_irq(&current->sighand->siglock); 176 spin_lock_irq(&current->sighand->siglock);
158 saveset = current->blocked; 177 current->saved_sigmask = current->blocked;
159 siginitset(&current->blocked, mask); 178 siginitset(&current->blocked, mask);
160 recalc_sigpending(); 179 recalc_sigpending();
161 spin_unlock_irq(&current->sighand->siglock); 180 spin_unlock_irq(&current->sighand->siglock);
162 181
163 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR; 182 current->state = TASK_INTERRUPTIBLE;
164 while (1) { 183 schedule();
165 current->state = TASK_INTERRUPTIBLE; 184 set_thread_flag(TIF_RESTORE_SIGMASK);
166 schedule(); 185 return -ERESTARTNOHAND;
167 if(kern_do_signal(&current->thread.regs, &saveset))
168 return(-EINTR);
169 }
170}
171
172long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
173{
174 sigset_t saveset, newset;
175
176 /* XXX: Don't preclude handling different sized sigset_t's. */
177 if (sigsetsize != sizeof(sigset_t))
178 return -EINVAL;
179
180 if (copy_from_user(&newset, unewset, sizeof(newset)))
181 return -EFAULT;
182 sigdelsetmask(&newset, ~_BLOCKABLE);
183
184 spin_lock_irq(&current->sighand->siglock);
185 saveset = current->blocked;
186 current->blocked = newset;
187 recalc_sigpending();
188 spin_unlock_irq(&current->sighand->siglock);
189
190 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
191 while (1) {
192 current->state = TASK_INTERRUPTIBLE;
193 schedule();
194 if (kern_do_signal(&current->thread.regs, &saveset))
195 return(-EINTR);
196 }
197} 186}
198 187
199long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) 188long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
200{ 189{
201 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs))); 190 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
202} 191}
203
204/*
205 * Overrides for Emacs so that we follow Linus's tabbing style.
206 * Emacs will notice this stuff at the end of the file and automatically
207 * adjust the settings for this buffer only. This must remain at the end
208 * of the file.
209 * ---------------------------------------------------------------------------
210 * Local variables:
211 * c-file-style: "linux"
212 * End:
213 */