Commit 7b3e2fc8 authored by Ralf Baechle's avatar Ralf Baechle

[MIPS] Add support for TIF_RESTORE_SIGMASK.

Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>

---
parent ac171c46
...@@ -58,8 +58,8 @@ ATTRIB_NORET void cpu_idle(void) ...@@ -58,8 +58,8 @@ ATTRIB_NORET void cpu_idle(void)
} }
} }
extern int do_signal(sigset_t *oldset, struct pt_regs *regs); extern int do_signal(struct pt_regs *regs);
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); extern int do_signal32(struct pt_regs *regs);
/* /*
* Native o32 and N64 ABI without DSP ASE * Native o32 and N64 ABI without DSP ASE
......
...@@ -39,8 +39,6 @@ ...@@ -39,8 +39,6 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #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. * Atomically swap in the new signal mask, and wait for a signal.
*/ */
...@@ -50,7 +48,7 @@ save_static_function(sys_sigsuspend); ...@@ -50,7 +48,7 @@ save_static_function(sys_sigsuspend);
__attribute_used__ noinline static int __attribute_used__ noinline static int
_sys_sigsuspend(nabi_no_regargs struct pt_regs regs) _sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
{ {
sigset_t saveset, newset; sigset_t newset;
sigset_t __user *uset; sigset_t __user *uset;
uset = (sigset_t __user *) regs.regs[4]; uset = (sigset_t __user *) regs.regs[4];
...@@ -59,19 +57,15 @@ _sys_sigsuspend(nabi_no_regargs struct pt_regs regs) ...@@ -59,19 +57,15 @@ _sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
sigdelsetmask(&newset, ~_BLOCKABLE); sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked; current->saved_sigmask = current->blocked;
current->blocked = newset; current->blocked = newset;
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
regs.regs[2] = EINTR;
regs.regs[7] = 1;
while (1) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
if (do_signal(&saveset, &regs)) set_thread_flag(TIF_RESTORE_SIGMASK);
return -EINTR; return -ERESTARTNOHAND;
}
} }
#endif #endif
...@@ -79,7 +73,7 @@ save_static_function(sys_rt_sigsuspend); ...@@ -79,7 +73,7 @@ save_static_function(sys_rt_sigsuspend);
__attribute_used__ noinline static int __attribute_used__ noinline static int
_sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
{ {
sigset_t saveset, newset; sigset_t newset;
sigset_t __user *unewset; sigset_t __user *unewset;
size_t sigsetsize; size_t sigsetsize;
...@@ -94,19 +88,15 @@ _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) ...@@ -94,19 +88,15 @@ _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
sigdelsetmask(&newset, ~_BLOCKABLE); sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked; current->saved_sigmask = current->blocked;
current->blocked = newset; current->blocked = newset;
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
regs.regs[2] = EINTR;
regs.regs[7] = 1;
while (1) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
if (do_signal(&saveset, &regs)) set_thread_flag(TIF_RESTORE_SIGMASK);
return -EINTR; return -ERESTARTNOHAND;
}
} }
#ifdef CONFIG_TRAD_SIGNALS #ifdef CONFIG_TRAD_SIGNALS
...@@ -315,11 +305,11 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -315,11 +305,11 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, frame->regs[31]); frame, regs->cp0_epc, frame->regs[31]);
#endif #endif
return 1; return 0;
give_sigsegv: give_sigsegv:
force_sigsegv(signr, current); force_sigsegv(signr, current);
return 0; return -EFAULT;
} }
#endif #endif
...@@ -375,11 +365,11 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -375,11 +365,11 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]); frame, regs->cp0_epc, regs->regs[31]);
#endif #endif
return 1; return 0;
give_sigsegv: give_sigsegv:
force_sigsegv(signr, current); force_sigsegv(signr, current);
return 0; return -EFAULT;
} }
static inline int handle_signal(unsigned long sig, siginfo_t *info, 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, ...@@ -393,7 +383,7 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
regs->regs[2] = EINTR; regs->regs[2] = EINTR;
break; break;
case ERESTARTSYS: case ERESTARTSYS:
if(!(ka->sa.sa_flags & SA_RESTART)) { if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->regs[2] = EINTR; regs->regs[2] = EINTR;
break; break;
} }
...@@ -420,9 +410,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, ...@@ -420,9 +410,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
return ret; return ret;
} }
int do_signal(sigset_t *oldset, struct pt_regs *regs) int do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
siginfo_t info; siginfo_t info;
int signr; int signr;
...@@ -437,12 +428,26 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -437,12 +428,26 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (try_to_freeze()) if (try_to_freeze())
goto no_signal; goto no_signal;
if (!oldset) if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) if (signr > 0) {
return handle_signal(signr, &info, &ka, oldset, regs); /* 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: no_signal:
/* /*
...@@ -463,18 +468,27 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -463,18 +468,27 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
regs->cp0_epc -= 4; 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, &current->saved_sigmask, NULL);
}
return 0; return 0;
} }
/* /*
* notification of userspace execution resumption * 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) __u32 thread_info_flags)
{ {
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING) { if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
current->thread.abi->do_signal(oldset, regs); current->thread.abi->do_signal(regs);
}
} }
...@@ -694,11 +694,11 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -694,11 +694,11 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, frame->sf_code); frame, regs->cp0_epc, frame->sf_code);
#endif #endif
return 1; return 0;
give_sigsegv: give_sigsegv:
force_sigsegv(signr, current); force_sigsegv(signr, current);
return 0; return -EFAULT;
} }
int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, 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, ...@@ -765,11 +765,11 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, frame->rs_code); frame, regs->cp0_epc, frame->rs_code);
#endif #endif
return 1; return 0;
give_sigsegv: give_sigsegv:
force_sigsegv(signr, current); force_sigsegv(signr, current);
return 0; return -EFAULT;
} }
static inline int handle_signal(unsigned long sig, siginfo_t *info, static inline int handle_signal(unsigned long sig, siginfo_t *info,
......
...@@ -186,9 +186,9 @@ int setup_rt_frame_n32(struct k_sigaction * ka, ...@@ -186,9 +186,9 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]); frame, regs->cp0_epc, regs->regs[31]);
#endif #endif
return 1; return 0;
give_sigsegv: give_sigsegv:
force_sigsegv(signr, current); force_sigsegv(signr, current);
return 0; return -EFAULT;
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * 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. * Copyright (C) 2005 MIPS Technologies, Inc.
*/ */
#ifndef _ASM_ABI_H #ifndef _ASM_ABI_H
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <asm/siginfo.h> #include <asm/siginfo.h>
struct mips_abi { 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, int (* const setup_frame)(struct k_sigaction * ka,
struct pt_regs *regs, int signr, struct pt_regs *regs, int signr,
sigset_t *set); sigset_t *set);
......
...@@ -114,6 +114,7 @@ register struct thread_info *__current_thread_info __asm__("$28"); ...@@ -114,6 +114,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */ #define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */
#define TIF_SECCOMP 5 /* secure computing */ #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_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_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 18 #define TIF_MEMDIE 18
...@@ -125,6 +126,7 @@ register struct thread_info *__current_thread_info __asm__("$28"); ...@@ -125,6 +126,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1<<TIF_SECCOMP) #define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_USEDFPU (1<<TIF_USEDFPU) #define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment