svn commit: r274462 - in head: lib/libc/sys sys/compat/freebsd32 sys/kern sys/sys

Dmitry Chagin dchagin at FreeBSD.org
Thu Nov 13 05:26:17 UTC 2014


Author: dchagin
Date: Thu Nov 13 05:26:14 2014
New Revision: 274462
URL: https://svnweb.freebsd.org/changeset/base/274462

Log:
  Add the ppoll() system call.
  Export kern_poll() needed by an upcoming Linuxulator change.
  
  Differential Revision:	https://reviews.freebsd.org/D1133
  Reviewed by:	kib, wblock
  MFC after:	1 month

Modified:
  head/lib/libc/sys/Makefile.inc
  head/lib/libc/sys/Symbol.map
  head/lib/libc/sys/poll.2
  head/sys/compat/freebsd32/freebsd32_misc.c
  head/sys/compat/freebsd32/syscalls.master
  head/sys/kern/sys_generic.c
  head/sys/kern/syscalls.master
  head/sys/sys/poll.h
  head/sys/sys/syscallsubr.h

Modified: head/lib/libc/sys/Makefile.inc
==============================================================================
--- head/lib/libc/sys/Makefile.inc	Thu Nov 13 03:59:36 2014	(r274461)
+++ head/lib/libc/sys/Makefile.inc	Thu Nov 13 05:26:14 2014	(r274462)
@@ -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: head/lib/libc/sys/Symbol.map
==============================================================================
--- head/lib/libc/sys/Symbol.map	Thu Nov 13 03:59:36 2014	(r274461)
+++ head/lib/libc/sys/Symbol.map	Thu Nov 13 05:26:14 2014	(r274462)
@@ -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: head/lib/libc/sys/poll.2
==============================================================================
--- head/lib/libc/sys/poll.2	Thu Nov 13 03:59:36 2014	(r274461)
+++ head/lib/libc/sys/poll.2	Thu Nov 13 05:26:14 2014	(r274462)
@@ -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: head/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_misc.c	Thu Nov 13 03:59:36 2014	(r274461)
+++ head/sys/compat/freebsd32/freebsd32_misc.c	Thu Nov 13 05:26:14 2014	(r274462)
@@ -2991,3 +2991,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: head/sys/compat/freebsd32/syscalls.master
==============================================================================
--- head/sys/compat/freebsd32/syscalls.master	Thu Nov 13 03:59:36 2014	(r274461)
+++ head/sys/compat/freebsd32/syscalls.master	Thu Nov 13 05:26:14 2014	(r274462)
@@ -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: head/sys/kern/sys_generic.c
==============================================================================
--- head/sys/kern/sys_generic.c	Thu Nov 13 03:59:36 2014	(r274461)
+++ head/sys/kern/sys_generic.c	Thu Nov 13 05:26:14 2014	(r274462)
@@ -1289,26 +1289,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);
@@ -1316,34 +1350,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);
@@ -1359,7 +1392,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;
 	}
@@ -1369,6 +1402,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: head/sys/kern/syscalls.master
==============================================================================
--- head/sys/kern/syscalls.master	Thu Nov 13 03:59:36 2014	(r274461)
+++ head/sys/kern/syscalls.master	Thu Nov 13 05:26:14 2014	(r274462)
@@ -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: head/sys/sys/poll.h
==============================================================================
--- head/sys/sys/poll.h	Thu Nov 13 03:59:36 2014	(r274461)
+++ head/sys/sys/poll.h	Thu Nov 13 05:26:14 2014	(r274462)
@@ -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: head/sys/sys/syscallsubr.h
==============================================================================
--- head/sys/sys/syscallsubr.h	Thu Nov 13 03:59:36 2014	(r274461)
+++ head/sys/sys/syscallsubr.h	Thu Nov 13 05:26:14 2014	(r274462)
@@ -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,


More information about the svn-src-all mailing list