aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2006-01-18 20:44:02 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-18 22:20:30 -0500
commit2fc10620e741153329e2f1cbcde76e526f501410 (patch)
treed93344bc160f4f2455d4a4947d6347c1ff9b6fd2 /arch/um
parentf27201da5c8f118cfe266f51447bdd108d5f081d (diff)
[PATCH] uml: add TIF_RESTORE_SIGMASK support
Add support for TIF_RESTORE_SIGMASK. I copy the i386 handling of the flag. sys_sigsuspend is also changed to follow i386. Also a bit of cleanup - turn an if into a switch get rid of a couple more emacs formatting comments Signed-off-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/kernel/signal_kern.c79
1 files changed, 41 insertions, 38 deletions
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 7b0e0e81c161..7a54708db50c 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -99,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
99 return err; 99 return err;
100} 100}
101 101
102static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) 102static int kern_do_signal(struct pt_regs *regs)
103{ 103{
104 struct k_sigaction ka_copy; 104 struct k_sigaction ka_copy;
105 siginfo_t info; 105 siginfo_t info;
106 sigset_t *oldset;
106 int sig, handled_sig = 0; 107 int sig, handled_sig = 0;
107 108
109 if (test_thread_flag(TIF_RESTORE_SIGMASK))
110 oldset = &current->saved_sigmask;
111 else
112 oldset = &current->blocked;
113
108 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){
109 handled_sig = 1; 115 handled_sig = 1;
110 /* Whee! Actually deliver the signal. */ 116 /* Whee! Actually deliver the signal. */
111 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);
112 break; 124 break;
125 }
113 } 126 }
114 127
115 /* Did we come from a system call? */ 128 /* Did we come from a system call? */
116 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ 129 if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
117 /* Restart the system call - no handlers present */ 130 /* Restart the system call - no handlers present */
118 if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || 131 switch(PT_REGS_SYSCALL_RET(regs)){
119 PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || 132 case -ERESTARTNOHAND:
120 PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ 133 case -ERESTARTSYS:
134 case -ERESTARTNOINTR:
121 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); 135 PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
122 PT_REGS_RESTART_SYSCALL(regs); 136 PT_REGS_RESTART_SYSCALL(regs);
123 } 137 break;
124 else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){ 138 case -ERESTART_RESTARTBLOCK:
125 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; 139 PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
126 PT_REGS_RESTART_SYSCALL(regs); 140 PT_REGS_RESTART_SYSCALL(regs);
141 break;
127 } 142 }
128 } 143 }
129 144
@@ -137,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
137 if(current->ptrace & PT_DTRACE) 152 if(current->ptrace & PT_DTRACE)
138 current->thread.singlestep_syscall = 153 current->thread.singlestep_syscall =
139 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 }
140 return(handled_sig); 162 return(handled_sig);
141} 163}
142 164
143int do_signal(void) 165int do_signal(void)
144{ 166{
145 return(kern_do_signal(&current->thread.regs, &current->blocked)); 167 return(kern_do_signal(&current->thread.regs));
146} 168}
147 169
148/* 170/*
@@ -150,27 +172,22 @@ int do_signal(void)
150 */ 172 */
151long sys_sigsuspend(int history0, int history1, old_sigset_t mask) 173long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
152{ 174{
153 sigset_t saveset;
154
155 mask &= _BLOCKABLE; 175 mask &= _BLOCKABLE;
156 spin_lock_irq(&current->sighand->siglock); 176 spin_lock_irq(&current->sighand->siglock);
157 saveset = current->blocked; 177 current->saved_sigmask = current->blocked;
158 siginitset(&current->blocked, mask); 178 siginitset(&current->blocked, mask);
159 recalc_sigpending(); 179 recalc_sigpending();
160 spin_unlock_irq(&current->sighand->siglock); 180 spin_unlock_irq(&current->sighand->siglock);
161 181
162 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR; 182 current->state = TASK_INTERRUPTIBLE;
163 while (1) { 183 schedule();
164 current->state = TASK_INTERRUPTIBLE; 184 set_thread_flag(TIF_RESTORE_SIGMASK);
165 schedule(); 185 return -ERESTARTNOHAND;
166 if(kern_do_signal(&current->thread.regs, &saveset))
167 return(-EINTR);
168 }
169} 186}
170 187
171long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) 188long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
172{ 189{
173 sigset_t saveset, newset; 190 sigset_t newset;
174 191
175 /* XXX: Don't preclude handling different sized sigset_t's. */ 192 /* XXX: Don't preclude handling different sized sigset_t's. */
176 if (sigsetsize != sizeof(sigset_t)) 193 if (sigsetsize != sizeof(sigset_t))
@@ -181,32 +198,18 @@ long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
181 sigdelsetmask(&newset, ~_BLOCKABLE); 198 sigdelsetmask(&newset, ~_BLOCKABLE);
182 199
183 spin_lock_irq(&current->sighand->siglock); 200 spin_lock_irq(&current->sighand->siglock);
184 saveset = current->blocked; 201 current->saved_sigmask = current->blocked;
185 current->blocked = newset; 202 current->blocked = newset;
186 recalc_sigpending(); 203 recalc_sigpending();
187 spin_unlock_irq(&current->sighand->siglock); 204 spin_unlock_irq(&current->sighand->siglock);
188 205
189 PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR; 206 current->state = TASK_INTERRUPTIBLE;
190 while (1) { 207 schedule();
191 current->state = TASK_INTERRUPTIBLE; 208 set_thread_flag(TIF_RESTORE_SIGMASK);
192 schedule(); 209 return -ERESTARTNOHAND;
193 if (kern_do_signal(&current->thread.regs, &saveset))
194 return(-EINTR);
195 }
196} 210}
197 211
198long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) 212long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
199{ 213{
200 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs))); 214 return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
201} 215}
202
203/*
204 * Overrides for Emacs so that we follow Linus's tabbing style.
205 * Emacs will notice this stuff at the end of the file and automatically
206 * adjust the settings for this buffer only. This must remain at the end
207 * of the file.
208 * ---------------------------------------------------------------------------
209 * Local variables:
210 * c-file-style: "linux"
211 * End:
212 */