[IA64] Add TIF_RESTORE_SIGMASK
Preparation for pselect and ppoll. ia32 compat code not tested. :-( Signed-off-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> Signed-off-by: Alexey Dobriyan <adobriyan@openvz.org> Signed-off-by: Tony Luck <tony.luck@intel.com>
This commit is contained in:
parent
690def2141
commit
4a177cbf84
|
@ -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(¤t->sighand->siglock);
|
||||
{
|
||||
oldset = current->blocked;
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
}
|
||||
current->saved_sigmask = current->blocked;
|
||||
siginitset(¤t->blocked, mask);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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(¤t->sighand->siglock);
|
||||
{
|
||||
oldset = current->blocked;
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
}
|
||||
spin_unlock_irq(¤t->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 = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->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, ¤t->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
|
||||
|
||||
|
|
Loading…
Reference in New Issue