diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-09-07 19:29:34 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-09-07 19:29:34 +0000 |
commit | 2559f0f996d958efae67fce20173accdceaa876d (patch) | |
tree | befab5157985f02a0deeede0514d309e7926f3b1 /sys/arch/macppc | |
parent | 83a9b83217e3e27c960e51da4254a5d5b694838d (diff) |
Sync mplock code with the current paradigm used in all other MP platforms.
macppc was left unchanged by mistake.
Diffstat (limited to 'sys/arch/macppc')
-rw-r--r-- | sys/arch/macppc/conf/files.macppc | 3 | ||||
-rw-r--r-- | sys/arch/macppc/include/mplock.h | 161 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/lock_machdep.c | 173 |
3 files changed, 186 insertions, 151 deletions
diff --git a/sys/arch/macppc/conf/files.macppc b/sys/arch/macppc/conf/files.macppc index 814bd305cb4..9f2c6d29f01 100644 --- a/sys/arch/macppc/conf/files.macppc +++ b/sys/arch/macppc/conf/files.macppc @@ -1,4 +1,4 @@ -# $OpenBSD: files.macppc,v 1.60 2009/05/03 21:30:09 kettenis Exp $ +# $OpenBSD: files.macppc,v 1.61 2009/09/07 19:29:29 miod Exp $ # # macppc-specific configuration info @@ -11,6 +11,7 @@ file arch/macppc/macppc/autoconf.c file arch/macppc/macppc/clock.c file arch/macppc/macppc/conf.c file arch/macppc/macppc/disksubr.c disk +file arch/macppc/macppc/lock_machdep.c multiprocessor file arch/macppc/macppc/machdep.c file arch/macppc/macppc/wscons_machdep.c file arch/macppc/macppc/mem.c diff --git a/sys/arch/macppc/include/mplock.h b/sys/arch/macppc/include/mplock.h index 8f87c895aae..e288efadad7 100644 --- a/sys/arch/macppc/include/mplock.h +++ b/sys/arch/macppc/include/mplock.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mplock.h,v 1.1 2007/11/26 17:15:29 art Exp $ */ +/* $OpenBSD: mplock.h,v 1.2 2009/09/07 19:29:33 miod Exp $ */ /* * Copyright (c) 2004 Niklas Hallqvist. All rights reserved. @@ -33,159 +33,20 @@ */ struct __mp_lock { - __cpu_simple_lock_t mpl_lock; - cpuid_t mpl_cpu; - int mpl_count; + volatile struct cpu_info *mpl_cpu; + volatile long mpl_count; }; -static __inline void -__mp_lock_init(struct __mp_lock *lock) -{ - __cpu_simple_lock_init(&lock->mpl_lock); - lock->mpl_cpu = LK_NOCPU; - lock->mpl_count = 0; -} +#ifndef _LOCORE -#if defined(MP_LOCKDEBUG) -#ifndef DDB -#error "MP_LOCKDEBUG requires DDB" -#endif - -extern void Debugger(void); -extern int db_printf(const char *, ...) - __attribute__((__format__(__kprintf__,1,2))); - -/* CPU-dependent timing, needs this to be settable from ddb. */ -extern int __mp_lock_spinout; -#endif - -static __inline void -__mp_lock(struct __mp_lock *lock) -{ - int s = spllock(); - - if (lock->mpl_cpu != cpu_number()) { -#ifndef MP_LOCKDEBUG - __cpu_simple_lock(&lock->mpl_lock); -#else - { - int got_it; - do { - int ticks = __mp_lock_spinout; - - do { - got_it = __cpu_simple_lock_try( - &lock->mpl_lock); - } while (!got_it && ticks-- > 0); - if (!got_it) { - db_printf( - "__mp_lock(0x%x): lock spun out", - lock); - Debugger(); - } - } while (!got_it); - } -#endif - lock->mpl_cpu = cpu_number(); - } - lock->mpl_count++; - splx(s); -} - -/* - * Try to acquire the lock, if another cpu has it, fill it in the - * call-by-reference cpu parameter. Return true if acquired. - */ -static __inline int -__mp_lock_try(struct __mp_lock *lock, cpuid_t *cpu) -{ - int s = spllock(); - - if (lock->mpl_cpu != cpu_number()) { - if (!__cpu_simple_lock_try(&lock->mpl_lock)) { - *cpu = lock->mpl_cpu; - splx(s); - return 0; - } - lock->mpl_cpu = cpu_number(); - } - lock->mpl_count++; - splx(s); - return 1; -} - -static __inline void -__mp_unlock(struct __mp_lock *lock) -{ - int s = spllock(); +void __mp_lock_init(struct __mp_lock *); +void __mp_lock(struct __mp_lock *); +void __mp_unlock(struct __mp_lock *); +int __mp_release_all(struct __mp_lock *); +int __mp_release_all_but_one(struct __mp_lock *); +void __mp_acquire_count(struct __mp_lock *, int); +int __mp_lock_held(struct __mp_lock *); -#ifdef MP_LOCKDEBUG - if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) { - db_printf("__mp_unlock(0x%x): releasing not locked lock\n", - lock); - Debugger(); - } #endif - if (--lock->mpl_count == 0) { - lock->mpl_cpu = LK_NOCPU; - __cpu_simple_unlock(&lock->mpl_lock); - } - splx(s); -} - -static __inline int -__mp_release_all(struct __mp_lock *lock) { - int s = spllock(); - int rv = lock->mpl_count; - -#ifdef MP_LOCKDEBUG - if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) { - db_printf( - "__mp_release_all(0x%x): releasing not locked lock\n", - lock); - Debugger(); - } -#endif - - lock->mpl_cpu = LK_NOCPU; - lock->mpl_count = 0; - __cpu_simple_unlock(&lock->mpl_lock); - splx(s); - return (rv); -} - -static __inline int -__mp_release_all_but_one(struct __mp_lock *lock) { - int s = spllock(); - int rv = lock->mpl_count - 1; - -#ifdef MP_LOCKDEBUG - if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) { - db_printf( - "__mp_release_all_but_one(0x%x): releasing not locked lock\n", - lock); - Debugger(); - } -#endif - - lock->mpl_count = 1; - splx(s); - return (rv); -} - -static __inline void -__mp_acquire_count(struct __mp_lock *lock, int count) { - int s = spllock(); - - while (count--) - __mp_lock(lock); - splx(s); -} - -static __inline int -__mp_lock_held(struct __mp_lock *lock) { - return lock->mpl_count && lock->mpl_cpu == cpu_number(); -} - #endif /* !_MACHINE_MPLOCK_H */ diff --git a/sys/arch/macppc/macppc/lock_machdep.c b/sys/arch/macppc/macppc/lock_machdep.c new file mode 100644 index 00000000000..e8697fdb31b --- /dev/null +++ b/sys/arch/macppc/macppc/lock_machdep.c @@ -0,0 +1,173 @@ +/* $OpenBSD: lock_machdep.c,v 1.1 2009/09/07 19:29:33 miod Exp $ */ + +/* + * Copyright (c) 2007 Artur Grabowski <art@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#include <sys/param.h> +#include <sys/lock.h> +#include <sys/systm.h> + +#include <machine/atomic.h> +#include <machine/lock.h> +#include <machine/psl.h> + +#include <ddb/db_output.h> + +void +__mp_lock_init(struct __mp_lock *lock) +{ + lock->mpl_cpu = NULL; + lock->mpl_count = 0; +} + +#if defined(MP_LOCKDEBUG) +#ifndef DDB +#error "MP_LOCKDEBUG requires DDB" +#endif + +/* CPU-dependent timing, needs this to be settable from ddb. */ +extern int __mp_lock_spinout; +#endif + +#define SPINLOCK_SPIN_HOOK /**/ + +static __inline void +__mp_lock_spin(struct __mp_lock *mpl) +{ +#ifndef MP_LOCKDEBUG + while (mpl->mpl_count != 0) + SPINLOCK_SPIN_HOOK; +#else + int ticks = __mp_lock_spinout; + + while (mpl->mpl_count != 0 && ticks-- > 0) + SPINLOCK_SPIN_HOOK; + + if (ticks == 0) { + db_printf("__mp_lock(0x%x): lock spun out", mpl); + Debugger(); + } +#endif +} + +void +__mp_lock(struct __mp_lock *mpl) +{ + /* + * Please notice that mpl_count gets incremented twice for the + * first lock. This is on purpose. The way we release the lock + * in mp_unlock is to decrement the mpl_count and then check if + * the lock should be released. Since mpl_count is what we're + * spinning on, decrementing it in mpl_unlock to 0 means that + * we can't clear mpl_cpu, because we're no longer holding the + * lock. In theory mpl_cpu doesn't need to be cleared, but it's + * safer to clear it and besides, setting mpl_count to 2 on the + * first lock makes most of this code much simpler. + */ + + while (1) { + int s; + + s = ppc_intr_disable(); + if (__cpu_cas(&mpl->mpl_count, 0, 1) == 0) { + __asm __volatile("eieio" ::: "memory"); + mpl->mpl_cpu = curcpu(); + } + + if (mpl->mpl_cpu == curcpu()) { + mpl->mpl_count++; + ppc_intr_enable(s); + break; + } + ppc_intr_enable(s); + + __mp_lock_spin(mpl); + } +} + +void +__mp_unlock(struct __mp_lock *mpl) +{ + int s; + +#ifdef MP_LOCKDEBUG + if (mpl->mpl_cpu != curcpu()) { + db_printf("__mp_unlock(%p): not held lock\n", mpl); + Debugger(); + } +#endif + + s = ppc_intr_disable(); + if (--mpl->mpl_count == 1) { + mpl->mpl_cpu = NULL; + __asm __volatile("eieio" ::: "memory"); + mpl->mpl_count = 0; + } + ppc_intr_enable(s); +} + +int +__mp_release_all(struct __mp_lock *mpl) +{ + int rv = mpl->mpl_count - 1; + int s; + +#ifdef MP_LOCKDEBUG + if (mpl->mpl_cpu != curcpu()) { + db_printf("__mp_release_all(%p): not held lock\n", mpl); + Debugger(); + } +#endif + + s = ppc_intr_disable(); + mpl->mpl_cpu = NULL; + __asm __volatile("eieio" ::: "memory"); + mpl->mpl_count = 0; + ppc_intr_enable(s); + + return (rv); +} + +int +__mp_release_all_but_one(struct __mp_lock *mpl) +{ + int rv = mpl->mpl_count - 2; + +#ifdef MP_LOCKDEBUG + if (mpl->mpl_cpu != curcpu()) { + db_printf("__mp_release_all_but_one(%p): not held lock\n", mpl); + Debugger(); + } +#endif + + mpl->mpl_count = 2; + + return (rv); +} + +void +__mp_acquire_count(struct __mp_lock *mpl, int count) +{ + while (count--) + __mp_lock(mpl); +} + +int +__mp_lock_held(struct __mp_lock *mpl) +{ + return mpl->mpl_cpu == curcpu(); +} |