[BACK]Return to mplock.h CVS log [TXT][DIR] Up to [local] / sys / sys

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