Module Name:    src
Committed By:   pooka
Date:           Tue May 18 14:58:42 UTC 2010

Modified Files:
        src/lib/librumpuser: rumpuser_int.h rumpuser_pth.c
        src/sys/rump/include/rump: rumpuser.h
        src/sys/rump/librump/rumpkern: intr.c locks.c rump_private.h
            scheduler.c

Log Message:
Make it possible to use the scheduler lock as the rumpuser condvar
interlock.  This is applicable in cases where the actual interlock
is the CPU the currently running thread is scheduled on.  Borrowing
the scheduler lock as the mutex mandated by pthread_cond_wait()
does away with need to have an additional mutex.  This both optimizes
runtime execution and simplifies code, as the extra lock typically
lead to quite some trickeries to avoid the dungeon collapsing due
to zaps from the wand of deadlock.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/lib/librumpuser/rumpuser_int.h
cvs rdiff -u -r1.1 -r1.2 src/lib/librumpuser/rumpuser_pth.c
cvs rdiff -u -r1.40 -r1.41 src/sys/rump/include/rump/rumpuser.h
cvs rdiff -u -r1.27 -r1.28 src/sys/rump/librump/rumpkern/intr.c
cvs rdiff -u -r1.39 -r1.40 src/sys/rump/librump/rumpkern/locks.c
cvs rdiff -u -r1.44 -r1.45 src/sys/rump/librump/rumpkern/rump_private.h
cvs rdiff -u -r1.13 -r1.14 src/sys/rump/librump/rumpkern/scheduler.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/librumpuser/rumpuser_int.h
diff -u src/lib/librumpuser/rumpuser_int.h:1.2 src/lib/librumpuser/rumpuser_int.h:1.3
--- src/lib/librumpuser/rumpuser_int.h:1.2	Mon Mar 22 09:39:02 2010
+++ src/lib/librumpuser/rumpuser_int.h	Tue May 18 14:58:41 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser_int.h,v 1.2 2010/03/22 09:39:02 pooka Exp $	*/
+/*	$NetBSD: rumpuser_int.h,v 1.3 2010/05/18 14:58:41 pooka Exp $	*/
 
 /*
  * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
@@ -25,6 +25,8 @@
  * SUCH DAMAGE.
  */
 
+#include <stdlib.h>
+
 #include <rump/rumpuser.h>
 
 extern kernel_lockfn rumpuser__klock;
@@ -34,9 +36,9 @@
 #define KLOCK_WRAP(a)							\
 do {									\
 	int nlocks;							\
-	rumpuser__kunlock(0, &nlocks);					\
+	rumpuser__kunlock(0, &nlocks, NULL);				\
 	a;								\
-	rumpuser__klock(nlocks);					\
+	rumpuser__klock(nlocks, NULL);					\
 } while (/*CONSTCOND*/0)
 
 #define DOCALL(rvtype, call)						\
@@ -54,9 +56,9 @@
 {									\
 	rvtype rv;							\
 	int nlocks;							\
-	rumpuser__kunlock(0, &nlocks);					\
+	rumpuser__kunlock(0, &nlocks, NULL);				\
 	rv = call;							\
-	rumpuser__klock(nlocks);					\
+	rumpuser__klock(nlocks, NULL);					\
 	if (rv == -1)							\
 		*error = errno;						\
 	else								\

Index: src/lib/librumpuser/rumpuser_pth.c
diff -u src/lib/librumpuser/rumpuser_pth.c:1.1 src/lib/librumpuser/rumpuser_pth.c:1.2
--- src/lib/librumpuser/rumpuser_pth.c:1.1	Fri Feb 26 18:54:20 2010
+++ src/lib/librumpuser/rumpuser_pth.c	Tue May 18 14:58:41 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser_pth.c,v 1.1 2010/02/26 18:54:20 pooka Exp $	*/
+/*	$NetBSD: rumpuser_pth.c,v 1.2 2010/05/18 14:58:41 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007-2010 Antti Kantee.  All Rights Reserved.
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>
 #if !defined(lint)
-__RCSID("$NetBSD: rumpuser_pth.c,v 1.1 2010/02/26 18:54:20 pooka Exp $");
+__RCSID("$NetBSD: rumpuser_pth.c,v 1.2 2010/05/18 14:58:41 pooka Exp $");
 #endif /* !lint */
 
 #ifdef __linux__
@@ -131,7 +131,7 @@
 	int error, dummy;
 
 	/* unschedule from CPU.  we reschedule before running the interrupt */
-	rumpuser__kunlock(0, &dummy);
+	rumpuser__kunlock(0, &dummy, NULL);
 	assert(dummy == 0);
 
 	NOFAIL_ERRNO(pthread_mutex_lock(&rumpuser_aio_mtx.pthmtx));
@@ -169,9 +169,9 @@
 #endif
 			}
 		}
-		rumpuser__klock(0);
+		rumpuser__klock(0, NULL);
 		biodone(rua->rua_bp, (size_t)rv, error);
-		rumpuser__kunlock(0, &dummy);
+		rumpuser__kunlock(0, &dummy, NULL);
 
 		rua->rua_bp = NULL;
 
@@ -443,12 +443,15 @@
 void
 rumpuser_cv_wait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
 {
+	int nlocks;
 
 	cv->nwaiters++;
+	rumpuser__kunlock(0, &nlocks, mtx);
 	assert(mtx->recursion == 1);
 	mtxexit(mtx);
-	KLOCK_WRAP(NOFAIL_ERRNO(pthread_cond_wait(&cv->pthcv, &mtx->pthmtx)));
+	NOFAIL_ERRNO(pthread_cond_wait(&cv->pthcv, &mtx->pthmtx));
 	mtxenter(mtx);
+	rumpuser__klock(nlocks, mtx);
 	cv->nwaiters--;
 }
 
@@ -469,15 +472,17 @@
 	int64_t sec, int64_t nsec)
 {
 	struct timespec ts;
-	int rv;
+	int rv, nlocks;
 
 	/* LINTED */
 	ts.tv_sec = sec; ts.tv_nsec = nsec;
 
 	cv->nwaiters++;
+	rumpuser__kunlock(0, &nlocks, mtx);
 	mtxexit(mtx);
-	KLOCK_WRAP(rv = pthread_cond_timedwait(&cv->pthcv, &mtx->pthmtx, &ts));
+	rv = pthread_cond_timedwait(&cv->pthcv, &mtx->pthmtx, &ts);
 	mtxenter(mtx);
+	rumpuser__klock(nlocks, mtx);
 	cv->nwaiters--;
 	if (rv != 0 && rv != ETIMEDOUT)
 		abort();

Index: src/sys/rump/include/rump/rumpuser.h
diff -u src/sys/rump/include/rump/rumpuser.h:1.40 src/sys/rump/include/rump/rumpuser.h:1.41
--- src/sys/rump/include/rump/rumpuser.h:1.40	Wed Apr 28 00:33:45 2010
+++ src/sys/rump/include/rump/rumpuser.h	Tue May 18 14:58:41 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser.h,v 1.40 2010/04/28 00:33:45 pooka Exp $	*/
+/*	$NetBSD: rumpuser.h,v 1.41 2010/05/18 14:58:41 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007 Antti Kantee.  All Rights Reserved.
@@ -40,8 +40,8 @@
 struct pollfd;
 struct sockaddr;
 
-typedef void (*kernel_lockfn)(int);
-typedef void (*kernel_unlockfn)(int, int *);
+typedef void (*kernel_lockfn)(int, void *);
+typedef void (*kernel_unlockfn)(int, int *, void *);
 
 int rumpuser_getfileinfo(const char *, uint64_t *, int *, int *);
 #define RUMPUSER_FT_OTHER 0

Index: src/sys/rump/librump/rumpkern/intr.c
diff -u src/sys/rump/librump/rumpkern/intr.c:1.27 src/sys/rump/librump/rumpkern/intr.c:1.28
--- src/sys/rump/librump/rumpkern/intr.c:1.27	Wed May 12 16:48:21 2010
+++ src/sys/rump/librump/rumpkern/intr.c	Tue May 18 14:58:42 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.c,v 1.27 2010/05/12 16:48:21 pooka Exp $	*/
+/*	$NetBSD: intr.c,v 1.28 2010/05/18 14:58:42 pooka Exp $	*/
 
 /*
  * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
@@ -26,13 +26,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.27 2010/05/12 16:48:21 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.28 2010/05/18 14:58:42 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
 #include <sys/kernel.h>
 #include <sys/kmem.h>
 #include <sys/kthread.h>
+#include <sys/malloc.h>
 #include <sys/intr.h>
 #include <sys/timetc.h>
 
@@ -57,7 +58,6 @@
 	LIST_ENTRY(softint) si_entries;
 };
 
-static struct rumpuser_mtx *si_mtx;
 struct softint_lev {
 	struct rumpuser_cv *si_cv;
 	LIST_HEAD(, softint) si_pending;
@@ -140,9 +140,9 @@
 }
 
 /*
- * Soft interrupt execution thread.  Note that we run without a CPU
- * context until we start processing the interrupt.  This is to avoid
- * lock recursion.
+ * Soft interrupt execution thread.  This thread is pinned to the
+ * same CPU that scheduled the interrupt, so we don't need to do
+ * lock against si_lvl.
  */
 static void
 sithread(void *arg)
@@ -155,16 +155,9 @@
 	struct softint_lev *si_lvlp, *si_lvl;
 	struct cpu_data *cd = &curcpu()->ci_data;
 
-	rump_unschedule();
-
 	si_lvlp = cd->cpu_softcpu;
 	si_lvl = &si_lvlp[mylevel];
 
-	/*
-	 * XXX: si_mtx is unnecessary, and should open an interface
-	 * which allows to use schedmtx for the cv wait
-	 */
-	rumpuser_mutex_enter_nowrap(si_mtx);
 	for (;;) {
 		if (!LIST_EMPTY(&si_lvl->si_pending)) {
 			si = LIST_FIRST(&si_lvl->si_pending);
@@ -175,28 +168,19 @@
 			si->si_flags &= ~SI_ONLIST;
 			LIST_REMOVE(si, si_entries);
 			if (si->si_flags & SI_KILLME) {
-				rumpuser_mutex_exit(si_mtx);
-				rump_schedule();
 				softint_disestablish(si);
-				rump_unschedule();
-				rumpuser_mutex_enter_nowrap(si_mtx);
 				continue;
 			}
 		} else {
-			rumpuser_cv_wait_nowrap(si_lvl->si_cv, si_mtx);
+			rump_schedlock_cv_wait(si_lvl->si_cv);
 			continue;
 		}
-		rumpuser_mutex_exit(si_mtx);
 
-		rump_schedule();
 		if (!mpsafe)
 			KERNEL_LOCK(1, curlwp);
 		func(funarg);
 		if (!mpsafe)
 			KERNEL_UNLOCK_ONE(curlwp);
-		rump_unschedule();
-
-		rumpuser_mutex_enter_nowrap(si_mtx);
 	}
 
 	panic("sithread unreachable");
@@ -206,7 +190,6 @@
 rump_intr_init()
 {
 
-	rumpuser_mutex_init(&si_mtx);
 	cv_init(&lbolt, "oh kath ra");
 }
 
@@ -233,6 +216,9 @@
 	}
 	cd->cpu_softcpu = slev;
 
+	/* softint might run on different physical CPU */
+	membar_sync();
+
 	for (i = 0; i < SOFTINT_COUNT; i++) {
 		rv = kthread_create(PRI_NONE,
 		    KTHREAD_MPSAFE | KTHREAD_INTR, ci,
@@ -261,7 +247,7 @@
 {
 	struct softint *si;
 
-	si = kmem_alloc(sizeof(*si), KM_SLEEP);
+	si = malloc(sizeof(*si), M_TEMP, M_WAITOK);
 	si->si_func = func;
 	si->si_arg = arg;
 	si->si_flags = flags & SOFTINT_MPSAFE ? SI_MPSAFE : 0;
@@ -295,13 +281,11 @@
 {
 	struct softint *si = cook;
 
-	rumpuser_mutex_enter(si_mtx);
 	if (si->si_flags & SI_ONLIST) {
 		si->si_flags |= SI_KILLME;
 		return;
 	}
-	rumpuser_mutex_exit(si_mtx);
-	kmem_free(si, sizeof(*si));
+	free(si, M_TEMP);
 }
 
 void

Index: src/sys/rump/librump/rumpkern/locks.c
diff -u src/sys/rump/librump/rumpkern/locks.c:1.39 src/sys/rump/librump/rumpkern/locks.c:1.40
--- src/sys/rump/librump/rumpkern/locks.c:1.39	Wed Apr 14 10:34:54 2010
+++ src/sys/rump/librump/rumpkern/locks.c	Tue May 18 14:58:42 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: locks.c,v 1.39 2010/04/14 10:34:54 pooka Exp $	*/
+/*	$NetBSD: locks.c,v 1.40 2010/05/18 14:58:42 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007, 2008 Antti Kantee.  All Rights Reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: locks.c,v 1.39 2010/04/14 10:34:54 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: locks.c,v 1.40 2010/05/18 14:58:42 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/kmem.h>
@@ -332,7 +332,7 @@
 		if (!rumpuser_mutex_tryenter(rump_giantlock)) {
 			struct lwp *l = curlwp;
 
-			rump_unschedule_cpu1(l);
+			rump_unschedule_cpu1(l, NULL);
 			rumpuser_mutex_enter_nowrap(rump_giantlock);
 			rump_schedule_cpu(l);
 		}
@@ -367,7 +367,7 @@
 }
 
 void
-rump_user_unschedule(int nlocks, int *countp)
+rump_user_unschedule(int nlocks, int *countp, void *interlock)
 {
 
 	_kernel_unlock(nlocks, countp);
@@ -375,14 +375,14 @@
 	 * XXX: technically we should unschedule_cpu1() here, but that
 	 * requires rump_intr_enter/exit to be implemented.
 	 */
-	rump_unschedule_cpu(curlwp);
+	rump_unschedule_cpu_interlock(curlwp, interlock);
 }
 
 void
-rump_user_schedule(int nlocks)
+rump_user_schedule(int nlocks, void *interlock)
 {
 
-	rump_schedule_cpu(curlwp);
+	rump_schedule_cpu_interlock(curlwp, interlock);
 
 	if (nlocks)
 		_kernel_lock(nlocks);

Index: src/sys/rump/librump/rumpkern/rump_private.h
diff -u src/sys/rump/librump/rumpkern/rump_private.h:1.44 src/sys/rump/librump/rumpkern/rump_private.h:1.45
--- src/sys/rump/librump/rumpkern/rump_private.h:1.44	Tue Apr 27 23:30:30 2010
+++ src/sys/rump/librump/rumpkern/rump_private.h	Tue May 18 14:58:42 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: rump_private.h,v 1.44 2010/04/27 23:30:30 pooka Exp $	*/
+/*	$NetBSD: rump_private.h,v 1.45 2010/05/18 14:58:42 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007 Antti Kantee.  All Rights Reserved.
@@ -109,11 +109,17 @@
 void	rump_schedule(void);
 void	rump_unschedule(void);
 void 	rump_schedule_cpu(struct lwp *);
+void 	rump_schedule_cpu_interlock(struct lwp *, void *);
 void	rump_unschedule_cpu(struct lwp *);
-void	rump_unschedule_cpu1(struct lwp *);
+void	rump_unschedule_cpu_interlock(struct lwp *, void *);
+void	rump_unschedule_cpu1(struct lwp *, void *);
 
-void	rump_user_schedule(int);
-void	rump_user_unschedule(int, int *);
+void	rump_schedlock_cv_wait(struct rumpuser_cv *);
+int	rump_schedlock_cv_timedwait(struct rumpuser_cv *,
+				    const struct timespec *);
+
+void	rump_user_schedule(int, void *);
+void	rump_user_unschedule(int, int *, void *);
 
 void	rump_cpu_attach(struct cpu_info *);
 

Index: src/sys/rump/librump/rumpkern/scheduler.c
diff -u src/sys/rump/librump/rumpkern/scheduler.c:1.13 src/sys/rump/librump/rumpkern/scheduler.c:1.14
--- src/sys/rump/librump/rumpkern/scheduler.c:1.13	Wed Apr 28 00:42:16 2010
+++ src/sys/rump/librump/rumpkern/scheduler.c	Tue May 18 14:58:42 2010
@@ -1,4 +1,4 @@
-/*      $NetBSD: scheduler.c,v 1.13 2010/04/28 00:42:16 pooka Exp $	*/
+/*      $NetBSD: scheduler.c,v 1.14 2010/05/18 14:58:42 pooka Exp $	*/
 
 /*
  * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: scheduler.c,v 1.13 2010/04/28 00:42:16 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: scheduler.c,v 1.14 2010/05/18 14:58:42 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -60,6 +60,7 @@
 #define RCPU_FREELIST	0x04	/* CPU is on freelist */
 
 static LIST_HEAD(,rumpcpu) cpu_freelist = LIST_HEAD_INITIALIZER(cpu_freelist);
+
 static struct rumpuser_mtx *schedmtx;
 static struct rumpuser_cv *schedcv, *lwp0cv;
 
@@ -118,6 +119,23 @@
 	}
 }
 
+/*
+ * condvar ops using scheduler lock as the rumpuser interlock.
+ */
+void
+rump_schedlock_cv_wait(struct rumpuser_cv *cv)
+{
+
+	rumpuser_cv_wait(cv, schedmtx);
+}
+
+int
+rump_schedlock_cv_timedwait(struct rumpuser_cv *cv, const struct timespec *ts)
+{
+
+	return rumpuser_cv_timedwait(cv, schedmtx, ts->tv_sec, ts->tv_nsec);
+}
+
 void
 rump_schedule()
 {
@@ -159,9 +177,19 @@
 void
 rump_schedule_cpu(struct lwp *l)
 {
+
+	rump_schedule_cpu_interlock(l, NULL);
+}
+
+void
+rump_schedule_cpu_interlock(struct lwp *l, void *interlock)
+{
 	struct rumpcpu *rcpu;
+	bool schedlock = interlock == schedmtx;
+
+	if (!schedlock)
+		rumpuser_mutex_enter_nowrap(schedmtx);
 
-	rumpuser_mutex_enter_nowrap(schedmtx);
 	if (l->l_pflag & LP_BOUND) {
 		KASSERT(l->l_cpu != NULL);
 		rcpu = &rcpu_storage[l->l_cpu-&rump_cpus[0]];
@@ -236,16 +264,24 @@
 rump_unschedule_cpu(struct lwp *l)
 {
 
+	rump_unschedule_cpu_interlock(l, NULL);
+}
+
+void
+rump_unschedule_cpu_interlock(struct lwp *l, void *interlock)
+{
+
 	if ((l->l_pflag & LP_INTR) == 0)
 		rump_softint_run(l->l_cpu);
-	rump_unschedule_cpu1(l);
+	rump_unschedule_cpu1(l, interlock);
 }
 
 void
-rump_unschedule_cpu1(struct lwp *l)
+rump_unschedule_cpu1(struct lwp *l, void *interlock)
 {
 	struct rumpcpu *rcpu;
 	struct cpu_info *ci;
+	bool schedlock = interlock == schedmtx;
 
 	ci = l->l_cpu;
 	if ((l->l_pflag & LP_BOUND) == 0) {
@@ -256,6 +292,7 @@
 	KASSERT(rcpu->rcpu_flags & RCPU_BUSY);
 
 	rumpuser_mutex_enter_nowrap(schedmtx);
+
 	if (rcpu->rcpu_flags & RCPU_WANTED) {
 		/*
 		 * The assumption is that there will usually be max 1
@@ -270,7 +307,9 @@
 		rumpuser_cv_signal(schedcv);
 	}
 	rcpu->rcpu_flags &= ~RCPU_BUSY;
-	rumpuser_mutex_exit(schedmtx);
+
+	if (!schedlock)
+		rumpuser_mutex_exit(schedmtx);
 }
 
 /* Give up and retake CPU (perhaps a different one) */

Reply via email to