forked from luck/tmp_suning_uos_patched
sparc64: Fix syscall restart, for real...
The change I put into copy_thread() just papered over the real problem. When we are looking to see if we should do a syscall restart, when deliverying a signal, we should only interpret the syscall return value as an error if the carry condition code(s) are set. Otherwise it's a success return. Also, sigreturn paths should do a pt_regs_clear_trap_type(). It turns out that doing a syscall restart when returning from a fork() does and should happen, from time to time. Even if copy_thread() returns success, copy_process() can still unwind and signal -ERESTARTNOINTR in the parent. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
32039f4954
commit
2678fefedb
@ -591,12 +591,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
|
|||||||
if (clone_flags & CLONE_SETTLS)
|
if (clone_flags & CLONE_SETTLS)
|
||||||
t->kregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3];
|
t->kregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3];
|
||||||
|
|
||||||
/* We do not want to accidently trigger system call restart
|
|
||||||
* handling in the new thread. Therefore, clear out the trap
|
|
||||||
* type, which will make pt_regs_regs_is_syscall() return false.
|
|
||||||
*/
|
|
||||||
pt_regs_clear_trap_type(t->kregs);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,6 +332,9 @@ void do_rt_sigreturn(struct pt_regs *regs)
|
|||||||
regs->tpc = tpc;
|
regs->tpc = tpc;
|
||||||
regs->tnpc = tnpc;
|
regs->tnpc = tnpc;
|
||||||
|
|
||||||
|
/* Prevent syscall restart. */
|
||||||
|
pt_regs_clear_trap_type(regs);
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
current->blocked = set;
|
current->blocked = set;
|
||||||
@ -515,7 +518,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
|||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
int signr;
|
int signr;
|
||||||
|
|
||||||
if (pt_regs_is_syscall(regs)) {
|
if (pt_regs_is_syscall(regs) &&
|
||||||
|
(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
|
||||||
pt_regs_clear_trap_type(regs);
|
pt_regs_clear_trap_type(regs);
|
||||||
cookie.restart_syscall = 1;
|
cookie.restart_syscall = 1;
|
||||||
} else
|
} else
|
||||||
|
@ -268,6 +268,9 @@ void do_sigreturn32(struct pt_regs *regs)
|
|||||||
regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
|
regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
|
||||||
regs->tstate |= psr_to_tstate_icc(psr);
|
regs->tstate |= psr_to_tstate_icc(psr);
|
||||||
|
|
||||||
|
/* Prevent syscall restart. */
|
||||||
|
pt_regs_clear_trap_type(regs);
|
||||||
|
|
||||||
err |= __get_user(fpu_save, &sf->fpu_save);
|
err |= __get_user(fpu_save, &sf->fpu_save);
|
||||||
if (fpu_save)
|
if (fpu_save)
|
||||||
err |= restore_fpu_state32(regs, &sf->fpu_state);
|
err |= restore_fpu_state32(regs, &sf->fpu_state);
|
||||||
@ -351,6 +354,9 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
|
|||||||
regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
|
regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
|
||||||
regs->tstate |= psr_to_tstate_icc(psr);
|
regs->tstate |= psr_to_tstate_icc(psr);
|
||||||
|
|
||||||
|
/* Prevent syscall restart. */
|
||||||
|
pt_regs_clear_trap_type(regs);
|
||||||
|
|
||||||
err |= __get_user(fpu_save, &sf->fpu_save);
|
err |= __get_user(fpu_save, &sf->fpu_save);
|
||||||
if (fpu_save)
|
if (fpu_save)
|
||||||
err |= restore_fpu_state32(regs, &sf->fpu_state);
|
err |= restore_fpu_state32(regs, &sf->fpu_state);
|
||||||
|
Loading…
Reference in New Issue
Block a user