Module Name:    src
Committed By:   pooka
Date:           Tue Mar  8 15:34:38 UTC 2011

Modified Files:
        src/lib/librumpclient: rumpclient.c
        src/lib/librumpuser: rumpuser_sp.c sp_common.c

Log Message:
Use sendmsg() instead multiple calls to sendto().  It behaves
slightly better in the multithreaded exec case in terms of partial
frames sent.  Plus, it's theoretically a little cheaper.

There's still a gray area with partial transfer from sendmsg(),
but I'm not sure I care enough about some academic scenario to
start fixing it (it basically needs an OOB exec signaller).


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.39 src/lib/librumpclient/rumpclient.c
cvs rdiff -u -r1.44 -r1.45 src/lib/librumpuser/rumpuser_sp.c
cvs rdiff -u -r1.30 -r1.31 src/lib/librumpuser/sp_common.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/librumpclient/rumpclient.c
diff -u src/lib/librumpclient/rumpclient.c:1.38 src/lib/librumpclient/rumpclient.c:1.39
--- src/lib/librumpclient/rumpclient.c:1.38	Sun Feb 27 12:58:29 2011
+++ src/lib/librumpclient/rumpclient.c	Tue Mar  8 15:34:37 2011
@@ -1,4 +1,4 @@
-/*      $NetBSD: rumpclient.c,v 1.38 2011/02/27 12:58:29 pooka Exp $	*/
+/*      $NetBSD: rumpclient.c,v 1.39 2011/03/08 15:34:37 pooka Exp $	*/
 
 /*
  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: rumpclient.c,v 1.38 2011/02/27 12:58:29 pooka Exp $");
+__RCSID("$NetBSD: rumpclient.c,v 1.39 2011/03/08 15:34:37 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/event.h>
@@ -66,8 +66,7 @@
 int	(*host_fcntl)(int, int, ...);
 int	(*host_poll)(struct pollfd *, nfds_t, int);
 ssize_t	(*host_read)(int, void *, size_t);
-ssize_t (*host_sendto)(int, const void *, size_t, int,
-		       const struct sockaddr *, socklen_t);
+ssize_t (*host_sendmsg)(int, const struct msghdr *, int);
 int	(*host_setsockopt)(int, int, int, const void *, socklen_t);
 int	(*host_dup)(int);
 
@@ -96,7 +95,7 @@
 static time_t retrytimo = 0;
 
 static int
-send_with_recon(struct spclient *spc, const void *data, size_t dlen)
+send_with_recon(struct spclient *spc, struct iovec *iov, size_t iovlen)
 {
 	struct timeval starttime, curtime;
 	time_t prevreconmsg;
@@ -104,7 +103,7 @@
 	int rv;
 
 	for (prevreconmsg = 0, reconretries = 0;;) {
-		rv = dosend(spc, data, dlen);
+		rv = dosend(spc, iov, iovlen);
 		if (__predict_false(rv == ENOTCONN || rv == EBADF)) {
 			/* no persistent connections */
 			if (retrytimo == 0) {
@@ -287,6 +286,7 @@
 {
 	struct rsp_hdr rhdr;
 	struct respwait rw;
+	struct iovec iov[2];
 	int rv;
 
 	rhdr.rsp_len = sizeof(rhdr) + dlen;
@@ -294,13 +294,12 @@
 	rhdr.rsp_type = RUMPSP_SYSCALL;
 	rhdr.rsp_sysnum = sysnum;
 
+	IOVPUT(iov[0], rhdr);
+	IOVPUT_WITHSIZE(iov[1], __UNCONST(data), dlen);
+
 	do {
 		putwait(spc, &rw, &rhdr);
-		if ((rv = send_with_recon(spc, &rhdr, sizeof(rhdr))) != 0) {
-			unputwait(spc, &rw);
-			continue;
-		}
-		if ((rv = send_with_recon(spc, data, dlen)) != 0) {
+		if ((rv = send_with_recon(spc, iov, __arraycount(iov))) != 0) {
 			unputwait(spc, &rw);
 			continue;
 		}
@@ -319,16 +318,19 @@
 	int cancel, bool haslock)
 {
 	struct handshake_fork rf;
+	const char *myprogname;
 	struct rsp_hdr rhdr;
 	struct respwait rw;
 	sigset_t omask;
 	size_t bonus;
+	struct iovec iov[2];
 	int rv;
 
 	if (type == HANDSHAKE_FORK) {
 		bonus = sizeof(rf);
 	} else {
-		bonus = strlen(getprogname())+1;
+		myprogname = getprogname();
+		bonus = strlen(myprogname)+1;
 	}
 
 	/* performs server handshake */
@@ -337,19 +339,21 @@
 	rhdr.rsp_type = RUMPSP_HANDSHAKE;
 	rhdr.rsp_handshake = type;
 
+	IOVPUT(iov[0], rhdr);
+
 	pthread_sigmask(SIG_SETMASK, &fullset, &omask);
 	if (haslock)
 		putwait_locked(spc, &rw, &rhdr);
 	else
 		putwait(spc, &rw, &rhdr);
-	rv = dosend(spc, &rhdr, sizeof(rhdr));
 	if (type == HANDSHAKE_FORK) {
 		memcpy(rf.rf_auth, data, sizeof(rf.rf_auth)); /* uh, why? */
 		rf.rf_cancel = cancel;
-		rv = send_with_recon(spc, &rf, sizeof(rf));
+		IOVPUT(iov[1], rf);
 	} else {
-		rv = dosend(spc, getprogname(), strlen(getprogname())+1);
+		IOVPUT_WITHSIZE(iov[1], __UNCONST(getprogname()), bonus);
 	}
+	rv = send_with_recon(spc, iov, __arraycount(iov));
 	if (rv || cancel) {
 		if (haslock)
 			unputwait_locked(spc, &rw);
@@ -377,6 +381,7 @@
 {
 	struct rsp_hdr rhdr;
 	struct respwait rw;
+	struct iovec iov[1];
 	int rv;
 
 	rhdr.rsp_len = sizeof(rhdr);
@@ -384,9 +389,11 @@
 	rhdr.rsp_type = RUMPSP_PREFORK;
 	rhdr.rsp_error = 0;
 
+	IOVPUT(iov[0], rhdr);
+
 	do {
 		putwait(spc, &rw, &rhdr);
-		rv = send_with_recon(spc, &rhdr, sizeof(rhdr));
+		rv = send_with_recon(spc, iov, __arraycount(iov));
 		if (rv != 0) {
 			unputwait(spc, &rw);
 			continue;
@@ -430,6 +437,7 @@
 	int wantstr)
 {
 	struct rsp_hdr rhdr;
+	struct iovec iov[2];
 
 	if (wantstr)
 		dlen = MIN(dlen, strlen(data)+1);
@@ -440,10 +448,12 @@
 	rhdr.rsp_type = RUMPSP_COPYIN;
 	rhdr.rsp_sysnum = 0;
 
+	IOVPUT(iov[0], rhdr);
+	IOVPUT_WITHSIZE(iov[1], data, dlen);
+
 	if (resp_sendlock(spc) != 0)
 		return;
-	(void)dosend(spc, &rhdr, sizeof(rhdr));
-	(void)dosend(spc, data, dlen);
+	(void)SENDIOV(spc, iov);
 	sendunlock(spc);
 }
 
@@ -451,6 +461,7 @@
 send_anonmmap_resp(struct spclient *spc, uint64_t reqno, void *addr)
 {
 	struct rsp_hdr rhdr;
+	struct iovec iov[2];
 
 	rhdr.rsp_len = sizeof(rhdr) + sizeof(addr);
 	rhdr.rsp_reqno = reqno;
@@ -458,10 +469,12 @@
 	rhdr.rsp_type = RUMPSP_ANONMMAP;
 	rhdr.rsp_sysnum = 0;
 
+	IOVPUT(iov[0], rhdr);
+	IOVPUT(iov[1], addr);
+
 	if (resp_sendlock(spc) != 0)
 		return;
-	(void)dosend(spc, &rhdr, sizeof(rhdr));
-	(void)dosend(spc, &addr, sizeof(addr));
+	(void)SENDIOV(spc, iov);
 	sendunlock(spc);
 }
 
@@ -775,7 +788,7 @@
 	FINDSYM(fcntl)
 	FINDSYM(poll)
 	FINDSYM(read)
-	FINDSYM(sendto)
+	FINDSYM(sendmsg)
 	FINDSYM(setsockopt)
 	FINDSYM(dup)
 	FINDSYM(kqueue)

Index: src/lib/librumpuser/rumpuser_sp.c
diff -u src/lib/librumpuser/rumpuser_sp.c:1.44 src/lib/librumpuser/rumpuser_sp.c:1.45
--- src/lib/librumpuser/rumpuser_sp.c:1.44	Tue Mar  8 12:39:28 2011
+++ src/lib/librumpuser/rumpuser_sp.c	Tue Mar  8 15:34:37 2011
@@ -1,4 +1,4 @@
-/*      $NetBSD: rumpuser_sp.c,v 1.44 2011/03/08 12:39:28 pooka Exp $	*/
+/*      $NetBSD: rumpuser_sp.c,v 1.45 2011/03/08 15:34:37 pooka Exp $	*/
 
 /*
  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: rumpuser_sp.c,v 1.44 2011/03/08 12:39:28 pooka Exp $");
+__RCSID("$NetBSD: rumpuser_sp.c,v 1.45 2011/03/08 15:34:37 pooka Exp $");
 
 #include <sys/types.h>
 #include <sys/atomic.h>
@@ -238,10 +238,16 @@
 	return nw;
 }
 
+/*
+ * XXX: we send responses with "blocking" I/O.  This is not
+ * ok for the main thread.  XXXFIXME
+ */
+
 static void
 send_error_resp(struct spclient *spc, uint64_t reqno, int error)
 {
 	struct rsp_hdr rhdr;
+	struct iovec iov[1];
 
 	rhdr.rsp_len = sizeof(rhdr);
 	rhdr.rsp_reqno = reqno;
@@ -249,8 +255,10 @@
 	rhdr.rsp_type = 0;
 	rhdr.rsp_error = error;
 
+	IOVPUT(iov[0], rhdr);
+
 	sendlock(spc);
-	(void)dosend(spc, &rhdr, sizeof(rhdr));
+	(void)SENDIOV(spc, iov);
 	sendunlock(spc);
 }
 
@@ -258,6 +266,7 @@
 send_handshake_resp(struct spclient *spc, uint64_t reqno, int error)
 {
 	struct rsp_hdr rhdr;
+	struct iovec iov[2];
 	int rv;
 
 	rhdr.rsp_len = sizeof(rhdr) + sizeof(error);
@@ -266,9 +275,11 @@
 	rhdr.rsp_type = RUMPSP_HANDSHAKE;
 	rhdr.rsp_error = 0;
 
+	IOVPUT(iov[0], rhdr);
+	IOVPUT(iov[1], error);
+
 	sendlock(spc);
-	rv = dosend(spc, &rhdr, sizeof(rhdr));
-	rv = dosend(spc, &error, sizeof(error));
+	rv = SENDIOV(spc, iov);
 	sendunlock(spc);
 
 	return rv;
@@ -280,6 +291,7 @@
 {
 	struct rsp_hdr rhdr;
 	struct rsp_sysresp sysresp;
+	struct iovec iov[2];
 	int rv;
 
 	rhdr.rsp_len = sizeof(rhdr) + sizeof(sysresp);
@@ -291,9 +303,11 @@
 	sysresp.rsys_error = error;
 	memcpy(sysresp.rsys_retval, retval, sizeof(sysresp.rsys_retval));
 
+	IOVPUT(iov[0], rhdr);
+	IOVPUT(iov[1], sysresp);
+
 	sendlock(spc);
-	rv = dosend(spc, &rhdr, sizeof(rhdr));
-	rv = dosend(spc, &sysresp, sizeof(sysresp));
+	rv = SENDIOV(spc, iov);
 	sendunlock(spc);
 
 	return rv;
@@ -303,6 +317,7 @@
 send_prefork_resp(struct spclient *spc, uint64_t reqno, uint32_t *auth)
 {
 	struct rsp_hdr rhdr;
+	struct iovec iov[2];
 	int rv;
 
 	rhdr.rsp_len = sizeof(rhdr) + AUTHLEN*sizeof(*auth);
@@ -311,9 +326,11 @@
 	rhdr.rsp_type = RUMPSP_PREFORK;
 	rhdr.rsp_sysnum = 0;
 
+	IOVPUT(iov[0], rhdr);
+	IOVPUT_WITHSIZE(iov[1], auth, AUTHLEN*sizeof(*auth));
+
 	sendlock(spc);
-	rv = dosend(spc, &rhdr, sizeof(rhdr));
-	rv = dosend(spc, auth, AUTHLEN*sizeof(*auth));
+	rv = SENDIOV(spc, iov);
 	sendunlock(spc);
 
 	return rv;
@@ -326,6 +343,7 @@
 	struct rsp_hdr rhdr;
 	struct rsp_copydata copydata;
 	struct respwait rw;
+	struct iovec iov[2];
 	int rv;
 
 	DPRINTF(("copyin_req: %zu bytes from %p\n", *dlen, remaddr));
@@ -341,9 +359,11 @@
 	copydata.rcp_addr = __UNCONST(remaddr);
 	copydata.rcp_len = *dlen;
 
+	IOVPUT(iov[0], rhdr);
+	IOVPUT(iov[1], copydata);
+
 	putwait(spc, &rw, &rhdr);
-	rv = dosend(spc, &rhdr, sizeof(rhdr));
-	rv = dosend(spc, &copydata, sizeof(copydata));
+	rv = SENDIOV(spc, iov);
 	if (rv) {
 		unputwait(spc, &rw);
 		return rv;
@@ -367,6 +387,7 @@
 {
 	struct rsp_hdr rhdr;
 	struct rsp_copydata copydata;
+	struct iovec iov[3];
 	int rv;
 
 	DPRINTF(("copyout_req (async): %zu bytes to %p\n", dlen, remaddr));
@@ -380,10 +401,12 @@
 	copydata.rcp_addr = __UNCONST(remaddr);
 	copydata.rcp_len = dlen;
 
+	IOVPUT(iov[0], rhdr);
+	IOVPUT(iov[1], copydata);
+	IOVPUT_WITHSIZE(iov[2], __UNCONST(data), dlen);
+
 	sendlock(spc);
-	rv = dosend(spc, &rhdr, sizeof(rhdr));
-	rv = dosend(spc, &copydata, sizeof(copydata));
-	rv = dosend(spc, data, dlen);
+	rv = SENDIOV(spc, iov);
 	sendunlock(spc);
 
 	return rv;
@@ -394,6 +417,7 @@
 {
 	struct rsp_hdr rhdr;
 	struct respwait rw;
+	struct iovec iov[2];
 	int rv;
 
 	DPRINTF(("anonmmap_req: %zu bytes\n", howmuch));
@@ -403,9 +427,11 @@
 	rhdr.rsp_type = RUMPSP_ANONMMAP;
 	rhdr.rsp_sysnum = 0;
 
+	IOVPUT(iov[0], rhdr);
+	IOVPUT(iov[1], howmuch);
+
 	putwait(spc, &rw, &rhdr);
-	rv = dosend(spc, &rhdr, sizeof(rhdr));
-	rv = dosend(spc, &howmuch, sizeof(howmuch));
+	rv = SENDIOV(spc, iov);
 	if (rv) {
 		unputwait(spc, &rw);
 		return rv;
@@ -424,6 +450,7 @@
 send_raise_req(struct spclient *spc, int signo)
 {
 	struct rsp_hdr rhdr;
+	struct iovec iov[1];
 	int rv;
 
 	rhdr.rsp_len = sizeof(rhdr);
@@ -431,8 +458,10 @@
 	rhdr.rsp_type = RUMPSP_RAISE;
 	rhdr.rsp_signo = signo;
 
+	IOVPUT(iov[0], rhdr);
+
 	sendlock(spc);
-	rv = dosend(spc, &rhdr, sizeof(rhdr));
+	rv = SENDIOV(spc, iov);
 	sendunlock(spc);
 
 	return rv;

Index: src/lib/librumpuser/sp_common.c
diff -u src/lib/librumpuser/sp_common.c:1.30 src/lib/librumpuser/sp_common.c:1.31
--- src/lib/librumpuser/sp_common.c:1.30	Tue Mar  8 12:39:28 2011
+++ src/lib/librumpuser/sp_common.c	Tue Mar  8 15:34:37 2011
@@ -1,4 +1,4 @@
-/*      $NetBSD: sp_common.c,v 1.30 2011/03/08 12:39:28 pooka Exp $	*/
+/*      $NetBSD: sp_common.c,v 1.31 2011/03/08 15:34:37 pooka Exp $	*/
 
 /*
  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
@@ -74,10 +74,14 @@
 #ifndef HOSTOPS
 #define host_poll poll
 #define host_read read
-#define host_sendto sendto
+#define host_sendmsg sendmsg
 #define host_setsockopt setsockopt
 #endif
 
+#define IOVPUT(_io_, _b_) _io_.iov_base = &_b_; _io_.iov_len = sizeof(_b_);
+#define IOVPUT_WITHSIZE(_io_, _b_, _l_) _io_.iov_base = _b_; _io_.iov_len = _l_;
+#define SENDIOV(_spc_, _iov_) dosend(_spc_, _iov_, __arraycount(_iov_))
+
 /*
  * Bah, I hate writing on-off-wire conversions in C
  */
@@ -254,18 +258,20 @@
 }
 
 static int
-dosend(struct spclient *spc, const void *data, size_t dlen)
+dosend(struct spclient *spc, struct iovec *iov, size_t iovlen)
 {
+	struct msghdr msg;
 	struct pollfd pfd;
-	const uint8_t *sdata = data;
-	ssize_t n;
-	size_t sent;
+	ssize_t n = 0;
 	int fd = spc->spc_fd;
 
 	pfd.fd = fd;
 	pfd.events = POLLOUT;
 
-	for (sent = 0, n = 0; sent < dlen; ) {
+	memset(&msg, 0, sizeof(msg));
+
+	for (;;) {
+		/* not first round?  poll */
 		if (n) {
 			if (host_poll(&pfd, 1, INFTIM) == -1) {
 				if (errno == EINTR)
@@ -274,8 +280,9 @@
 			}
 		}
 
-		n = host_sendto(fd, sdata + sent, dlen - sent,
-		    MSG_NOSIGNAL, NULL, 0);
+		msg.msg_iov = iov;
+		msg.msg_iovlen = iovlen;
+		n = host_sendmsg(fd, &msg, MSG_NOSIGNAL);
 		if (n == -1)  {
 			if (errno == EPIPE)
 				return ENOTCONN;
@@ -286,7 +293,21 @@
 		if (n == 0) {
 			return ENOTCONN;
 		}
-		sent += n;
+
+		/* ok, need to adjust iovec for potential next round */
+		while (n >= (ssize_t)iov[0].iov_len && iovlen) {
+			n -= iov[0].iov_len;
+			iov++;
+			iovlen--;
+		}
+
+		if (iovlen == 0) {
+			_DIAGASSERT(n == 0);
+			break;
+		} else {
+			iov[0].iov_base = (uint8_t *)iov[0].iov_base + n;
+			iov[0].iov_len -= n;
+		}
 	}
 
 	return 0;

Reply via email to