Module Name: src
Committed By: martin
Date: Wed Sep 12 10:35:10 UTC 2012
Modified Files:
src/lib/librumphijack: hijack.c
Log Message:
When emulating poll/select better tell the events of the host kernel
apart from those received from the rump kernel. Also handle timeout.
Patch from pooka.
To generate a diff of this commit:
cvs rdiff -u -r1.98 -r1.99 src/lib/librumphijack/hijack.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/librumphijack/hijack.c
diff -u src/lib/librumphijack/hijack.c:1.98 src/lib/librumphijack/hijack.c:1.99
--- src/lib/librumphijack/hijack.c:1.98 Mon Sep 3 12:07:42 2012
+++ src/lib/librumphijack/hijack.c Wed Sep 12 10:35:10 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: hijack.c,v 1.98 2012/09/03 12:07:42 pooka Exp $ */
+/* $NetBSD: hijack.c,v 1.99 2012/09/12 10:35:10 martin Exp $ */
/*-
* Copyright (c) 2011 Antti Kantee. All Rights Reserved.
@@ -31,7 +31,7 @@
#include "rumpuser_port.h"
#include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.98 2012/09/03 12:07:42 pooka Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.99 2012/09/12 10:35:10 martin Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -1502,7 +1502,7 @@ msg_convert(struct msghdr *msg, int (*fu
int *fdp = (void *)CMSG_DATA(cmsg);
const size_t size =
cmsg->cmsg_len - __CMSG_ALIGN(sizeof(*cmsg));
- const int nfds = size / sizeof(int);
+ const int nfds = (int)(size / sizeof(int));
const int * const efdp = fdp + nfds;
while (fdp < efdp) {
@@ -1957,7 +1957,7 @@ REALPOLLTS(struct pollfd *fds, nfds_t nf
int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1};
struct pollarg parg;
void *trv_val;
- int sverrno = 0, lrv, trv;
+ int sverrno = 0, rv_rump, rv_host, errno_rump, errno_host;
/*
* ok, this is where it gets tricky. We must support
@@ -2047,30 +2047,63 @@ REALPOLLTS(struct pollfd *fds, nfds_t nf
pthread_create(&pt, NULL, hostpoll, &parg);
op_pollts = GETSYSCALL(rump, POLLTS);
- lrv = op_pollts(pfd_rump, nfds+1, ts, NULL);
- sverrno = errno;
+ rv_rump = op_pollts(pfd_rump, nfds+1, ts, NULL);
+ errno_rump = errno;
write(hpipe[1], &rv, sizeof(rv));
pthread_join(pt, &trv_val);
- trv = (int)(intptr_t)trv_val;
+ rv_host = (int)(intptr_t)trv_val;
+ errno_host = parg.errnum;
- /* check who "won" and merge results */
- if (lrv != 0 && pfd_host[nfds].revents & POLLIN) {
- rv = trv;
-
- for (i = 0; i < nfds; i++) {
- if (pfd_rump[i].fd != -1)
- fds[i].revents = pfd_rump[i].revents;
+ /* strip cross-thread notification from real results */
+ if (pfd_host[nfds].revents & POLLIN) {
+ assert((pfd_rump[nfds].revents & POLLIN) == 0);
+ assert(rv_host > 0);
+ rv_host--;
+ }
+ if (pfd_rump[nfds].revents & POLLIN) {
+ assert((pfd_host[nfds].revents & POLLIN) == 0);
+ assert(rv_rump > 0);
+ rv_rump--;
+ }
+
+ /* then merge the results into what's reported to the caller */
+ if (rv_rump > 0 || rv_host > 0) {
+ /* SUCCESS */
+
+ rv = 0;
+ if (rv_rump > 0) {
+ for (i = 0; i < nfds; i++) {
+ if (pfd_rump[i].fd != -1)
+ fds[i].revents
+ = pfd_rump[i].revents;
+ }
+ rv += rv_rump;
}
- sverrno = parg.errnum;
- } else if (trv != 0 && pfd_rump[nfds].revents & POLLIN) {
- rv = trv;
-
- for (i = 0; i < nfds; i++) {
- if (pfd_host[i].fd != -1)
- fds[i].revents = pfd_host[i].revents;
+ if (rv_host > 0) {
+ for (i = 0; i < nfds; i++) {
+ if (pfd_host[i].fd != -1)
+ fds[i].revents
+ = pfd_host[i].revents;
+ }
+ rv += rv_host;
+ }
+ assert(rv > 0);
+ sverrno = 0;
+ } else if (rv_rump == -1 || rv_host == -1) {
+ /* ERROR */
+
+ /* just pick one kernel at "random" */
+ rv = -1;
+ if (rv_host == -1) {
+ sverrno = errno_host;
+ } else if (rv_rump == -1) {
+ sverrno = errno_rump;
}
} else {
+ /* TIMEOUT */
+
rv = 0;
+ assert(rv_rump == 0 && rv_host == 0);
}
out: