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