[MIPS] Add support for TIF_RESTORE_SIGMASK.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org> ---
This commit is contained in:
parent
ac171c4666
commit
7b3e2fc847
6 changed files with 62 additions and 46 deletions
|
@ -58,8 +58,8 @@ ATTRIB_NORET void cpu_idle(void)
|
|||
}
|
||||
}
|
||||
|
||||
extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
|
||||
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
|
||||
extern int do_signal(struct pt_regs *regs);
|
||||
extern int do_signal32(struct pt_regs *regs);
|
||||
|
||||
/*
|
||||
* Native o32 and N64 ABI without DSP ASE
|
||||
|
|
|
@ -39,8 +39,6 @@
|
|||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
int do_signal(sigset_t *oldset, struct pt_regs *regs);
|
||||
|
||||
/*
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
*/
|
||||
|
@ -50,7 +48,7 @@ save_static_function(sys_sigsuspend);
|
|||
__attribute_used__ noinline static int
|
||||
_sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
sigset_t saveset, newset;
|
||||
sigset_t newset;
|
||||
sigset_t __user *uset;
|
||||
|
||||
uset = (sigset_t __user *) regs.regs[4];
|
||||
|
@ -59,19 +57,15 @@ _sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
|||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->saved_sigmask = current->blocked;
|
||||
current->blocked = newset;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs.regs[2] = EINTR;
|
||||
regs.regs[7] = 1;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(&saveset, ®s))
|
||||
return -EINTR;
|
||||
}
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -79,7 +73,7 @@ save_static_function(sys_rt_sigsuspend);
|
|||
__attribute_used__ noinline static int
|
||||
_sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
sigset_t saveset, newset;
|
||||
sigset_t newset;
|
||||
sigset_t __user *unewset;
|
||||
size_t sigsetsize;
|
||||
|
||||
|
@ -94,19 +88,15 @@ _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
|||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->saved_sigmask = current->blocked;
|
||||
current->blocked = newset;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
regs.regs[2] = EINTR;
|
||||
regs.regs[7] = 1;
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(&saveset, ®s))
|
||||
return -EINTR;
|
||||
}
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TRAD_SIGNALS
|
||||
|
@ -315,11 +305,11 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
|
|||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, frame->regs[31]);
|
||||
#endif
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -375,11 +365,11 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
|
|||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, regs->regs[31]);
|
||||
#endif
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
|
@ -393,7 +383,7 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
|
|||
regs->regs[2] = EINTR;
|
||||
break;
|
||||
case ERESTARTSYS:
|
||||
if(!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
regs->regs[2] = EINTR;
|
||||
break;
|
||||
}
|
||||
|
@ -420,9 +410,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
||||
int do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
|
||||
|
@ -437,12 +428,26 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
|||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
if (!oldset)
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0)
|
||||
return handle_signal(signr, &info, &ka, oldset, regs);
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
|
||||
/*
|
||||
* A signal was successfully delivered; the saved
|
||||
* sigmask will have been stored in the signal frame,
|
||||
* and will be restored by sigreturn, so we can simply
|
||||
* clear the TIF_RESTORE_SIGMASK flag.
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
}
|
||||
}
|
||||
|
||||
no_signal:
|
||||
/*
|
||||
|
@ -463,18 +468,27 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
|
|||
regs->cp0_epc -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's no signal to deliver, we just put the saved sigmask
|
||||
* back
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* notification of userspace execution resumption
|
||||
* - triggered by current->work.notify_resume
|
||||
* - triggered by the TIF_WORK_MASK flags
|
||||
*/
|
||||
asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
|
||||
asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
|
||||
__u32 thread_info_flags)
|
||||
{
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & _TIF_SIGPENDING) {
|
||||
current->thread.abi->do_signal(oldset, regs);
|
||||
}
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
current->thread.abi->do_signal(regs);
|
||||
}
|
||||
|
|
|
@ -694,11 +694,11 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
|
|||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, frame->sf_code);
|
||||
#endif
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
|
||||
|
@ -765,11 +765,11 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
|
|||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, frame->rs_code);
|
||||
#endif
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
|
|
|
@ -186,9 +186,9 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
|
|||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, regs->regs[31]);
|
||||
#endif
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return 0;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2005 by Ralf Baechle
|
||||
* Copyright (C) 2005, 06 by Ralf Baechle (ralf@linux-mips.org)
|
||||
* Copyright (C) 2005 MIPS Technologies, Inc.
|
||||
*/
|
||||
#ifndef _ASM_ABI_H
|
||||
|
@ -13,7 +13,7 @@
|
|||
#include <asm/siginfo.h>
|
||||
|
||||
struct mips_abi {
|
||||
int (* const do_signal)(sigset_t *oldset, struct pt_regs *regs);
|
||||
int (* const do_signal)(struct pt_regs *regs);
|
||||
int (* const setup_frame)(struct k_sigaction * ka,
|
||||
struct pt_regs *regs, int signr,
|
||||
sigset_t *set);
|
||||
|
|
|
@ -114,6 +114,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
|
|||
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
|
||||
#define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */
|
||||
#define TIF_SECCOMP 5 /* secure computing */
|
||||
#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */
|
||||
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
|
||||
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
|
||||
#define TIF_MEMDIE 18
|
||||
|
@ -125,6 +126,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
|
|||
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
|
||||
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
|
||||
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
|
||||
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
|
||||
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
|
||||
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
|
||||
|
||||
|
|
Loading…
Reference in a new issue