summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2004-07-20 20:15:14 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2004-07-20 20:15:14 +0000
commit2ffda532d68e2f976e0579af1ee163b2eac6e2a7 (patch)
treede15cf88073954aa6170c89423e279dc9ceee63d
parent95e0c0da10d0fb322b432d30519b677a8abb4720 (diff)
Introducing mutexes - cpu-owned spinning locks with spl semantics.
This is the MI (slightly inefficient and not MP safe) implementation. deraadt@ ok Tested by many. (this and following commits)
-rw-r--r--sys/conf/files3
-rw-r--r--sys/kern/subr_mutex.c82
-rw-r--r--sys/sys/mutex.h109
3 files changed, 193 insertions, 1 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 2afb58e8498..caf2d05e24d 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.309 2004/07/15 12:10:44 henning Exp $
+# $OpenBSD: files,v 1.310 2004/07/20 20:15:13 art Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -581,6 +581,7 @@ file kern/subr_disk.c
file kern/subr_evcount.c
file kern/subr_extent.c
file kern/subr_log.c
+file kern/subr_mutex.c
file kern/subr_pool.c
file kern/subr_prf.c
file kern/subr_prof.c
diff --git a/sys/kern/subr_mutex.c b/sys/kern/subr_mutex.c
new file mode 100644
index 00000000000..d4f397466ae
--- /dev/null
+++ b/sys/kern/subr_mutex.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+
+#ifndef __HAVE_MUTEX
+
+/*
+ * Single processor systems don't need any mutexes, but they need the spl
+ * raising semantics of the mutexes.
+ */
+void
+mtx_init1(struct mutex *mtx, int wantipl)
+{
+ mtx->mtx_oldipl = 0;
+ mtx->mtx_wantipl = wantipl;
+ mtx->mtx_lock = 0;
+}
+
+void
+mtx_enter(struct mutex *mtx)
+{
+#define UGLY(lc, uc) case MUTEX_IPL_##uc: mtx->mtx_oldipl = spl##lc(); break
+
+ switch (mtx->mtx_wantipl) {
+ UGLY(high, HIGH);
+ UGLY(statclock, STATCLOCK);
+#ifdef IPL_SCHED
+ UGLY(sched, SCHED);
+#endif
+ UGLY(clock, CLOCK);
+ UGLY(vm, VM);
+ UGLY(tty, TTY);
+ UGLY(net, NET);
+ UGLY(bio, BIO);
+ UGLY(softnet, SOFTNET);
+ UGLY(softclock, SOFTCLOCK);
+ case MUTEX_IPL_NONE:
+ break;
+ default:
+ panic("mtx_enter: ipl not implemented");
+ }
+#undef UGLY
+
+ MUTEX_ASSERT_UNLOCKED(mtx);
+ mtx->mtx_lock = 1;
+}
+
+void
+mtx_leave(struct mutex *mtx)
+{
+ MUTEX_ASSERT_LOCKED(mtx);
+ mtx->mtx_lock = 0;
+ if (mtx->mtx_wantipl != MUTEX_IPL_NONE)
+ splx(mtx->mtx_oldipl);
+}
+
+#endif
diff --git a/sys/sys/mutex.h b/sys/sys/mutex.h
new file mode 100644
index 00000000000..51e08d702d0
--- /dev/null
+++ b/sys/sys/mutex.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SYS_MUTEX_H_
+#define _SYS_MUTEX_H_
+
+/*
+ * A mutex is:
+ * - owned by a cpu.
+ * - non-recursive.
+ * - spinning.
+ * - not providing mutual exclusion between processes, only cpus.
+ * - providing interrupt blocking when necessary.
+ *
+ * Different mutexes can be nested, but not interleaved. This is ok:
+ * "mtx_enter(foo); mtx_enter(bar); mtx_leave(bar); mtx_leave(foo);"
+ * This is _not_ ok:
+ * "mtx_enter(foo); mtx_enter(bar); mtx_leave(foo); mtx_leave(bar);"
+ */
+
+#ifdef __HAVE_MUTEX
+#include <machine/mutex.h>
+#else
+
+/*
+ * Simple non-mp implementation.
+ */
+struct mutex {
+ int mtx_lock;
+ int mtx_wantipl;
+ int mtx_oldipl;
+};
+
+/*
+ * Since the alpha IPL levels are so messed up, we have to do magic to get
+ * this right.
+ */
+#define MUTEX_IPL(ipl) MUTEX_##ipl
+#define MUTEX_IPL_NONE 0
+#define MUTEX_IPL_SOFTSERIAL 1
+#define MUTEX_IPL_SOFTCLOCK 2
+#define MUTEX_IPL_SOFTNET 3
+#define MUTEX_IPL_NET 4
+#define MUTEX_IPL_BIO 5
+#define MUTEX_IPL_VM 6
+#define MUTEX_IPL_TTY 7
+#define MUTEX_IPL_SERIAL 8
+#define MUTEX_IPL_AUDIO 9
+#define MUTEX_IPL_CLOCK 10
+#define MUTEX_IPL_STATCLOCK 11
+#define MUTEX_IPL_SCHED 12
+#define MUTEX_IPL_HIGH 13
+
+void mtx_init1(struct mutex *, int);
+#define mtx_init(mtx, ipl) mtx_init1(mtx, MUTEX_##ipl)
+
+#define MUTEX_INITIALIZER(ipl) { 0, MUTEX_##ipl, 0 }
+
+#ifdef DIAGNOSTIC
+#define MUTEX_ASSERT_LOCKED(mtx) do { \
+ if ((mtx)->mtx_lock == 0) \
+ panic("mutex %p not held in %s\n", (mtx), __func__); \
+} while (0)
+
+#define MUTEX_ASSERT_UNLOCKED(mtx) do { \
+ if ((mtx)->mtx_lock != 0) \
+ panic("mutex %p held in %s\n", (mtx), __func__); \
+} while (0)
+#else
+#define MUTEX_ASSERT_LOCKED(mtx) do { } while (0)
+#define MUTEX_ASSERT_UNLOCKED(mtx) do { } while (0)
+#endif
+
+#define MUTEX_OLDIPL(mtx) (mtx)->mtx_oldipl
+
+#endif
+
+/*
+ * Some architectures need to do magic for the ipl, so they need a macro.
+ */
+#ifndef mtx_init
+void mtx_init(struct mutex *, int);
+#endif
+void mtx_enter(struct mutex *);
+void mtx_leave(struct mutex *);
+
+#endif