Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib Make rumpclient syscalls safe to call from signal handlers.
details: https://anonhg.NetBSD.org/src/rev/9005e557e677
branches: trunk
changeset: 760494:9005e557e677
user: pooka <pooka%NetBSD.org@localhost>
date: Thu Jan 06 06:57:14 2011 +0000
description:
Make rumpclient syscalls safe to call from signal handlers.
diffstat:
lib/librumpclient/rumpclient.c | 107 ++++++++++++++++++++++++++++++++++++++--
lib/librumpuser/rumpuser_sp.c | 80 +++++++++++++++++++++++++++++-
lib/librumpuser/sp_common.c | 74 +---------------------------
3 files changed, 180 insertions(+), 81 deletions(-)
diffs (truncated from 392 to 300 lines):
diff -r 1fe045269859 -r 9005e557e677 lib/librumpclient/rumpclient.c
--- a/lib/librumpclient/rumpclient.c Thu Jan 06 06:49:12 2011 +0000
+++ b/lib/librumpclient/rumpclient.c Thu Jan 06 06:57:14 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpclient.c,v 1.11 2011/01/05 17:14:50 pooka Exp $ */
+/* $NetBSD: rumpclient.c,v 1.12 2011/01/06 06:57:14 pooka Exp $ */
/*
* Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved.
@@ -60,12 +60,95 @@
.spc_fd = -1,
};
+/*
+ * This version of waitresp is optimized for single-threaded clients
+ * and is required by signal-safe clientside rump syscalls.
+ */
+
+static void
+releasercvlock(struct spclient *spc)
+{
+
+ pthread_mutex_lock(&spc->spc_mtx);
+ if (spc->spc_istatus == SPCSTATUS_WANTED)
+ kickall(spc);
+ spc->spc_istatus = SPCSTATUS_FREE;
+}
+
+static sigset_t fullset;
+static int
+waitresp(struct spclient *spc, struct respwait *rw, sigset_t *mask)
+{
+ struct pollfd pfd;
+ int rv = 0;
+
+ sendunlockl(spc);
+
+ rw->rw_error = 0;
+ while (rw->rw_data == NULL && rw->rw_error == 0
+ && spc->spc_state != SPCSTATE_DYING){
+ /* are we free to receive? */
+ if (spc->spc_istatus == SPCSTATUS_FREE) {
+ spc->spc_istatus = SPCSTATUS_BUSY;
+ pthread_mutex_unlock(&spc->spc_mtx);
+
+ pfd.fd = spc->spc_fd;
+ pfd.events = POLLIN;
+
+ switch (readframe(spc)) {
+ case 0:
+ releasercvlock(spc);
+ pthread_mutex_unlock(&spc->spc_mtx);
+ pollts(&pfd, 1, NULL, mask);
+ pthread_mutex_lock(&spc->spc_mtx);
+ continue;
+ case -1:
+ releasercvlock(spc);
+ rv = errno;
+ spc->spc_state = SPCSTATE_DYING;
+ continue;
+ default:
+ break;
+ }
+
+ switch (spc->spc_hdr.rsp_class) {
+ case RUMPSP_RESP:
+ case RUMPSP_ERROR:
+ kickwaiter(spc);
+ break;
+ case RUMPSP_REQ:
+ handlereq(spc);
+ break;
+ default:
+ /* panic */
+ break;
+ }
+
+ releasercvlock(spc);
+ } else {
+ spc->spc_istatus = SPCSTATUS_WANTED;
+ pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);
+ }
+ }
+ TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
+ pthread_mutex_unlock(&spc->spc_mtx);
+ pthread_cond_destroy(&rw->rw_cv);
+
+ if (rv)
+ return rv;
+ if (spc->spc_state == SPCSTATE_DYING)
+ return ENOTCONN;
+ return rw->rw_error;
+}
+
+
static int
syscall_req(struct spclient *spc, int sysnum,
const void *data, size_t dlen, void **resp)
{
struct rsp_hdr rhdr;
struct respwait rw;
+ sigset_t omask;
int rv;
rhdr.rsp_len = sizeof(rhdr) + dlen;
@@ -73,17 +156,21 @@
rhdr.rsp_type = RUMPSP_SYSCALL;
rhdr.rsp_sysnum = sysnum;
+ pthread_sigmask(SIG_SETMASK, &fullset, &omask);
do {
+
putwait(spc, &rw, &rhdr);
rv = dosend(spc, &rhdr, sizeof(rhdr));
rv = dosend(spc, data, dlen);
if (rv) {
unputwait(spc, &rw);
+ pthread_sigmask(SIG_SETMASK, &omask, NULL);
return rv;
}
- rv = waitresp(spc, &rw);
+ rv = waitresp(spc, &rw, &omask);
} while (rv == EAGAIN);
+ pthread_sigmask(SIG_SETMASK, &omask, NULL);
*resp = rw.rw_data;
return rv;
@@ -95,6 +182,7 @@
struct handshake_fork rf;
struct rsp_hdr rhdr;
struct respwait rw;
+ sigset_t omask;
int rv;
/* performs server handshake */
@@ -106,6 +194,7 @@
else
rhdr.rsp_handshake = HANDSHAKE_GUEST;
+ pthread_sigmask(SIG_SETMASK, &fullset, &omask);
putwait(spc, &rw, &rhdr);
rv = dosend(spc, &rhdr, sizeof(rhdr));
if (auth) {
@@ -115,10 +204,12 @@
}
if (rv != 0 || cancel) {
unputwait(spc, &rw);
+ pthread_sigmask(SIG_SETMASK, &omask, NULL);
return rv;
}
- rv = waitresp(spc, &rw);
+ rv = waitresp(spc, &rw, &omask);
+ pthread_sigmask(SIG_SETMASK, &omask, NULL);
if (rv)
return rv;
@@ -133,6 +224,7 @@
{
struct rsp_hdr rhdr;
struct respwait rw;
+ sigset_t omask;
int rv;
rhdr.rsp_len = sizeof(rhdr);
@@ -140,15 +232,17 @@
rhdr.rsp_type = RUMPSP_PREFORK;
rhdr.rsp_error = 0;
-
+ pthread_sigmask(SIG_SETMASK, &fullset, &omask);
putwait(spc, &rw, &rhdr);
rv = dosend(spc, &rhdr, sizeof(rhdr));
if (rv != 0) {
unputwait(spc, &rw);
+ pthread_sigmask(SIG_SETMASK, &omask, NULL);
return rv;
}
- rv = waitresp(spc, &rw);
+ rv = waitresp(spc, &rw, &omask);
+ pthread_sigmask(SIG_SETMASK, &omask, NULL);
*resp = rw.rw_data;
return rv;
}
@@ -263,7 +357,7 @@
send_anonmmap_resp(spc, spc->spc_hdr.rsp_reqno, mapaddr);
break;
default:
- printf("PANIC: INVALID TYPE\n");
+ printf("PANIC: INVALID TYPE %d\n", reqtype);
abort();
break;
}
@@ -351,6 +445,7 @@
return -1;
}
+ sigfillset(&fullset);
return 0;
}
diff -r 1fe045269859 -r 9005e557e677 lib/librumpuser/rumpuser_sp.c
--- a/lib/librumpuser/rumpuser_sp.c Thu Jan 06 06:49:12 2011 +0000
+++ b/lib/librumpuser/rumpuser_sp.c Thu Jan 06 06:57:14 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rumpuser_sp.c,v 1.30 2011/01/05 22:57:01 pooka Exp $ */
+/* $NetBSD: rumpuser_sp.c,v 1.31 2011/01/06 06:57:14 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.30 2011/01/05 22:57:01 pooka Exp $");
+__RCSID("$NetBSD: rumpuser_sp.c,v 1.31 2011/01/06 06:57:14 pooka Exp $");
#include <sys/types.h>
#include <sys/atomic.h>
@@ -98,6 +98,82 @@
static pthread_mutex_t pfmtx;
/*
+ * This version is for the server. It's optimized for multiple threads
+ * and is *NOT* reentrant wrt to signals
+ */
+static int
+waitresp(struct spclient *spc, struct respwait *rw)
+{
+ struct pollfd pfd;
+ int rv = 0;
+
+ sendunlockl(spc);
+
+ rw->rw_error = 0;
+ while (rw->rw_data == NULL && rw->rw_error == 0
+ && spc->spc_state != SPCSTATE_DYING){
+ /* are we free to receive? */
+ if (spc->spc_istatus == SPCSTATUS_FREE) {
+ int gotresp;
+
+ spc->spc_istatus = SPCSTATUS_BUSY;
+ pthread_mutex_unlock(&spc->spc_mtx);
+
+ pfd.fd = spc->spc_fd;
+ pfd.events = POLLIN;
+
+ for (gotresp = 0; !gotresp; ) {
+ switch (readframe(spc)) {
+ case 0:
+ poll(&pfd, 1, INFTIM);
+ continue;
+ case -1:
+ rv = errno;
+ spc->spc_state = SPCSTATE_DYING;
+ goto cleanup;
+ default:
+ break;
+ }
+
+ switch (spc->spc_hdr.rsp_class) {
+ case RUMPSP_RESP:
+ case RUMPSP_ERROR:
+ kickwaiter(spc);
+ gotresp = spc->spc_hdr.rsp_reqno ==
+ rw->rw_reqno;
+ break;
+ case RUMPSP_REQ:
+ handlereq(spc);
+ break;
+ default:
+ /* panic */
+ break;
+ }
+ }
+ cleanup:
+ pthread_mutex_lock(&spc->spc_mtx);
+ if (spc->spc_istatus == SPCSTATUS_WANTED)
+ kickall(spc);
+ spc->spc_istatus = SPCSTATUS_FREE;
+ } else {
+ spc->spc_istatus = SPCSTATUS_WANTED;
+ pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);
+ }
+ }
+
+ TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
+ pthread_mutex_unlock(&spc->spc_mtx);
+
+ pthread_cond_destroy(&rw->rw_cv);
+
+ if (rv)
+ return rv;
+ if (spc->spc_state == SPCSTATE_DYING)
+ return ENOTCONN;
+ return rw->rw_error;
+}
+
Home |
Main Index |
Thread Index |
Old Index