Annotation of sys/sys/mplock.h, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: mplock.h,v 1.8 2005/06/17 22:33:34 niklas Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2004 Niklas Hallqvist. All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27: #ifndef _MPLOCK_H_
! 28: #define _MPLOCK_H_
! 29:
! 30: /*
! 31: * Really simple spinlock implementation with recursive capabilities.
! 32: * Correctness is paramount, no fancyness allowed.
! 33: */
! 34:
! 35: struct __mp_lock {
! 36: __cpu_simple_lock_t mpl_lock;
! 37: cpuid_t mpl_cpu;
! 38: int mpl_count;
! 39: };
! 40:
! 41: static __inline void __mp_lock_init(struct __mp_lock *);
! 42: static __inline void __mp_lock(struct __mp_lock *);
! 43: static __inline void __mp_unlock(struct __mp_lock *);
! 44: static __inline int __mp_release_all(struct __mp_lock *);
! 45: static __inline void __mp_acquire_count(struct __mp_lock *, int);
! 46: static __inline int __mp_lock_held(struct __mp_lock *);
! 47:
! 48: /*
! 49: * XXX Simplelocks macros used at "trusted" places.
! 50: */
! 51: #define SIMPLELOCK __mp_lock
! 52: #define SIMPLE_LOCK_INIT __mp_lock_init
! 53: #define SIMPLE_LOCK __mp_lock
! 54: #define SIMPLE_UNLOCK __mp_unlock
! 55:
! 56: static __inline void
! 57: __mp_lock_init(struct __mp_lock *lock)
! 58: {
! 59: __cpu_simple_lock_init(&lock->mpl_lock);
! 60: lock->mpl_cpu = LK_NOCPU;
! 61: lock->mpl_count = 0;
! 62: }
! 63:
! 64: #if defined(MP_LOCKDEBUG)
! 65: #ifndef DDB
! 66: #error "MP_LOCKDEBUG requires DDB"
! 67: #endif
! 68:
! 69: extern void Debugger(void);
! 70: extern int db_printf(const char *, ...)
! 71: __attribute__((__format__(__kprintf__,1,2)));
! 72:
! 73: /* CPU-dependent timing, needs this to be settable from ddb. */
! 74: extern int __mp_lock_spinout;
! 75: #endif
! 76:
! 77: static __inline void
! 78: __mp_lock(struct __mp_lock *lock)
! 79: {
! 80: int s = spllock();
! 81:
! 82: if (lock->mpl_cpu != cpu_number()) {
! 83: #ifndef MP_LOCKDEBUG
! 84: __cpu_simple_lock(&lock->mpl_lock);
! 85: #else
! 86: {
! 87: int got_it;
! 88: do {
! 89: int ticks = __mp_lock_spinout;
! 90:
! 91: do {
! 92: got_it = __cpu_simple_lock_try(
! 93: &lock->mpl_lock);
! 94: } while (!got_it && ticks-- > 0);
! 95: if (!got_it) {
! 96: db_printf(
! 97: "__mp_lock(0x%x): lock spun out",
! 98: lock);
! 99: Debugger();
! 100: }
! 101: } while (!got_it);
! 102: }
! 103: #endif
! 104: lock->mpl_cpu = cpu_number();
! 105: }
! 106: lock->mpl_count++;
! 107: splx(s);
! 108: }
! 109:
! 110: /*
! 111: * Try to acquire the lock, if another cpu has it, fill it in the
! 112: * call-by-reference cpu parameter. Return true if acquired.
! 113: */
! 114: static __inline int
! 115: __mp_lock_try(struct __mp_lock *lock, cpuid_t *cpu)
! 116: {
! 117: int s = spllock();
! 118:
! 119: if (lock->mpl_cpu != cpu_number()) {
! 120: if (!__cpu_simple_lock_try(&lock->mpl_lock)) {
! 121: *cpu = lock->mpl_cpu;
! 122: splx(s);
! 123: return 0;
! 124: }
! 125: lock->mpl_cpu = cpu_number();
! 126: }
! 127: lock->mpl_count++;
! 128: splx(s);
! 129: return 1;
! 130: }
! 131:
! 132: static __inline void
! 133: __mp_unlock(struct __mp_lock *lock)
! 134: {
! 135: int s = spllock();
! 136:
! 137: #ifdef MP_LOCKDEBUG
! 138: if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
! 139: db_printf("__mp_unlock(0x%x): releasing not locked lock\n",
! 140: lock);
! 141: Debugger();
! 142: }
! 143: #endif
! 144:
! 145: if (--lock->mpl_count == 0) {
! 146: lock->mpl_cpu = LK_NOCPU;
! 147: __cpu_simple_unlock(&lock->mpl_lock);
! 148: }
! 149: splx(s);
! 150: }
! 151:
! 152: static __inline int
! 153: __mp_release_all(struct __mp_lock *lock) {
! 154: int s = spllock();
! 155: int rv = lock->mpl_count;
! 156:
! 157: #ifdef MP_LOCKDEBUG
! 158: if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
! 159: db_printf(
! 160: "__mp_release_all(0x%x): releasing not locked lock\n",
! 161: lock);
! 162: Debugger();
! 163: }
! 164: #endif
! 165:
! 166: lock->mpl_cpu = LK_NOCPU;
! 167: lock->mpl_count = 0;
! 168: __cpu_simple_unlock(&lock->mpl_lock);
! 169: splx(s);
! 170: return (rv);
! 171: }
! 172:
! 173: static __inline int
! 174: __mp_release_all_but_one(struct __mp_lock *lock) {
! 175: int s = spllock();
! 176: int rv = lock->mpl_count - 1;
! 177:
! 178: #ifdef MP_LOCKDEBUG
! 179: if (lock->mpl_count == 0 || lock->mpl_cpu == LK_NOCPU) {
! 180: db_printf(
! 181: "__mp_release_all_but_one(0x%x): releasing not locked lock\n",
! 182: lock);
! 183: Debugger();
! 184: }
! 185: #endif
! 186:
! 187: lock->mpl_count = 1;
! 188: splx(s);
! 189: return (rv);
! 190: }
! 191:
! 192: static __inline void
! 193: __mp_acquire_count(struct __mp_lock *lock, int count) {
! 194: int s = spllock();
! 195:
! 196: while (count--)
! 197: __mp_lock(lock);
! 198: splx(s);
! 199: }
! 200:
! 201: static __inline int
! 202: __mp_lock_held(struct __mp_lock *lock) {
! 203: return lock->mpl_count && lock->mpl_cpu == cpu_number();
! 204: }
! 205:
! 206: extern struct __mp_lock kernel_lock;
! 207:
! 208: #endif /* !_MPLOCK_H */
CVSweb