Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/rump/librump/rumpkern Support mtsleep() without a bigloc...
details: https://anonhg.NetBSD.org/src/rev/f46aaf724dc1
branches: trunk
changeset: 755303:f46aaf724dc1
user: pooka <pooka%NetBSD.org@localhost>
date: Mon May 31 23:18:33 2010 +0000
description:
Support mtsleep() without a biglocked sleeper (uvm uses this in
UVM_UNLOCK_AND_WAIT())
diffstat:
sys/rump/librump/rumpkern/ltsleep.c | 152 ++++++++++++++++++++----------
sys/rump/librump/rumpkern/rump.c | 5 +-
sys/rump/librump/rumpkern/rump_private.h | 4 +-
3 files changed, 105 insertions(+), 56 deletions(-)
diffs (281 lines):
diff -r 8f5b6621f9d3 -r f46aaf724dc1 sys/rump/librump/rumpkern/ltsleep.c
--- a/sys/rump/librump/rumpkern/ltsleep.c Mon May 31 23:13:17 2010 +0000
+++ b/sys/rump/librump/rumpkern/ltsleep.c Mon May 31 23:18:33 2010 +0000
@@ -1,10 +1,7 @@
-/* $NetBSD: ltsleep.c,v 1.26 2010/05/18 15:16:10 pooka Exp $ */
+/* $NetBSD: ltsleep.c,v 1.27 2010/05/31 23:18:33 pooka Exp $ */
/*
- * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
- *
- * Development of this software was supported by the
- * Finnish Cultural Foundation.
+ * Copyright (c) 2009, 2010 Antti Kantee. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,13 +26,15 @@
*/
/*
- * Emulate the prehistoric tsleep-style kernel interfaces. We assume
- * only code under the biglock will be using this type of synchronization
- * and use the biglock as the cv interlock.
+ * Implementation of the ltsleep/mtsleep kernel sleep interface. There
+ * are two sides to our implementation. For historic spinlocks we
+ * assume the kernel is giantlocked and use kernel giantlock as the
+ * wait interlock. For mtsleep, we use the interlock supplied by
+ * the caller. This duality leads to some if/else messiness in the code ...
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ltsleep.c,v 1.26 2010/05/18 15:16:10 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ltsleep.c,v 1.27 2010/05/31 23:18:33 pooka Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -49,46 +48,76 @@
struct ltsleeper {
wchan_t id;
- struct rumpuser_cv *cv;
+ union {
+ struct rumpuser_cv *user;
+ kcondvar_t kern;
+ } u;
+ bool iskwait;
LIST_ENTRY(ltsleeper) entries;
};
+#define ucv u.user
+#define kcv u.kern
static LIST_HEAD(, ltsleeper) sleepers = LIST_HEAD_INITIALIZER(sleepers);
+static struct rumpuser_mtx *qlock;
static int
-sleeper(struct ltsleeper *ltsp, int timo)
+sleeper(wchan_t ident, int timo, kmutex_t *kinterlock)
{
+ struct ltsleeper lts;
struct timespec ts, ticks;
- int rv, nlocks;
+ int rv;
- LIST_INSERT_HEAD(&sleepers, ltsp, entries);
- rump_kernel_unlock_allbutone(&nlocks);
+ lts.id = ident;
+ if (kinterlock) {
+ lts.iskwait = true;
+ cv_init(<s.kcv, "mtsleep");
+ } else {
+ lts.iskwait = false;
+ rumpuser_cv_init(<s.ucv);
+ }
- /* protected by biglock */
+ rumpuser_mutex_enter_nowrap(qlock);
+ LIST_INSERT_HEAD(&sleepers, <s, entries);
+ rumpuser_mutex_exit(qlock);
+
if (timo) {
- /*
- * Calculate wakeup-time.
- * XXX: should assert nanotime() does not block,
- * i.e. yield the cpu and/or biglock.
- */
- ticks.tv_sec = timo / hz;
- ticks.tv_nsec = (timo % hz) * (1000000000/hz);
- nanotime(&ts);
- timespecadd(&ts, &ticks, &ts);
+ if (kinterlock) {
+ rv = cv_timedwait(<s.kcv, kinterlock, timo);
+ } else {
+ /*
+ * Calculate wakeup-time.
+ * XXX: should assert nanotime() does not block,
+ * i.e. yield the cpu and/or biglock.
+ */
+ ticks.tv_sec = timo / hz;
+ ticks.tv_nsec = (timo % hz) * (1000000000/hz);
+ nanotime(&ts);
+ timespecadd(&ts, &ticks, &ts);
- if (rumpuser_cv_timedwait(ltsp->cv, rump_giantlock,
- ts.tv_sec, ts.tv_nsec) == 0)
- rv = 0;
- else
+ rv = rumpuser_cv_timedwait(lts.ucv, rump_giantlock,
+ ts.tv_sec, ts.tv_nsec);
+ }
+
+ if (rv != 0)
rv = EWOULDBLOCK;
} else {
- rumpuser_cv_wait(ltsp->cv, rump_giantlock);
+ if (kinterlock) {
+ cv_wait(<s.kcv, kinterlock);
+ } else {
+ rumpuser_cv_wait(lts.ucv, rump_giantlock);
+ }
rv = 0;
}
- LIST_REMOVE(ltsp, entries);
- rumpuser_cv_destroy(ltsp->cv);
- rump_kernel_ununlock_allbutone(nlocks);
+ rumpuser_mutex_enter_nowrap(qlock);
+ LIST_REMOVE(<s, entries);
+ rumpuser_mutex_exit(qlock);
+
+ if (kinterlock)
+ cv_destroy(<s.kcv);
+ else
+ rumpuser_cv_destroy(lts.ucv);
return rv;
}
@@ -97,16 +126,20 @@
ltsleep(wchan_t ident, pri_t prio, const char *wmesg, int timo,
volatile struct simplelock *slock)
{
- struct ltsleeper lts;
- int rv;
+ int rv, nlocks;
- lts.id = ident;
- rumpuser_cv_init(<s.cv);
-
+ /*
+ * Since we cannot use slock as the rumpuser interlock,
+ * require that everyone using this prehistoric interface
+ * is biglocked.
+ */
+ KASSERT(rump_kernel_isbiglocked());
if (slock)
simple_unlock(slock);
- rv = sleeper(<s, timo);
+ rump_kernel_unlock_allbutone(&nlocks);
+ rv = sleeper(ident, timo, NULL);
+ rump_kernel_ununlock_allbutone(nlocks);
if (slock && (prio & PNORELOCK) == 0)
simple_lock(slock);
@@ -118,45 +151,58 @@
mtsleep(wchan_t ident, pri_t prio, const char *wmesg, int timo,
kmutex_t *lock)
{
- struct ltsleeper lts;
int rv;
- lts.id = ident;
- rumpuser_cv_init(<s.cv);
-
- mutex_exit(lock);
-
- rv = sleeper(<s, timo);
-
- if ((prio & PNORELOCK) == 0)
- mutex_enter(lock);
+ rv = sleeper(ident, timo, lock);
+ if (prio & PNORELOCK)
+ mutex_exit(lock);
return rv;
}
static void
-do_wakeup(wchan_t ident, void (*wakeupfn)(struct rumpuser_cv *))
+do_wakeup(wchan_t ident, bool wakeup_all)
{
struct ltsleeper *ltsp;
- KASSERT(rump_kernel_isbiglocked());
+ rumpuser_mutex_enter_nowrap(qlock);
LIST_FOREACH(ltsp, &sleepers, entries) {
if (ltsp->id == ident) {
- wakeupfn(ltsp->cv);
+ if (wakeup_all) {
+ if (ltsp->iskwait) {
+ cv_broadcast(<sp->kcv);
+ } else {
+ rumpuser_cv_broadcast(ltsp->ucv);
+ }
+ } else {
+ if (ltsp->iskwait) {
+ cv_signal(<sp->kcv);
+ } else {
+ rumpuser_cv_signal(ltsp->ucv);
+ }
+ }
}
}
+ rumpuser_mutex_exit(qlock);
}
void
wakeup(wchan_t ident)
{
- do_wakeup(ident, rumpuser_cv_broadcast);
+ do_wakeup(ident, true);
}
void
wakeup_one(wchan_t ident)
{
- do_wakeup(ident, rumpuser_cv_signal);
+ do_wakeup(ident, false);
}
+
+void
+rump_tsleep_init()
+{
+
+ rumpuser_mutex_init(&qlock);
+}
diff -r 8f5b6621f9d3 -r f46aaf724dc1 sys/rump/librump/rumpkern/rump.c
--- a/sys/rump/librump/rumpkern/rump.c Mon May 31 23:13:17 2010 +0000
+++ b/sys/rump/librump/rumpkern/rump.c Mon May 31 23:18:33 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rump.c,v 1.172 2010/05/28 16:44:14 pooka Exp $ */
+/* $NetBSD: rump.c,v 1.173 2010/05/31 23:18:33 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.172 2010/05/28 16:44:14 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.173 2010/05/31 23:18:33 pooka Exp $");
#include <sys/systm.h>
#define ELFSIZE ARCH_ELFSIZE
@@ -265,6 +265,7 @@
rumpuser_thrinit(rump_user_schedule, rump_user_unschedule,
rump_threads);
rump_intr_init();
+ rump_tsleep_init();
/* init minimal lwp/cpu context */
l = &lwp0;
diff -r 8f5b6621f9d3 -r f46aaf724dc1 sys/rump/librump/rumpkern/rump_private.h
--- a/sys/rump/librump/rumpkern/rump_private.h Mon May 31 23:13:17 2010 +0000
+++ b/sys/rump/librump/rumpkern/rump_private.h Mon May 31 23:18:33 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rump_private.h,v 1.46 2010/05/18 15:16:10 pooka Exp $ */
+/* $NetBSD: rump_private.h,v 1.47 2010/05/31 23:18:33 pooka Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@@ -127,6 +127,8 @@
void rump_kernel_unlock_allbutone(int *);
void rump_kernel_ununlock_allbutone(int);
+void rump_tsleep_init(void);
+
void rump_intr_init(void);
void rump_softint_run(struct cpu_info *);
Home |
Main Index |
Thread Index |
Old Index