Hi,

kevent(2) system call is ulocked more than year ago. Since select(2)
and pselect(2) are kqueue(2)/kevent(2) wrappers, it makes sense to
unlock them too. select(2) does the temporary kernel event queue
initialization for this call only and does queue scan with events
conversion between kevent(2) and select(2) data formats.

pselect(2) is the same, but it also sets provided signal mask. sigset_t
is unsigned int and only current thread does `p_sigmask' and `p_oldmask'
modification, so dosigsuspend() call outside kernel lock is safe.
claudio@, is this true? If so, I want to mark `p_sigmask' and
`p_oldmask' as atomic in proc structure description.

In dopselect() I used local `nfiles' variable to store
p->p_fd->fd_nfiles value for `nd' normalisation.

I'm the select(2) user and this unlocking makes sense for me, because
the performance of select based programs increased by ~10-15%.

Index: sys/kern/sys_generic.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_generic.c,v
retrieving revision 1.151
diff -u -p -r1.151 sys_generic.c
--- sys/kern/sys_generic.c      27 Dec 2022 20:13:03 -0000      1.151
+++ sys/kern/sys_generic.c      3 Feb 2023 21:37:37 -0000
@@ -596,15 +596,16 @@ dopselect(struct proc *p, int nd, fd_set
        struct timespec zerots = {};
        fd_mask bits[6];
        fd_set *pibits[3], *pobits[3];
-       int error, ncollected = 0, nevents = 0;
+       int error, nfiles, ncollected = 0, nevents = 0;
        u_int ni;
 
        if (nd < 0)
                return (EINVAL);
-       if (nd > p->p_fd->fd_nfiles) {
-               /* forgiving; slightly wrong */
-               nd = p->p_fd->fd_nfiles;
-       }
+
+       nfiles = READ_ONCE(p->p_fd->fd_nfiles);
+       if (nd > nfiles)
+               nd = nfiles;
+
        ni = howmany(nd, NFDBITS) * sizeof(fd_mask);
        if (ni > sizeof(bits[0])) {
                caddr_t mbits;
Index: sys/kern/syscalls.master
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.239
diff -u -p -r1.239 syscalls.master
--- sys/kern/syscalls.master    7 Jan 2023 05:24:58 -0000       1.239
+++ sys/kern/syscalls.master    3 Feb 2023 21:37:37 -0000
@@ -165,7 +165,7 @@
                            struct itimerval *oitv); }
 70     STD NOLOCK      { int sys_getitimer(int which, \
                            struct itimerval *itv); }
-71     STD             { int sys_select(int nd, fd_set *in, fd_set *ou, \
+71     STD NOLOCK      { int sys_select(int nd, fd_set *in, fd_set *ou, \
                            fd_set *ex, struct timeval *tv); }
 72     STD NOLOCK      { int sys_kevent(int fd, \
                            const struct kevent *changelist, int nchanges, \
@@ -233,7 +233,7 @@
 109    STD             { int sys_ppoll(struct pollfd *fds, \
                            u_int nfds, const struct timespec *ts, \
                            const sigset_t *mask); }
-110    STD             { int sys_pselect(int nd, fd_set *in, fd_set *ou, \
+110    STD NOLOCK      { int sys_pselect(int nd, fd_set *in, fd_set *ou, \
                            fd_set *ex, const struct timespec *ts, \
                            const sigset_t *mask); }
 111    STD             { int sys_sigsuspend(int mask); }

Reply via email to