diff options
| author | Anton Altaparmakov <aia21@cantab.net> | 2006-01-19 11:39:33 -0500 |
|---|---|---|
| committer | Anton Altaparmakov <aia21@cantab.net> | 2006-01-19 11:39:33 -0500 |
| commit | 944d79559d154c12becde0dab327016cf438f46c (patch) | |
| tree | 50c101806f4d3b6585222dda060559eb4f3e005a /arch/um/kernel/signal_kern.c | |
| parent | d087e4bdd24ebe3ae3d0b265b6573ec901af4b4b (diff) | |
| parent | 0f36b018b2e314d45af86449f1a97facb1fbe300 (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.c | 92 |
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 | ||
| 103 | static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) | 102 | static 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 = ¤t->saved_sigmask; | ||
| 111 | else | ||
| 112 | oldset = ¤t->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(¤t->thread.regs)); | 154 | is_syscall(PT_REGS_IP(¤t->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, ¤t->saved_sigmask, NULL); | ||
| 161 | } | ||
| 141 | return(handled_sig); | 162 | return(handled_sig); |
| 142 | } | 163 | } |
| 143 | 164 | ||
| 144 | int do_signal(void) | 165 | int do_signal(void) |
| 145 | { | 166 | { |
| 146 | return(kern_do_signal(¤t->thread.regs, ¤t->blocked)); | 167 | return(kern_do_signal(¤t->thread.regs)); |
| 147 | } | 168 | } |
| 148 | 169 | ||
| 149 | /* | 170 | /* |
| @@ -151,63 +172,20 @@ int do_signal(void) | |||
| 151 | */ | 172 | */ |
| 152 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask) | 173 | long 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(¤t->sighand->siglock); | 176 | spin_lock_irq(¤t->sighand->siglock); |
| 158 | saveset = current->blocked; | 177 | current->saved_sigmask = current->blocked; |
| 159 | siginitset(¤t->blocked, mask); | 178 | siginitset(¤t->blocked, mask); |
| 160 | recalc_sigpending(); | 179 | recalc_sigpending(); |
| 161 | spin_unlock_irq(¤t->sighand->siglock); | 180 | spin_unlock_irq(¤t->sighand->siglock); |
| 162 | 181 | ||
| 163 | PT_REGS_SYSCALL_RET(¤t->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(¤t->thread.regs, &saveset)) | ||
| 168 | return(-EINTR); | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | long 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(¤t->sighand->siglock); | ||
| 185 | saveset = current->blocked; | ||
| 186 | current->blocked = newset; | ||
| 187 | recalc_sigpending(); | ||
| 188 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 189 | |||
| 190 | PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; | ||
| 191 | while (1) { | ||
| 192 | current->state = TASK_INTERRUPTIBLE; | ||
| 193 | schedule(); | ||
| 194 | if (kern_do_signal(¤t->thread.regs, &saveset)) | ||
| 195 | return(-EINTR); | ||
| 196 | } | ||
| 197 | } | 186 | } |
| 198 | 187 | ||
| 199 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) | 188 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) |
| 200 | { | 189 | { |
| 201 | return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); | 190 | return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->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 | */ | ||
