diff options
Diffstat (limited to 'arch/alpha/kernel/signal.c')
| -rw-r--r-- | arch/alpha/kernel/signal.c | 48 | 
1 files changed, 28 insertions, 20 deletions
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index a8c97d42ec8..32575f85507 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -298,8 +298,9 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)  static long  setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,  -		 struct switch_stack *sw, unsigned long mask, unsigned long sp) +		 unsigned long mask, unsigned long sp)  { +	struct switch_stack *sw = (struct switch_stack *)regs - 1;  	long i, err = 0;  	err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack); @@ -354,7 +355,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,  static int  setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, -	    struct pt_regs *regs, struct switch_stack * sw) +	    struct pt_regs *regs)  {  	unsigned long oldsp, r26, err = 0;  	struct sigframe __user *frame; @@ -364,7 +365,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,  	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))  		return -EFAULT; -	err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); +	err |= setup_sigcontext(&frame->sc, regs, set->sig[0], oldsp);  	if (err)  		return -EFAULT; @@ -401,7 +402,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,  static int  setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, -	       sigset_t *set, struct pt_regs *regs, struct switch_stack * sw) +	       sigset_t *set, struct pt_regs *regs)  {  	unsigned long oldsp, r26, err = 0;  	struct rt_sigframe __user *frame; @@ -420,7 +421,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);  	err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);  	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); -	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw, +	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs,   				set->sig[0], oldsp);  	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));  	if (err) @@ -464,15 +465,15 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,   */  static inline void  handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, -	      struct pt_regs * regs, struct switch_stack *sw) +	      struct pt_regs * regs)  {  	sigset_t *oldset = sigmask_to_save();  	int ret;  	if (ka->sa.sa_flags & SA_SIGINFO) -		ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); +		ret = setup_rt_frame(sig, ka, info, oldset, regs);  	else -		ret = setup_frame(sig, ka, oldset, regs, sw); +		ret = setup_frame(sig, ka, oldset, regs);  	if (ret) {  		force_sigsegv(sig, current); @@ -519,8 +520,7 @@ syscall_restart(unsigned long r0, unsigned long r19,   * all (if we get here from anything but a syscall return, it will be 0)   */  static void -do_signal(struct pt_regs * regs, struct switch_stack * sw, -	  unsigned long r0, unsigned long r19) +do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)  {  	siginfo_t info;  	int signr; @@ -537,7 +537,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,  		/* Whee!  Actually deliver the signal.  */  		if (r0)  			syscall_restart(r0, r19, regs, &ka); -		handle_signal(signr, &ka, &info, regs, sw); +		handle_signal(signr, &ka, &info, regs);  		if (single_stepping)   			ptrace_set_bpt(current); /* re-set bpt */  		return; @@ -568,15 +568,23 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,  }  void -do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, -		 unsigned long thread_info_flags, +do_work_pending(struct pt_regs *regs, unsigned long thread_flags,  		 unsigned long r0, unsigned long r19)  { -	if (thread_info_flags & _TIF_SIGPENDING) -		do_signal(regs, sw, r0, r19); - -	if (thread_info_flags & _TIF_NOTIFY_RESUME) { -		clear_thread_flag(TIF_NOTIFY_RESUME); -		tracehook_notify_resume(regs); -	} +	do { +		if (thread_flags & _TIF_NEED_RESCHED) { +			schedule(); +		} else { +			local_irq_enable(); +			if (thread_flags & _TIF_SIGPENDING) { +				do_signal(regs, r0, r19); +				r0 = 0; +			} else { +				clear_thread_flag(TIF_NOTIFY_RESUME); +				tracehook_notify_resume(regs); +			} +		} +		local_irq_disable(); +		thread_flags = current_thread_info()->flags; +	} while (thread_flags & _TIF_WORK_MASK);  }  |