[PARISC] Add TIF_RESTORE_SIGMASK support

And unmask the pselect6/ppoll system calls.

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
This commit is contained in:
Kyle McMartin 2007-01-08 16:28:06 -05:00 committed by Kyle McMartin
parent 0bbdac0897
commit 4650f0a583
5 changed files with 88 additions and 137 deletions

View File

@ -978,11 +978,39 @@ intr_check_resched:
LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
.import do_notify_resume,code
intr_check_sig:
/* As above */
mfctl %cr30,%r1
LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_SIGPENDING */
bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
LDREG TI_FLAGS(%r1),%r19
load32 (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r20
and,COND(<>) %r19, %r20, %r0
b,n intr_restore /* skip past if we've nothing to do */
/* This check is critical to having LWS
* working. The IASQ is zero on the gateway
* page and we cannot deliver any signals until
* we get off the gateway page.
*
* Only do signals if we are returning to user space
*/
LDREG PT_IASQ0(%r16), %r20
CMPIB= 0,%r20,intr_restore /* backward */
nop
LDREG PT_IASQ1(%r16), %r20
CMPIB= 0,%r20,intr_restore /* backward */
nop
copy %r0, %r25 /* long in_syscall = 0 */
#ifdef CONFIG_64BIT
ldo -16(%r30),%r29 /* Reference param save area */
#endif
BL do_notify_resume,%r2
copy %r16, %r26 /* struct pt_regs *regs */
b intr_check_sig
nop
intr_restore:
copy %r16,%r29
@ -1072,35 +1100,6 @@ intr_do_preempt:
b,n intr_restore /* ssm PSW_SM_I done by intr_restore */
#endif /* CONFIG_PREEMPT */
.import do_signal,code
intr_do_signal:
/*
This check is critical to having LWS
working. The IASQ is zero on the gateway
page and we cannot deliver any signals until
we get off the gateway page.
Only do signals if we are returning to user space
*/
LDREG PT_IASQ0(%r16), %r20
CMPIB= 0,%r20,intr_restore /* backward */
nop
LDREG PT_IASQ1(%r16), %r20
CMPIB= 0,%r20,intr_restore /* backward */
nop
copy %r0, %r24 /* unsigned long in_syscall */
copy %r16, %r25 /* struct pt_regs *regs */
#ifdef CONFIG_64BIT
ldo -16(%r30),%r29 /* Reference param save area */
#endif
BL do_signal,%r2
copy %r0, %r26 /* sigset_t *oldset = NULL */
b intr_check_sig
nop
/*
* External interrupts.
*/
@ -2024,32 +2023,6 @@ sys32_sigaltstack_wrapper:
nop
#endif
.export sys_rt_sigsuspend_wrapper
sys_rt_sigsuspend_wrapper:
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
ldo TASK_REGS(%r1),%r24
reg_save %r24
STREG %r2, -RP_OFFSET(%r30)
#ifdef CONFIG_64BIT
ldo FRAME_SIZE(%r30), %r30
BL sys_rt_sigsuspend,%r2
ldo -16(%r30),%r29 /* Reference param save area */
#else
BL sys_rt_sigsuspend,%r2
ldo FRAME_SIZE(%r30), %r30
#endif
ldo -FRAME_SIZE(%r30), %r30
LDREG -RP_OFFSET(%r30), %r2
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
ldo TASK_REGS(%r1),%r1
reg_restore %r1
bv %r0(%r2)
nop
.export syscall_exit
syscall_exit:
@ -2115,9 +2088,35 @@ syscall_check_resched:
LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */
bb,<,n %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
.import do_signal,code
syscall_check_sig:
LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* get ti flags */
bb,<,n %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
load32 (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r26
and,COND(<>) %r19, %r26, %r0
b,n syscall_restore /* skip past if we've nothing to do */
syscall_do_signal:
/* Save callee-save registers (for sigcontext).
* FIXME: After this point the process structure should be
* consistent with all the relevant state of the process
* before the syscall. We need to verify this.
*/
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
ldo TASK_REGS(%r1), %r26 /* struct pt_regs *regs */
reg_save %r26
#ifdef CONFIG_64BIT
ldo -16(%r30),%r29 /* Reference param save area */
#endif
BL do_notify_resume,%r2
ldi 1, %r25 /* long in_syscall = 1 */
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
reg_restore %r20
b,n syscall_check_sig
syscall_restore:
/* Are we being ptraced? */
@ -2256,30 +2255,6 @@ syscall_do_resched:
b syscall_check_bh /* if resched, we start over again */
nop
.import do_signal,code
syscall_do_signal:
/* Save callee-save registers (for sigcontext).
FIXME: After this point the process structure should be
consistent with all the relevant state of the process
before the syscall. We need to verify this. */
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */
reg_save %r25
ldi 1, %r24 /* unsigned long in_syscall */
#ifdef CONFIG_64BIT
ldo -16(%r30),%r29 /* Reference param save area */
#endif
BL do_signal,%r2
copy %r0, %r26 /* sigset_t *oldset = NULL */
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
reg_restore %r20
b,n syscall_check_sig
/*
* get_register is used by the non access tlb miss handlers to
* copy the value of the general register specified in r8 into

View File

@ -59,8 +59,6 @@
* this. */
#define A(__x) ((unsigned long)(__x))
int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
@ -68,49 +66,6 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
#include "sys32.h"
#endif
asmlinkage int
sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
{
sigset_t saveset, newset;
#ifdef __LP64__
compat_sigset_t newset32;
if (is_compat_task()) {
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(compat_sigset_t))
return -EINVAL;
if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
return -EFAULT;
sigset_32to64(&newset,&newset32);
} else
#endif
{
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (copy_from_user(&newset, unewset, sizeof(newset)))
return -EFAULT;
}
sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
regs->gr[28] = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(&saveset, regs, 1))
return -EINTR;
}
}
/*
* Do a signal return - restore sigcontext.
*/
@ -528,12 +483,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
* us due to the magic of delayed branching.
*/
asmlinkage int
do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
asmlinkage void
do_signal(struct pt_regs *regs, long in_syscall)
{
siginfo_t info;
struct k_sigaction ka;
int signr;
sigset_t *oldset;
DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
oldset, regs, regs->sr[7], in_syscall);
@ -543,7 +499,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
we would be called in that case, but for some reason we
are. */
if (!oldset)
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
DBG(1,"do_signal: oldset %08lx / %08lx\n",
@ -592,7 +550,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) {
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
regs->gr[28]);
return 1;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
return;
}
}
/* end of while(1) looping forever if we can't force a signal */
@ -653,5 +613,17 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
regs->gr[28]);
return 0;
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return;
}
void do_notify_resume(struct pt_regs *regs, long in_syscall)
{
if (test_thread_flag(TIF_SIGPENDING) ||
test_thread_flag(TIF_RESTORE_SIGMASK))
do_signal(regs, in_syscall);
}

View File

@ -283,7 +283,7 @@
* struct from a 32-bit user-space app.
*/
ENTRY_SAME(rt_sigqueueinfo)
ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
ENTRY_COMP(rt_sigsuspend)
ENTRY_SAME(chown) /* 180 */
/* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
ENTRY_COMP(setsockopt)
@ -377,8 +377,8 @@
ENTRY_SAME(inotify_init)
ENTRY_SAME(inotify_add_watch) /* 270 */
ENTRY_SAME(inotify_rm_watch)
ENTRY_SAME(ni_syscall) /* 271 ENTRY_COMP(pselect6) */
ENTRY_SAME(ni_syscall) /* 272 ENTRY_COMP(ppoll) */
ENTRY_COMP(pselect6)
ENTRY_COMP(ppoll)
ENTRY_SAME(migrate_pages)
ENTRY_COMP(openat) /* 275 */
ENTRY_SAME(mkdirat)

View File

@ -62,6 +62,7 @@ struct thread_info {
#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_32BIT 5 /* 32 bit binary */
#define TIF_MEMDIE 6
#define TIF_RESTORE_SIGMASK 7 /* restore saved signal mask */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
@ -69,9 +70,10 @@ struct thread_info {
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_32BIT (1 << TIF_32BIT)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
_TIF_NEED_RESCHED)
_TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
#endif /* __KERNEL__ */

View File

@ -955,6 +955,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
#endif /* __ASSEMBLY__ */