Author: dchagin
Date: Sun Dec 21 07:58:28 2014
New Revision: 275986
URL: https://svnweb.freebsd.org/changeset/base/275986

Log:
  MFC r274462: Add the ppoll() system call.

Modified:
  stable/10/lib/libc/sys/Makefile.inc
  stable/10/lib/libc/sys/Symbol.map
  stable/10/lib/libc/sys/poll.2
  stable/10/sys/compat/freebsd32/freebsd32_misc.c
  stable/10/sys/compat/freebsd32/syscalls.master
  stable/10/sys/kern/sys_generic.c
  stable/10/sys/kern/syscalls.master
  stable/10/sys/sys/poll.h
  stable/10/sys/sys/syscallsubr.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/sys/Makefile.inc
==============================================================================
--- stable/10/lib/libc/sys/Makefile.inc Sun Dec 21 05:07:11 2014        
(r275985)
+++ stable/10/lib/libc/sys/Makefile.inc Sun Dec 21 07:58:28 2014        
(r275986)
@@ -356,6 +356,7 @@ MLINKS+=pdfork.2 pdgetpid.2\
        pdfork.2 pdkill.2 \
        pdfork.2 pdwait4.2
 MLINKS+=pipe.2 pipe2.2
+MLINKS+=poll.2 ppoll.2
 MLINKS+=read.2 pread.2 \
        read.2 preadv.2 \
        read.2 readv.2

Modified: stable/10/lib/libc/sys/Symbol.map
==============================================================================
--- stable/10/lib/libc/sys/Symbol.map   Sun Dec 21 05:07:11 2014        
(r275985)
+++ stable/10/lib/libc/sys/Symbol.map   Sun Dec 21 07:58:28 2014        
(r275986)
@@ -399,6 +399,10 @@ FBSD_1.3 {
        wait6;
 };
 
+FBSD_1.4 {
+       ppoll;
+};
+
 FBSDprivate_1.0 {
        ___acl_aclcheck_fd;
        __sys___acl_aclcheck_fd;
@@ -821,6 +825,8 @@ FBSDprivate_1.0 {
        __sys_pipe;
        _poll;
        __sys_poll;
+       _ppoll;
+       __sys_ppoll;
        _preadv;
        __sys_preadv;
        _procctl;

Modified: stable/10/lib/libc/sys/poll.2
==============================================================================
--- stable/10/lib/libc/sys/poll.2       Sun Dec 21 05:07:11 2014        
(r275985)
+++ stable/10/lib/libc/sys/poll.2       Sun Dec 21 07:58:28 2014        
(r275986)
@@ -28,7 +28,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd July 8, 2002
+.Dd November 13, 2014
 .Dt POLL 2
 .Os
 .Sh NAME
@@ -40,6 +40,13 @@
 .In poll.h
 .Ft int
 .Fn poll "struct pollfd fds[]" "nfds_t nfds" "int timeout"
+.Ft int
+.Fo ppoll
+.Fa "struct pollfd fds[]"
+.Fa "nfds_t nfds"
+.Fa "const struct timespec * restrict timeout"
+.Fa "const sigset_t * restrict newsigmask"
+.Fc
 .Sh DESCRIPTION
 The
 .Fn poll
@@ -139,6 +146,47 @@ If
 is zero, then
 .Fn poll
 will return without blocking.
+.Pp
+The
+.Fn ppoll 
+system call, unlike 
+.Fn poll ,
+is used to safely wait until either a set of file descriptors becomes
+ready or until a signal is caught.
+The
+.Fa fds
+and
+.Fa nfds
+arguments are identical to the analogous arguments of
+.Fn poll .
+The
+.Fa timeout
+argument in
+.Fn ppoll
+points to a
+.Vt "const struct timespec"
+which is defined in
+.In sys/timespec.h
+(shown below) rather than the
+.Vt "int timeout"
+used by
+.Fn poll .
+A null pointer may be passed to indicate that
+.Fn ppoll
+should wait indefinitely.
+Finally, 
+.Fa newsigmask
+specifies a signal mask which is set while waiting for input.
+When 
+.Fn ppoll
+returns, the original signal mask is restored.
+.Pp
+.Bd -literal
+struct timespec {
+       time_t  tv_sec;         /* seconds */
+       long    tv_nsec;        /* and nanoseconds */
+};
+.Ed
 .Sh RETURN VALUES
 The
 .Fn poll
@@ -185,17 +233,26 @@ points outside the process's allocated a
 A signal was delivered before the time limit expired and
 before any of the selected events occurred.
 .It Bq Er EINVAL
-The specified time limit is negative.
+The specified time limit is invalid. One of its components is negative or too 
large.
 .El
 .Sh SEE ALSO
 .Xr accept 2 ,
 .Xr connect 2 ,
 .Xr kqueue 2 ,
+.Xr pselect 2 ,
 .Xr read 2 ,
 .Xr recv 2 ,
 .Xr select 2 ,
 .Xr send 2 ,
 .Xr write 2
+.Sh STANDARDS
+The
+.Fn poll 
+function conforms to
+.St -p1003.1-2001 .
+The
+.Fn ppoll 
+is not specified by POSIX.
 .Sh HISTORY
 The
 .Fn poll
@@ -203,6 +260,10 @@ function appeared in
 .At V .
 This manual page and the core of the implementation was taken from
 .Nx .
+The
+.Fn ppoll
+function first appeared in 
+.Fx 11.0 
 .Sh BUGS
 The distinction between some of the fields in the
 .Fa events

Modified: stable/10/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- stable/10/sys/compat/freebsd32/freebsd32_misc.c     Sun Dec 21 05:07:11 
2014        (r275985)
+++ stable/10/sys/compat/freebsd32/freebsd32_misc.c     Sun Dec 21 07:58:28 
2014        (r275986)
@@ -3102,3 +3102,31 @@ freebsd32_fcntl(struct thread *td, struc
        }
        return (kern_fcntl_freebsd(td, uap->fd, uap->cmd, tmp));
 }
+
+int
+freebsd32_ppoll(struct thread *td, struct freebsd32_ppoll_args *uap)
+{
+       struct timespec32 ts32;
+       struct timespec ts, *tsp;
+       sigset_t set, *ssp;
+       int error;
+
+       if (uap->ts != NULL) {
+               error = copyin(uap->ts, &ts32, sizeof(ts32));
+               if (error != 0)
+                       return (error);
+               CP(ts32, ts, tv_sec);
+               CP(ts32, ts, tv_nsec);
+               tsp = &ts;
+       } else
+               tsp = NULL;
+       if (uap->set != NULL) {
+               error = copyin(uap->set, &set, sizeof(set));
+               if (error != 0)
+                       return (error);
+               ssp = &set;
+       } else
+               ssp = NULL;
+
+       return (kern_poll(td, uap->fds, uap->nfds, tsp, ssp));
+}

Modified: stable/10/sys/compat/freebsd32/syscalls.master
==============================================================================
--- stable/10/sys/compat/freebsd32/syscalls.master      Sun Dec 21 05:07:11 
2014        (r275985)
+++ stable/10/sys/compat/freebsd32/syscalls.master      Sun Dec 21 07:58:28 
2014        (r275986)
@@ -1066,3 +1066,6 @@
                                    uint32_t id1, uint32_t id2, int com, \
                                    void *data); }
 #endif
+545    AUE_POLL        STD     { int freebsd32_ppoll(struct pollfd *fds, \
+                                   u_int nfds, const struct timespec32 *ts, \
+                                   const sigset_t *set); }

Modified: stable/10/sys/kern/sys_generic.c
==============================================================================
--- stable/10/sys/kern/sys_generic.c    Sun Dec 21 05:07:11 2014        
(r275985)
+++ stable/10/sys/kern/sys_generic.c    Sun Dec 21 07:58:28 2014        
(r275986)
@@ -1300,26 +1300,60 @@ selscan(td, ibits, obits, nfd)
        return (0);
 }
 
-#ifndef _SYS_SYSPROTO_H_
-struct poll_args {
-       struct pollfd *fds;
-       u_int   nfds;
-       int     timeout;
-};
-#endif
 int
-sys_poll(td, uap)
-       struct thread *td;
-       struct poll_args *uap;
+sys_poll(struct thread *td, struct poll_args *uap)
+{
+       struct timespec ts, *tsp;
+
+       if (uap->timeout != INFTIM) {
+               if (uap->timeout < 0)
+                       return (EINVAL);
+               ts.tv_sec = uap->timeout / 1000;
+               ts.tv_nsec = (uap->timeout % 1000) * 1000000;
+               tsp = &ts;
+       } else
+               tsp = NULL;
+
+       return (kern_poll(td, uap->fds, uap->nfds, tsp, NULL));
+}
+
+int
+kern_poll(struct thread *td, struct pollfd *fds, u_int nfds,
+    struct timespec *tsp, sigset_t *uset)
 {
        struct pollfd *bits;
        struct pollfd smallbits[32];
-       sbintime_t asbt, precision, rsbt;
-       u_int nfds;
+       sbintime_t sbt, precision, tmp;
+       time_t over;
+       struct timespec ts;
        int error;
        size_t ni;
 
-       nfds = uap->nfds;
+       precision = 0;
+       if (tsp != NULL) {
+               if (tsp->tv_sec < 0)
+                       return (EINVAL);
+               if (tsp->tv_nsec < 0 || tsp->tv_nsec >= 1000000000)
+                       return (EINVAL);
+               if (tsp->tv_sec == 0 && tsp->tv_nsec == 0)
+                       sbt = 0;
+               else {
+                       ts = *tsp;
+                       if (ts.tv_sec > INT32_MAX / 2) {
+                               over = ts.tv_sec - INT32_MAX / 2;
+                               ts.tv_sec -= over;
+                       } else
+                               over = 0;
+                       tmp = tstosbt(ts);
+                       precision = tmp;
+                       precision >>= tc_precexp;
+                       if (TIMESEL(&sbt, tmp))
+                               sbt += tc_tick_sbt;
+                       sbt += tmp;
+               }
+       } else
+               sbt = -1;
+
        if (nfds > maxfilesperproc && nfds > FD_SETSIZE) 
                return (EINVAL);
        ni = nfds * sizeof(struct pollfd);
@@ -1327,34 +1361,33 @@ sys_poll(td, uap)
                bits = malloc(ni, M_TEMP, M_WAITOK);
        else
                bits = smallbits;
-       error = copyin(uap->fds, bits, ni);
+       error = copyin(fds, bits, ni);
        if (error)
                goto done;
-       precision = 0;
-       if (uap->timeout != INFTIM) {
-               if (uap->timeout < 0) {
-                       error = EINVAL;
+
+       if (uset != NULL) {
+               error = kern_sigprocmask(td, SIG_SETMASK, uset,
+                   &td->td_oldsigmask, 0);
+               if (error)
                        goto done;
-               }
-               if (uap->timeout == 0)
-                       asbt = 0;
-               else {
-                       rsbt = SBT_1MS * uap->timeout;
-                       precision = rsbt;
-                       precision >>= tc_precexp;
-                       if (TIMESEL(&asbt, rsbt))
-                               asbt += tc_tick_sbt;
-                       asbt += rsbt;
-               }
-       } else
-               asbt = -1;
+               td->td_pflags |= TDP_OLDMASK;
+               /*
+                * Make sure that ast() is called on return to
+                * usermode and TDP_OLDMASK is cleared, restoring old
+                * sigmask.
+                */
+               thread_lock(td);
+               td->td_flags |= TDF_ASTPENDING;
+               thread_unlock(td);
+       }
+
        seltdinit(td);
        /* Iterate until the timeout expires or descriptors become ready. */
        for (;;) {
                error = pollscan(td, bits, nfds);
                if (error || td->td_retval[0] != 0)
                        break;
-               error = seltdwait(td, asbt, precision);
+               error = seltdwait(td, sbt, precision);
                if (error)
                        break;
                error = pollrescan(td);
@@ -1370,7 +1403,7 @@ done:
        if (error == EWOULDBLOCK)
                error = 0;
        if (error == 0) {
-               error = pollout(td, bits, uap->fds, nfds);
+               error = pollout(td, bits, fds, nfds);
                if (error)
                        goto out;
        }
@@ -1380,6 +1413,35 @@ out:
        return (error);
 }
 
+int
+sys_ppoll(struct thread *td, struct ppoll_args *uap)
+{
+       struct timespec ts, *tsp;
+       sigset_t set, *ssp;
+       int error;
+
+       if (uap->ts != NULL) {
+               error = copyin(uap->ts, &ts, sizeof(ts));
+               if (error)
+                       return (error);
+               tsp = &ts;
+       } else
+               tsp = NULL;
+       if (uap->set != NULL) {
+               error = copyin(uap->set, &set, sizeof(set));
+               if (error)
+                       return (error);
+               ssp = &set;
+       } else
+               ssp = NULL;
+       /*
+        * fds is still a pointer to user space. kern_poll() will
+        * take care of copyin that array to the kernel space.
+        */
+
+       return (kern_poll(td, uap->fds, uap->nfds, tsp, ssp));
+}
+
 static int
 pollrescan(struct thread *td)
 {

Modified: stable/10/sys/kern/syscalls.master
==============================================================================
--- stable/10/sys/kern/syscalls.master  Sun Dec 21 05:07:11 2014        
(r275985)
+++ stable/10/sys/kern/syscalls.master  Sun Dec 21 07:58:28 2014        
(r275986)
@@ -980,5 +980,8 @@
 543    AUE_NULL        NOSTD   { int aio_mlock(struct aiocb *aiocbp); }
 544    AUE_NULL        STD     { int procctl(idtype_t idtype, id_t id, \
                                    int com, void *data); }
+545    AUE_POLL        STD     { int ppoll(struct pollfd *fds, u_int nfds, \
+                                   const struct timespec *ts, \
+                                   const sigset_t *set); }
 ; Please copy any additions and changes to the following compatability tables:
 ; sys/compat/freebsd32/syscalls.master

Modified: stable/10/sys/sys/poll.h
==============================================================================
--- stable/10/sys/sys/poll.h    Sun Dec 21 05:07:11 2014        (r275985)
+++ stable/10/sys/sys/poll.h    Sun Dec 21 07:58:28 2014        (r275986)
@@ -95,8 +95,26 @@ struct pollfd {
 
 #ifndef _KERNEL
 
+#if __BSD_VISIBLE
+#include <sys/_types.h>
+
+#include <sys/_sigset.h>
+#include <sys/timespec.h>
+
+#ifndef _SIGSET_T_DECLARED
+#define        _SIGSET_T_DECLARED
+typedef        __sigset_t      sigset_t;
+#endif
+
+#endif
+
 __BEGIN_DECLS
 int    poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout);
+#if __BSD_VISIBLE
+int    ppoll(struct pollfd _pfd[], nfds_t _nfds,
+           const struct timespec *__restrict _timeout,
+           const sigset_t *__restrict _newsigmask);
+#endif
 __END_DECLS
 
 #endif /* !_KERNEL */

Modified: stable/10/sys/sys/syscallsubr.h
==============================================================================
--- stable/10/sys/sys/syscallsubr.h     Sun Dec 21 05:07:11 2014        
(r275985)
+++ stable/10/sys/sys/syscallsubr.h     Sun Dec 21 07:58:28 2014        
(r275986)
@@ -46,6 +46,7 @@ struct ksiginfo;
 struct mbuf;
 struct msghdr;
 struct msqid_ds;
+struct pollfd;
 struct ogetdirentries_args;
 struct rlimit;
 struct rusage;
@@ -164,6 +165,8 @@ int kern_pathconf(struct thread *td, cha
            int name, u_long flags);
 int    kern_pipe(struct thread *td, int fildes[2]);
 int    kern_pipe2(struct thread *td, int fildes[2], int flags);
+int    kern_poll(struct thread *td, struct pollfd *fds, u_int nfds,
+           struct timespec *tsp, sigset_t *uset);
 int    kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len,
            int advice);
 int    kern_posix_fallocate(struct thread *td, int fd, off_t offset,
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to