On Tue, Feb 07, 2023 at 05:42:40PM +0300, Vitaliy Makkoveev wrote:
> 
> > > Otherwise, if you are concerning about serialized `p_sigmask' and
> > > P_SIGSUSPEND, dosigsuspend() should be left under kernel lock:
> > > 
> > >   if (sigmask) {
> > >           KERNEL_LOCK();
> > >           dosigsuspend(p, *sigmask &~ sigcantmask);
> > >           KERNEL_UNLOCK();
> > >   }
> > 
> > This is a hack but would allow progress. Now I would prefer if
> > dosigsuspend() is made safe so that the KERNEL_LOCK is not needed. Which
> > would also allow sigsuspend to be called with NOLOCK.
> > 
> 
> Makes sense, but sigsuspend(2) will not be unlocked together with
> select(2), so dosigsuspend() could be left under kernel lock for a
> while.
> 

Now, I want to keep dosigsuspend() under the kernel lock. To me it's
better to unlock it together with sigsuspend(2) to separate possible
signal related fallout. This still makes sense because signal mask is
the optional arg for pselect(2) only. Except the local event data
conversion, poll(2) internals are the same as select(2) internals, it
makes sense to unlock them both.

This doesn't mean I dropped dosigsuspend(), I'm still waiting feedback
for barriers.

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      8 Feb 2023 10:56:08 -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;
@@ -643,8 +644,11 @@ dopselect(struct proc *p, int nd, fd_set
        }
 #endif
 
-       if (sigmask)
+       if (sigmask) {
+               KERNEL_LOCK();
                dosigsuspend(p, *sigmask &~ sigcantmask);
+               KERNEL_UNLOCK();
+       }
 
        /* Register kqueue events */
        error = pselregister(p, pibits, pobits, nd, &nevents, &ncollected);
@@ -948,8 +952,11 @@ doppoll(struct proc *p, struct pollfd *f
        if ((error = copyin(fds, pl, sz)) != 0)
                goto bad;
 
-       if (sigmask)
+       if (sigmask) {
+               KERNEL_LOCK();
                dosigsuspend(p, *sigmask &~ sigcantmask);
+               KERNEL_UNLOCK();
+       }
 
        /* Register kqueue events */
        ppollregister(p, pl, nfds, &nevents, &ncollected);
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    8 Feb 2023 10:56:10 -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, \
@@ -230,10 +230,10 @@
                            u_int flags, int atflags); }
 108    STD NOLOCK      { int sys_pledge(const char *promises, \
                            const char *execpromises); }
-109    STD             { int sys_ppoll(struct pollfd *fds, \
+109    STD NOLOCK      { 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); }
@@ -448,7 +448,7 @@
 250    STD NOLOCK      { int sys_minherit(void *addr, size_t len, \
                            int inherit); }
 251    OBSOL           rfork
-252    STD             { int sys_poll(struct pollfd *fds, \
+252    STD NOLOCK      { int sys_poll(struct pollfd *fds, \
                            u_int nfds, int timeout); }
 253    STD NOLOCK      { int sys_issetugid(void); }
 254    STD             { int sys_lchown(const char *path, uid_t uid, gid_t 
gid); }

Reply via email to