Martin Pelikan <martin.peli...@gmail.com> writes:

> Hi!
>
> Recently, I had to unleash my crappy Atom and decided to run OpenBSD on it.
> Then I became irritated with the performance of most X11 applications, and
> started poking around:
>  - libfreetype.so is quite common
>  - it does setjmp (disguised as ft_setjmp) quite a lot
>  - setjmp needs to do sigprocmask
>  - sigprocmask (I presume) needs the kernel lock.

If you're right that atomic_{clear,set}bits_int is correct and
sufficient and actually faster, then all dynamic executables would
benefit from this speedup (sigprocmask is used in ld.so(1)).

> sigprocmask(2) is quite simple actually, but wasn't marked as NOLOCK,
> so I made it so.  And then I made a pointless test to demonstrate my point,
> and ran it on my pointless Atom N270 (two threads, one core from 1980s)
> as well as in VMware, which is the only 4-core amd64 machine I can get
> on right now.  (did I say anything about using virtual machines to measure
> things?)
>
> #include <setjmp.h>
>
> int
> main(void)
> {
>         jmp_buf env;
>         unsigned i;
>
>       /* on amd64 this was too slow, so 20M was used instead */
>         for (i = 0; i < 4000000; ++i) {
>                 setjmp(env);
>         }
>         return (0);
> }
>
> Before:
> Atom, i386, single process,   0m3.80s real     0m1.15s user     0m2.50s system
> Atom, i386, two processes,    0m4.81s real     0m1.44s user     0m3.09s system
>
> amd64, single process, i<20M, 0m3.35s real     0m0.65s user     0m2.23s system
> amd64, two processes, i<20M,  0m4.48s real     0m0.66s user     0m3.37s system
>
> After:
> Atom, i386, single process,   0m2.93s real     0m0.95s user     0m1.35s system
> Atom, i386, two processes,    0m3.67s real     0m1.36s user     0m2.15s system
>
> amd64, single process, i<20M, 0m2.14s real     0m0.63s user     0m1.12s system
> amd64, two processes, i<20M,  0m2.57s real     0m0.57s user     0m1.55s system
>
>
> If anyone has a real test with some real-world application using lots
> of setjmps, I'd like to see it.  What'd I like to see most, is if does
> it work on other architectures and if it is indeed correct.  Although
> the numbers suggest quite an improvement, bear in mind this kind of
> load does not at all resemble any software actually doing useful stuff.
>
> Any comments?
> --
> Martin Pelikan
>
>
> Index: kern/init_sysent.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/init_sysent.c,v
> retrieving revision 1.145
> diff -u -p -r1.145 init_sysent.c
> --- kern/init_sysent.c        9 Jun 2013 13:10:27 -0000       1.145
> +++ kern/init_sysent.c        19 Jun 2013 09:49:57 -0000
> @@ -136,7 +136,7 @@ struct sysent sysent[] = {
>           sys_sigaction },                    /* 46 = sigaction */
>       { 0, 0, 0,
>           sys_getgid },                       /* 47 = getgid */
> -     { 2, s(struct sys_sigprocmask_args), 0,
> +     { 2, s(struct sys_sigprocmask_args), SY_NOLOCK | 0,
>           sys_sigprocmask },                  /* 48 = sigprocmask */
>       { 2, s(struct sys_getlogin_args), 0,
>           sys_getlogin },                     /* 49 = getlogin */
> Index: kern/kern_sig.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_sig.c,v
> retrieving revision 1.152
> diff -u -p -r1.152 kern_sig.c
> --- kern/kern_sig.c   1 Jun 2013 04:05:26 -0000       1.152
> +++ kern/kern_sig.c   19 Jun 2013 09:49:57 -0000
> @@ -429,28 +429,25 @@ sys_sigprocmask(struct proc *p, void *v,
>               syscallarg(sigset_t) mask;
>       } */ *uap = v;
>       int error = 0;
> -     int s;
>       sigset_t mask;
>  
>       *retval = p->p_sigmask;
> -     mask = SCARG(uap, mask);
> -     s = splhigh();
> +     mask = SCARG(uap, mask) &~ sigcantmask;
>  
>       switch (SCARG(uap, how)) {
>       case SIG_BLOCK:
> -             p->p_sigmask |= mask &~ sigcantmask;
> +             atomic_setbits_int(&p->p_sigmask, mask);
>               break;
>       case SIG_UNBLOCK:
> -             p->p_sigmask &= ~mask;
> +             atomic_clearbits_int(&p->p_sigmask, mask);
>               break;
>       case SIG_SETMASK:
> -             p->p_sigmask = mask &~ sigcantmask;
> +             p->p_sigmask = mask;
>               break;
>       default:
>               error = EINVAL;
>               break;
>       }
> -     splx(s);
>       return (error);
>  }
>  
> Index: kern/syscalls.master
> ===================================================================
> RCS file: /cvs/src/sys/kern/syscalls.master,v
> retrieving revision 1.133
> diff -u -p -r1.133 syscalls.master
> --- kern/syscalls.master      9 Jun 2013 13:10:19 -0000       1.133
> +++ kern/syscalls.master      19 Jun 2013 09:49:57 -0000
> @@ -123,7 +123,7 @@
>                           const struct sigaction *nsa, \
>                           struct sigaction *osa); }
>  47   STD             { gid_t sys_getgid(void); }
> -48   STD             { int sys_sigprocmask(int how, sigset_t mask); }
> +48   STD NOLOCK      { int sys_sigprocmask(int how, sigset_t mask); }
>  49   STD             { int sys_getlogin(char *namebuf, u_int namelen); }
>  50   STD             { int sys_setlogin(const char *namebuf); }
>  #ifdef ACCOUNTING
>

-- 
Jérémie Courrèges-Anglas
PGP Key fingerprint: 61DB D9A0 00A4 67CF 2A90  8961 6191 8FBF 06A1 1494

Reply via email to