aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/kernel/signal_kern.c79
-rw-r--r--include/asm-um/thread_info.h13
2 files changed, 43 insertions, 49 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 */
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 705c71972c32..17b6b07c4332 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -69,6 +69,7 @@ static inline struct thread_info *current_thread_info(void)
69#define TIF_RESTART_BLOCK 4 69#define TIF_RESTART_BLOCK 4
70#define TIF_MEMDIE 5 70#define TIF_MEMDIE 5
71#define TIF_SYSCALL_AUDIT 6 71#define TIF_SYSCALL_AUDIT 6
72#define TIF_RESTORE_SIGMASK 7
72 73
73#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) 74#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
74#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) 75#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
@@ -76,16 +77,6 @@ static inline struct thread_info *current_thread_info(void)
76#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) 77#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
77#define _TIF_MEMDIE (1 << TIF_MEMDIE) 78#define _TIF_MEMDIE (1 << TIF_MEMDIE)
78#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) 79#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
80#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
79 81
80#endif 82#endif
81
82/*
83 * Overrides for Emacs so that we follow Linus's tabbing style.
84 * Emacs will notice this stuff at the end of the file and automatically
85 * adjust the settings for this buffer only. This must remain at the end
86 * of the file.
87 * ---------------------------------------------------------------------------
88 * Local variables:
89 * c-file-style: "linux"
90 * End:
91 */