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, ©data, 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, ©data, 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;