Commit 4a177cbf authored by Alexey Dobriyan's avatar Alexey Dobriyan Committed by Tony Luck

[IA64] Add TIF_RESTORE_SIGMASK

Preparation for pselect and ppoll.
ia32 compat code not tested. :-(
Signed-off-by: default avatarAlexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Signed-off-by: default avatarAlexey Dobriyan <adobriyan@openvz.org>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 690def21
......@@ -52,43 +52,6 @@ ENTRY(ia32_clone)
br.ret.sptk.many rp
END(ia32_clone)
ENTRY(sys32_rt_sigsuspend)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
mov loc0=rp
mov out0=in0 // mask
mov out1=in1 // sigsetsize
mov out2=sp // out2 = &sigscratch
.fframe 16
adds sp=-16,sp // allocate dummy "sigscratch"
;;
.body
br.call.sptk.many rp=ia32_rt_sigsuspend
1: .restore sp
adds sp=16,sp
mov rp=loc0
mov ar.pfs=loc1
br.ret.sptk.many rp
END(sys32_rt_sigsuspend)
ENTRY(sys32_sigsuspend)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
mov loc0=rp
mov out0=in2 // mask (first two args are ignored)
;;
mov out1=sp // out1 = &sigscratch
.fframe 16
adds sp=-16,sp // allocate dummy "sigscratch"
.body
br.call.sptk.many rp=ia32_sigsuspend
1: .restore sp
adds sp=16,sp
mov rp=loc0
mov ar.pfs=loc1
br.ret.sptk.many rp
END(sys32_sigsuspend)
GLOBAL_ENTRY(ia32_ret_from_clone)
PT_REGS_UNWIND_INFO(0)
{ /*
......@@ -389,7 +352,7 @@ ia32_syscall_table:
data8 sys_rt_sigpending
data8 compat_sys_rt_sigtimedwait
data8 sys32_rt_sigqueueinfo
data8 sys32_rt_sigsuspend
data8 compat_sys_rt_sigsuspend
data8 sys32_pread /* 180 */
data8 sys32_pwrite
data8 sys_chown /* 16-bit version */
......
......@@ -452,59 +452,20 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r
sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
}
long
__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr)
asmlinkage long
sys32_sigsuspend (int history0, int history1, old_sigset_t mask)
{
extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall);
sigset_t oldset, set;
scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */
memset(&set, 0, sizeof(set));
memcpy(&set.sig, &sset->sig, sigsetsize);
sigdelsetmask(&set, ~_BLOCKABLE);
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
{
oldset = current->blocked;
current->blocked = set;
recalc_sigpending();
}
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
/*
* The return below usually returns to the signal handler. We need to pre-set the
* correct error code here to ensure that the right values get saved in sigcontext
* by ia64_do_signal.
*/
scr->pt.r8 = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (ia64_do_signal(&oldset, scr, 1))
return -EINTR;
}
}
asmlinkage long
ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr)
{
compat_sigset_t set;
if (sigsetsize > sizeof(compat_sigset_t))
return -EINVAL;
if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
return -EFAULT;
return __ia32_rt_sigsuspend(&set, sigsetsize, scr);
}
asmlinkage long
ia32_sigsuspend (unsigned int mask, struct sigscratch *scr)
{
return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr);
current->state = TASK_INTERRUPTIBLE;
schedule();
set_thread_flag(TIF_RESTORE_SIGMASK);
return -ERESTARTNOHAND;
}
asmlinkage long
......
......@@ -1199,32 +1199,6 @@ ENTRY(notify_resume_user)
br.ret.sptk.many rp
END(notify_resume_user)
GLOBAL_ENTRY(sys_rt_sigsuspend)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
mov r9=ar.unat
mov loc0=rp // save return address
mov out0=in0 // mask
mov out1=in1 // sigsetsize
adds out2=8,sp // out2=&sigscratch->ar_pfs
;;
.fframe 16
.spillsp ar.unat, 16
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
.body
br.call.sptk.many rp=ia64_rt_sigsuspend
.ret17: .restore sp
adds sp=16,sp // pop scratch stack space
;;
ld8 r9=[sp] // load new unat from sw->caller_unat
mov rp=loc0
;;
mov ar.unat=r9
mov ar.pfs=loc1
br.ret.sptk.many rp
END(sys_rt_sigsuspend)
ENTRY(sys_rt_sigreturn)
PT_REGS_UNWIND_INFO(0)
/*
......
......@@ -156,7 +156,7 @@ show_regs (struct pt_regs *regs)
}
void
do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall)
{
if (fsys_mode(current, &scr->pt)) {
/* defer signal-handling etc. until we return to privilege-level 0. */
......@@ -171,8 +171,8 @@ do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall
#endif
/* deal with pending signal delivery */
if (test_thread_flag(TIF_SIGPENDING))
ia64_do_signal(oldset, scr, in_syscall);
if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
ia64_do_signal(scr, in_syscall);
}
static int pal_halt = 1;
......
......@@ -22,4 +22,4 @@ struct sigframe {
struct sigcontext sc;
};
extern long ia64_do_signal (sigset_t *, struct sigscratch *, long);
extern void ia64_do_signal (struct sigscratch *, long);
......@@ -41,47 +41,6 @@
# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0])
#endif
long
ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr)
{
sigset_t oldset, set;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (!access_ok(VERIFY_READ, uset, sigsetsize))
return -EFAULT;
if (GET_SIGSET(&set, uset))
return -EFAULT;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
{
oldset = current->blocked;
current->blocked = set;
recalc_sigpending();
}
spin_unlock_irq(&current->sighand->siglock);
/*
* The return below usually returns to the signal handler. We need to
* pre-set the correct error code here to ensure that the right values
* get saved in sigcontext by ia64_do_signal.
*/
scr->pt.r8 = EINTR;
scr->pt.r10 = -1;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (ia64_do_signal(&oldset, scr, 1))
return -EINTR;
}
}
asmlinkage long
sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2,
long arg3, long arg4, long arg5, long arg6, long arg7,
......@@ -478,10 +437,11 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
* Note that `init' is a special process: it doesn't get signals it doesn't want to
* handle. Thus you cannot kill init even with a SIGKILL even by mistake.
*/
long
ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
void
ia64_do_signal (struct sigscratch *scr, long in_syscall)
{
struct k_sigaction ka;
sigset_t *oldset;
siginfo_t info;
long restart = in_syscall;
long errno = scr->pt.r8;
......@@ -493,9 +453,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
* doing anything if so.
*/
if (!user_mode(&scr->pt))
return 0;
return;
if (!oldset)
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
/*
......@@ -558,8 +520,15 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
* Whee! Actually deliver the signal. If the delivery failed, we need to
* continue to iterate in this loop so we can deliver the SIGSEGV...
*/
if (handle_signal(signr, &ka, &info, oldset, scr))
return 1;
if (handle_signal(signr, &ka, &info, oldset, scr)) {
/* 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);
return;
}
}
/* Did we come from a system call? */
......@@ -585,5 +554,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
}
}
}
return 0;
/* 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);
}
}
......@@ -85,6 +85,7 @@ struct thread_info {
#define TIF_SYSCALL_TRACE 3 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */
#define TIF_SINGLESTEP 5 /* restore singlestep on return to user mode */
#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17
#define TIF_MCA_INIT 18 /* this task is processing MCA or INIT */
......@@ -96,6 +97,7 @@ struct thread_info {
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_SYSCALL_TRACEAUDIT (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
......@@ -104,7 +106,7 @@ struct thread_info {
#define _TIF_FREEZE (1 << TIF_FREEZE)
/* "work to do on user-return" bits */
#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
#define TIF_ALLWORK_MASK (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_RESTORE_SIGMASK)
/* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */
#define TIF_WORK_MASK (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
......
......@@ -300,6 +300,7 @@
#define NR_syscalls 281 /* length of syscall table */
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#ifdef CONFIG_IA32_SUPPORT
# define __ARCH_WANT_SYS_FADVISE64
......@@ -310,6 +311,7 @@
# define __ARCH_WANT_SYS_OLDUMOUNT
# define __ARCH_WANT_SYS_SIGPENDING
# define __ARCH_WANT_SYS_SIGPROCMASK
# define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
# define __ARCH_WANT_COMPAT_SYS_TIME
#endif
......
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