diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2004-07-20 20:15:14 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2004-07-20 20:15:14 +0000 |
commit | 2ffda532d68e2f976e0579af1ee163b2eac6e2a7 (patch) | |
tree | de15cf88073954aa6170c89423e279dc9ceee63d | |
parent | 95e0c0da10d0fb322b432d30519b677a8abb4720 (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/files | 3 | ||||
-rw-r--r-- | sys/kern/subr_mutex.c | 82 | ||||
-rw-r--r-- | sys/sys/mutex.h | 109 |
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 |