svn commit: r274242 - in user/dchagin/lemul/sys: kern sys

Dmitry Chagin dchagin at FreeBSD.org
Fri Nov 7 16:25:09 UTC 2014


Author: dchagin
Date: Fri Nov  7 16:25:07 2014
New Revision: 274242
URL: https://svnweb.freebsd.org/changeset/base/274242

Log:
  Split up sys_poll() into a sys_ and kern_ counterparts, add kern_ppoll()
  version needed by an upcoming Linuxulator change.

Modified:
  user/dchagin/lemul/sys/kern/sys_generic.c
  user/dchagin/lemul/sys/sys/syscallsubr.h

Modified: user/dchagin/lemul/sys/kern/sys_generic.c
==============================================================================
--- user/dchagin/lemul/sys/kern/sys_generic.c	Fri Nov  7 16:22:58 2014	(r274241)
+++ user/dchagin/lemul/sys/kern/sys_generic.c	Fri Nov  7 16:25:07 2014	(r274242)
@@ -97,6 +97,8 @@ static int	pollout(struct thread *, stru
 		    u_int);
 static int	pollscan(struct thread *, struct pollfd *, u_int);
 static int	pollrescan(struct thread *);
+static int	kern_poll(struct thread *, struct pollfd *, uint32_t,
+		    sbintime_t, sbintime_t);
 static int	selscan(struct thread *, fd_mask **, fd_mask **, int);
 static int	selrescan(struct thread *, fd_mask **, fd_mask **);
 static void	selfdalloc(struct thread *, void *);
@@ -1301,30 +1303,12 @@ sys_poll(td, uap)
 	struct thread *td;
 	struct poll_args *uap;
 {
-	struct pollfd *bits;
-	struct pollfd smallbits[32];
 	sbintime_t asbt, precision, rsbt;
-	u_int nfds;
-	int error;
-	size_t ni;
 
-	nfds = uap->nfds;
-	if (nfds > maxfilesperproc && nfds > FD_SETSIZE) 
-		return (EINVAL);
-	ni = nfds * sizeof(struct pollfd);
-	if (ni > sizeof(smallbits))
-		bits = malloc(ni, M_TEMP, M_WAITOK);
-	else
-		bits = smallbits;
-	error = copyin(uap->fds, bits, ni);
-	if (error)
-		goto done;
 	precision = 0;
 	if (uap->timeout != INFTIM) {
-		if (uap->timeout < 0) {
-			error = EINVAL;
-			goto done;
-		}
+		if (uap->timeout < 0)
+			return (EINVAL);
 		if (uap->timeout == 0)
 			asbt = 0;
 		else {
@@ -1337,13 +1321,37 @@ sys_poll(td, uap)
 		}
 	} else
 		asbt = -1;
+
+	return (kern_poll(td, uap->fds, uap->nfds, asbt, precision));
+}
+
+static int
+kern_poll(struct thread *td, struct pollfd *fds, uint32_t nfds,
+    sbintime_t sbt, sbintime_t prec)
+{
+	struct pollfd *bits;
+	struct pollfd smallbits[32];
+	int error;
+	size_t ni;
+
+	if (nfds > maxfilesperproc && nfds > FD_SETSIZE) 
+		return (EINVAL);
+	ni = nfds * sizeof(struct pollfd);
+	if (ni > sizeof(smallbits))
+		bits = malloc(ni, M_TEMP, M_WAITOK);
+	else
+		bits = smallbits;
+	error = copyin(fds, bits, ni);
+	if (error)
+		goto done;
+
 	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, prec);
 		if (error)
 			break;
 		error = pollrescan(td);
@@ -1359,7 +1367,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 +1377,59 @@ out:
 	return (error);
 }
 
+int
+kern_ppoll(struct thread *td, struct pollfd *fds, uint32_t nfds,
+    struct timespec *tsp, sigset_t *uset)
+{
+	struct timespec ts;
+	sbintime_t sbt, precision, tmp;
+	time_t over;
+	int error;
+
+	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 (uset != NULL) {
+		error = kern_sigprocmask(td, SIG_SETMASK, uset,
+		    &td->td_oldsigmask, 0);
+		if (error != 0)
+			return (error);
+		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);
+	}
+
+	return (kern_poll(td, fds, nfds, sbt, precision));
+}
+
 static int
 pollrescan(struct thread *td)
 {

Modified: user/dchagin/lemul/sys/sys/syscallsubr.h
==============================================================================
--- user/dchagin/lemul/sys/sys/syscallsubr.h	Fri Nov  7 16:22:58 2014	(r274241)
+++ user/dchagin/lemul/sys/sys/syscallsubr.h	Fri Nov  7 16:25:07 2014	(r274242)
@@ -46,6 +46,7 @@ struct ksiginfo;
 struct mbuf;
 struct msghdr;
 struct msqid_ds;
+struct pollfd;
 struct ogetdirentries_args;
 struct rlimit;
 struct rusage;
@@ -169,6 +170,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_ppoll(struct thread *td, struct pollfd *fds, uint32_t 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-user mailing list