[parisc-linux] [RFC] pselect/ppoll support

Carlos O'Donell carlos at systemhalted.org
Sun Apr 9 20:06:03 MDT 2006


On 4/9/06, Kyle McMartin <kyle at mcmartin.ca> wrote:
> First strike at adding TIF_RESTORE_SIGMASK support for the pselect/ppoll
> system calls... Doesn't seem to work at all yet...

Thanks!

> -       .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
> -       b,l     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
> -

This needs more review.

> -asmlinkage int
> -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)

You've switched over to the kernel generic version of
sys_rt_sigsuspend, and you will have to review if it does exactly what
our version was doing. I suspect it's slightly different, and you
problems start here.

> +/* Setup a trampoline to restart the syscall
> + * with __NR_restart_syscall
> + *
> + *  0: <return address (orig r31)>
> + *  4: <2nd half for 64-bit>
> + *  8: ldw 0(%sp), %r31
> + * 12: be 0x100(%sr2, %r0)
> + * 16: ldi __NR_restart_syscall, %r20
> + */
> +static void setup_restart_syscall_tramp(struct pt_regs *regs)
> +{
> +       unsigned int *usp = (unsigned int *)regs->gr[30];
> +
> +#ifdef CONFIG_64BIT
> +       put_user(regs->gr[31] >> 32, &usp[0]);
> +       put_user(regs->gr[31] & 0xffffffff, &usp[1]);
> +       put_user(0x0fc010df, &usp[2]);
> +#else
> +       put_user(regs->gr[31], &usp[0]);
> +       put_user(0x0fc0109f, &usp[2]);
> +#endif
> +       put_user(0xe0008200, &usp[3]);
> +       put_user(0x34140000, &usp[4]);
> +
> +       /* Stack is 64-byte aligned, and we only need
> +        * to flush 1 cache line.
> +        * Flushing one cacheline is cheap.
> +        * "sync" on bigger (> 4 way) boxes is not.
> +        */
> +       asm("fdc %%r0(%%sr3, %0)\n"
> +           "sync\n"
> +           "fic %%r0(%%sr3, %0)\n"
> +           "sync\n"
> +           : : "r"(regs->gr[30]));
> +
> +       regs->gr[31] = regs->gr[30] + 8;
> +       /* Preserve original r28. */
> +       regs->gr[28] = regs->orig_r28;
> +
> +       return;
>  }

I believe we've always had a race condition in this trampoline.
I'm raising this issue so we can remember that it's there or
completely squash the issue. While returning to userspace
you *cannot* take another restart since the restarts are not
nestable. You must disable restarts and then reenable them
when you return from the trampoline. Linus wrote an email about
this issue. Has this been fixed for us?

> -       /* Everyone else checks to see if they are in kernel mode at
> -          this point and exits if that's the case.  I'm not sure why
> -          we would be called in that case, but for some reason we
> -          are. */
> +       if (!user_mode(regs))
> +               return;

Don't delete the comment unless you are willing to replace it with
one that explains why this might be the case. Please think about
kernel mode threads and why we don't do this for them.

>         /* May need to force signal if handle_signal failed to deliver */
> -       while (1) {
> -
> -               signr = get_signal_to_deliver(&info, &ka, regs, NULL);
> -               DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
> +       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
> +       DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);

Have other arches changed their handlers?
Are we no longer required to loop in an attempt to deliver the signal?

> -       ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
> +       ENTRY_COMP(rt_sigsuspend)

This was always really ugly. Thanks.


> -       ENTRY_SAME(ni_syscall)          /* 271 ENTRY_COMP(pselect6) */
> -       ENTRY_SAME(ni_syscall)          /* 272 ENTRY_COMP(ppoll) */
> +       ENTRY_COMP(pselect6)
> +       ENTRY_COMP(ppoll)

Yay.

Cheers,
Carlos.



More information about the parisc-linux mailing list