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.

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

Reply via email to