Index: kern/kern_mutex.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_mutex.c,v retrieving revision 1.33 diff -u -r1.33 kern_mutex.c --- kern/kern_mutex.c 2001/01/20 02:30:58 1.33 +++ kern/kern_mutex.c 2001/01/20 04:10:05 @@ -228,6 +228,109 @@ } } +/* + * Default, unoptimized mutex micro-operations + */ + +#ifndef _obtain_lock +/* Actually obtain mtx_lock */ +#define _obtain_lock(mp, tid) \ + atomic_cmpset_acq_ptr(&(mp)->mtx_lock, (void *)MTX_UNOWNED, (tid)) +#endif + +#ifndef _release_lock +/* Actually release mtx_lock */ +#define _release_lock(mp, tid) \ + atomic_cmpset_rel_ptr(&(mp)->mtx_lock, (tid), (void *)MTX_UNOWNED) +#endif + +#ifndef _release_lock_quick +/* Actually release mtx_lock quickly assuming that we own it */ +#define _release_lock_quick(mp) \ + atomic_store_rel_ptr(&(mp)->mtx_lock, (void *)MTX_UNOWNED) +#endif + +#ifndef _getlock_sleep +/* Get a sleep lock, deal with recursion inline. */ +#define _getlock_sleep(mp, tid, type) do { \ + if (!_obtain_lock(mp, tid)) { \ + if (((mp)->mtx_lock & MTX_FLAGMASK) != ((uintptr_t)(tid)))\ + mtx_enter_hard(mp, (type) & MTX_HARDOPTS, 0); \ + else { \ + atomic_set_ptr(&(mp)->mtx_lock, MTX_RECURSED); \ + (mp)->mtx_recurse++; \ + } \ + } \ +} while (0) +#endif + +#ifndef _getlock_spin_block +/* Get a spin lock, handle recursion inline (as the less common case) */ +#define _getlock_spin_block(mp, tid, type) do { \ + u_int _mtx_intr = save_intr(); \ + disable_intr(); \ + if (!_obtain_lock(mp, tid)) \ + mtx_enter_hard(mp, (type) & MTX_HARDOPTS, _mtx_intr); \ + else \ + (mp)->mtx_saveintr = _mtx_intr; \ +} while (0) +#endif + +#ifndef _getlock_norecurse +/* + * Get a lock without any recursion handling. Calls the hard enter function if + * we can't get it inline. + */ +#define _getlock_norecurse(mp, tid, type) do { \ + if (!_obtain_lock(mp, tid)) \ + mtx_enter_hard((mp), (type) & MTX_HARDOPTS, 0); \ +} while (0) +#endif + +#ifndef _exitlock_norecurse +/* + * Release a sleep lock assuming we haven't recursed on it, recursion is handled + * in the hard function. + */ +#define _exitlock_norecurse(mp, tid, type) do { \ + if (!_release_lock(mp, tid)) \ + mtx_exit_hard((mp), (type) & MTX_HARDOPTS); \ +} while (0) +#endif + +#ifndef _exitlock +/* + * Release a sleep lock when its likely we recursed (the code to + * deal with simple recursion is inline). + */ +#define _exitlock(mp, tid, type) do { \ + if (!_release_lock(mp, tid)) { \ + if ((mp)->mtx_lock & MTX_RECURSED) { \ + if (--((mp)->mtx_recurse) == 0) \ + atomic_clear_ptr(&(mp)->mtx_lock, \ + MTX_RECURSED); \ + } else { \ + mtx_exit_hard((mp), (type) & MTX_HARDOPTS); \ + } \ + } \ +} while (0) +#endif + +#ifndef _exitlock_spin +/* Release a spin lock (with possible recursion). */ +#define _exitlock_spin(mp) do { \ + if (!mtx_recursed((mp))) { \ + int _mtx_intr = (mp)->mtx_saveintr; \ + \ + _release_lock_quick(mp); \ + restore_intr(_mtx_intr); \ + } else { \ + (mp)->mtx_recurse--; \ + } \ +} while (0) +#endif + + void mtx_enter_hard(struct mtx *m, int type, int saveintr) { @@ -506,6 +609,156 @@ panic("mtx_exit_hard: unsupported type 0x%x\n", type); } } + +/* HERE */ + + +/* Common strings */ +char STR_mtx_enter_fmt[] = "GOT %s [%p] r=%d at %s:%d"; +char STR_mtx_exit_fmt[] = "REL %s [%p] r=%d at %s:%d"; +char STR_mtx_try_enter_fmt[] = "TRY_ENTER %s [%p] result=%d at %s:%d"; +char STR_mtx_bad_type[] = "((type) & (MTX_NORECURSE | MTX_NOSWITCH)) == 0"; +char STR_mtx_owned[] = "mtx_owned(mpp)"; +char STR_mtx_recurse[] = "mpp->mtx_recurse == 0"; + +/* + * Get lock 'm', the macro handles the easy (and most common cases) and leaves + * the slow stuff to the mtx_enter_hard() function. + * + * Note: since type is usually a constant much of this code is optimized out. + */ +void +_mtx_enter(struct mtx *mtxp, int type, const char *file, int line) +{ + struct mtx *mpp = mtxp; + + /* bits only valid on mtx_exit() */ + MPASS4(((type) & (MTX_NORECURSE | MTX_NOSWITCH)) == 0, + STR_mtx_bad_type, file, line); + + if ((type) & MTX_SPIN) { + /* + * Easy cases of spin locks: + * + * 1) We already own the lock and will simply recurse on it (if + * RLIKELY) + * + * 2) The lock is free, we just get it + */ + if ((type) & MTX_RLIKELY) { + /* + * Check for recursion, if we already have this + * lock we just bump the recursion count. + */ + if (mpp->mtx_lock == (uintptr_t)CURTHD) { + mpp->mtx_recurse++; + goto done; + } + } + + if (((type) & MTX_TOPHALF) == 0) { + /* + * If an interrupt thread uses this we must block + * interrupts here. + */ + if ((type) & MTX_FIRST) { + ASS_IEN; + disable_intr(); + _getlock_norecurse(mpp, CURTHD, + (type) & MTX_HARDOPTS); + } else { + _getlock_spin_block(mpp, CURTHD, + (type) & MTX_HARDOPTS); + } + } else + _getlock_norecurse(mpp, CURTHD, (type) & MTX_HARDOPTS); + } else { + /* Sleep locks */ + if ((type) & MTX_RLIKELY) + _getlock_sleep(mpp, CURTHD, (type) & MTX_HARDOPTS); + else + _getlock_norecurse(mpp, CURTHD, (type) & MTX_HARDOPTS); + } +done: + WITNESS_ENTER(mpp, type, file, line); + if (((type) & MTX_QUIET) == 0) + CTR5(KTR_LOCK, STR_mtx_enter_fmt, + mpp->mtx_description, mpp, mpp->mtx_recurse, file, line); + +} + +/* + * Attempt to get MTX_DEF lock, return non-zero if lock acquired. + * + * XXX DOES NOT HANDLE RECURSION + */ +int +_mtx_try_enter(struct mtx *mtxp, int type, const char *file, int line) +{ + struct mtx *const mpp = mtxp; + int rval; + + rval = _obtain_lock(mpp, CURTHD); +#ifdef WITNESS + if (rval && mpp->mtx_witness != NULL) { + MPASS(mpp->mtx_recurse == 0); + witness_try_enter(mpp, type, file, line); + } +#endif /* WITNESS */ + if (((type) & MTX_QUIET) == 0) + CTR5(KTR_LOCK, STR_mtx_try_enter_fmt, + mpp->mtx_description, mpp, rval, file, line); + + return rval; +} + +/* + * Release lock m. + */ +void +_mtx_exit(struct mtx *mtxp, int type, const char *file, int line) +{ + struct mtx *const mpp = mtxp; + + MPASS4(mtx_owned(mpp), STR_mtx_owned, file, line); + WITNESS_EXIT(mpp, type, file, line); + if (((type) & MTX_QUIET) == 0) + CTR5(KTR_LOCK, STR_mtx_exit_fmt, + mpp->mtx_description, mpp, mpp->mtx_recurse, file, line); + if ((type) & MTX_SPIN) { + if ((type) & MTX_NORECURSE) { + int mtx_intr = mpp->mtx_saveintr; + + MPASS4(mpp->mtx_recurse == 0, STR_mtx_recurse, + file, line); + _release_lock_quick(mpp); + if (((type) & MTX_TOPHALF) == 0) { + if ((type) & MTX_FIRST) { + ASS_IDIS; + enable_intr(); + } else + restore_intr(mtx_intr); + } + } else { + if (((type & MTX_TOPHALF) == 0) && + (type & MTX_FIRST)) { + ASS_IDIS; + ASS_SIEN(mpp); + } + _exitlock_spin(mpp); + } + } else { + /* Handle sleep locks */ + if ((type) & MTX_RLIKELY) + _exitlock(mpp, CURTHD, (type) & MTX_HARDOPTS); + else { + _exitlock_norecurse(mpp, CURTHD, + (type) & MTX_HARDOPTS); + } + } +} + +/* END */ #define MV_DESTROY 0 /* validate before destory */ #define MV_INIT 1 /* validate before init */ Index: sys/mutex.h =================================================================== RCS file: /home/ncvs/src/sys/sys/mutex.h,v retrieving revision 1.17 diff -u -r1.17 mutex.h --- sys/mutex.h 2001/01/19 01:59:14 1.17 +++ sys/mutex.h 2001/01/20 04:10:05 @@ -143,11 +143,9 @@ * Wrap the following functions with cpp macros so that filenames and line * numbers are embedded in the code correctly. */ -#if (defined(KLD_MODULE) || defined(_KERN_MUTEX_C_)) void _mtx_enter(struct mtx *mtxp, int type, const char *file, int line); int _mtx_try_enter(struct mtx *mtxp, int type, const char *file, int line); void _mtx_exit(struct mtx *mtxp, int type, const char *file, int line); -#endif #define mtx_enter(mtxp, type) \ _mtx_enter((mtxp), (type), __FILE__, __LINE__) @@ -333,108 +331,6 @@ #define _V(x) __STRING(x) /* - * Default, unoptimized mutex micro-operations - */ - -#ifndef _obtain_lock -/* Actually obtain mtx_lock */ -#define _obtain_lock(mp, tid) \ - atomic_cmpset_acq_ptr(&(mp)->mtx_lock, (void *)MTX_UNOWNED, (tid)) -#endif - -#ifndef _release_lock -/* Actually release mtx_lock */ -#define _release_lock(mp, tid) \ - atomic_cmpset_rel_ptr(&(mp)->mtx_lock, (tid), (void *)MTX_UNOWNED) -#endif - -#ifndef _release_lock_quick -/* Actually release mtx_lock quickly assuming that we own it */ -#define _release_lock_quick(mp) \ - atomic_store_rel_ptr(&(mp)->mtx_lock, (void *)MTX_UNOWNED) -#endif - -#ifndef _getlock_sleep -/* Get a sleep lock, deal with recursion inline. */ -#define _getlock_sleep(mp, tid, type) do { \ - if (!_obtain_lock(mp, tid)) { \ - if (((mp)->mtx_lock & MTX_FLAGMASK) != ((uintptr_t)(tid)))\ - mtx_enter_hard(mp, (type) & MTX_HARDOPTS, 0); \ - else { \ - atomic_set_ptr(&(mp)->mtx_lock, MTX_RECURSED); \ - (mp)->mtx_recurse++; \ - } \ - } \ -} while (0) -#endif - -#ifndef _getlock_spin_block -/* Get a spin lock, handle recursion inline (as the less common case) */ -#define _getlock_spin_block(mp, tid, type) do { \ - u_int _mtx_intr = save_intr(); \ - disable_intr(); \ - if (!_obtain_lock(mp, tid)) \ - mtx_enter_hard(mp, (type) & MTX_HARDOPTS, _mtx_intr); \ - else \ - (mp)->mtx_saveintr = _mtx_intr; \ -} while (0) -#endif - -#ifndef _getlock_norecurse -/* - * Get a lock without any recursion handling. Calls the hard enter function if - * we can't get it inline. - */ -#define _getlock_norecurse(mp, tid, type) do { \ - if (!_obtain_lock(mp, tid)) \ - mtx_enter_hard((mp), (type) & MTX_HARDOPTS, 0); \ -} while (0) -#endif - -#ifndef _exitlock_norecurse -/* - * Release a sleep lock assuming we haven't recursed on it, recursion is handled - * in the hard function. - */ -#define _exitlock_norecurse(mp, tid, type) do { \ - if (!_release_lock(mp, tid)) \ - mtx_exit_hard((mp), (type) & MTX_HARDOPTS); \ -} while (0) -#endif - -#ifndef _exitlock -/* - * Release a sleep lock when its likely we recursed (the code to - * deal with simple recursion is inline). - */ -#define _exitlock(mp, tid, type) do { \ - if (!_release_lock(mp, tid)) { \ - if ((mp)->mtx_lock & MTX_RECURSED) { \ - if (--((mp)->mtx_recurse) == 0) \ - atomic_clear_ptr(&(mp)->mtx_lock, \ - MTX_RECURSED); \ - } else { \ - mtx_exit_hard((mp), (type) & MTX_HARDOPTS); \ - } \ - } \ -} while (0) -#endif - -#ifndef _exitlock_spin -/* Release a spin lock (with possible recursion). */ -#define _exitlock_spin(mp) do { \ - if (!mtx_recursed((mp))) { \ - int _mtx_intr = (mp)->mtx_saveintr; \ - \ - _release_lock_quick(mp); \ - restore_intr(_mtx_intr); \ - } else { \ - (mp)->mtx_recurse--; \ - } \ -} while (0) -#endif - -/* * Externally visible mutex functions. *------------------------------------------------------------------------------ */ @@ -450,161 +346,12 @@ #define mtx_recursed(m) ((m)->mtx_recurse != 0) /* Common strings */ -#ifdef _KERN_MUTEX_C_ -char STR_mtx_enter_fmt[] = "GOT %s [%p] r=%d at %s:%d"; -char STR_mtx_exit_fmt[] = "REL %s [%p] r=%d at %s:%d"; -char STR_mtx_try_enter_fmt[] = "TRY_ENTER %s [%p] result=%d at %s:%d"; -char STR_mtx_bad_type[] = "((type) & (MTX_NORECURSE | MTX_NOSWITCH)) == 0"; -char STR_mtx_owned[] = "mtx_owned(mpp)"; -char STR_mtx_recurse[] = "mpp->mtx_recurse == 0"; -#else /* _KERN_MUTEX_C_ */ extern char STR_mtx_enter_fmt[]; extern char STR_mtx_bad_type[]; extern char STR_mtx_exit_fmt[]; extern char STR_mtx_owned[]; extern char STR_mtx_recurse[]; extern char STR_mtx_try_enter_fmt[]; -#endif /* _KERN_MUTEX_C_ */ - -#ifndef KLD_MODULE -/* - * Get lock 'm', the macro handles the easy (and most common cases) and leaves - * the slow stuff to the mtx_enter_hard() function. - * - * Note: since type is usually a constant much of this code is optimized out. - */ -_MTX_INLINE void -_mtx_enter(struct mtx *mtxp, int type, const char *file, int line) -{ - struct mtx *mpp = mtxp; - - /* bits only valid on mtx_exit() */ - MPASS4(((type) & (MTX_NORECURSE | MTX_NOSWITCH)) == 0, - STR_mtx_bad_type, file, line); - - if ((type) & MTX_SPIN) { - /* - * Easy cases of spin locks: - * - * 1) We already own the lock and will simply recurse on it (if - * RLIKELY) - * - * 2) The lock is free, we just get it - */ - if ((type) & MTX_RLIKELY) { - /* - * Check for recursion, if we already have this - * lock we just bump the recursion count. - */ - if (mpp->mtx_lock == (uintptr_t)CURTHD) { - mpp->mtx_recurse++; - goto done; - } - } - - if (((type) & MTX_TOPHALF) == 0) { - /* - * If an interrupt thread uses this we must block - * interrupts here. - */ - if ((type) & MTX_FIRST) { - ASS_IEN; - disable_intr(); - _getlock_norecurse(mpp, CURTHD, - (type) & MTX_HARDOPTS); - } else { - _getlock_spin_block(mpp, CURTHD, - (type) & MTX_HARDOPTS); - } - } else - _getlock_norecurse(mpp, CURTHD, (type) & MTX_HARDOPTS); - } else { - /* Sleep locks */ - if ((type) & MTX_RLIKELY) - _getlock_sleep(mpp, CURTHD, (type) & MTX_HARDOPTS); - else - _getlock_norecurse(mpp, CURTHD, (type) & MTX_HARDOPTS); - } -done: - WITNESS_ENTER(mpp, type, file, line); - if (((type) & MTX_QUIET) == 0) - CTR5(KTR_LOCK, STR_mtx_enter_fmt, - mpp->mtx_description, mpp, mpp->mtx_recurse, file, line); - -} - -/* - * Attempt to get MTX_DEF lock, return non-zero if lock acquired. - * - * XXX DOES NOT HANDLE RECURSION - */ -_MTX_INLINE int -_mtx_try_enter(struct mtx *mtxp, int type, const char *file, int line) -{ - struct mtx *const mpp = mtxp; - int rval; - - rval = _obtain_lock(mpp, CURTHD); -#ifdef WITNESS - if (rval && mpp->mtx_witness != NULL) { - MPASS(mpp->mtx_recurse == 0); - witness_try_enter(mpp, type, file, line); - } -#endif /* WITNESS */ - if (((type) & MTX_QUIET) == 0) - CTR5(KTR_LOCK, STR_mtx_try_enter_fmt, - mpp->mtx_description, mpp, rval, file, line); - - return rval; -} - -/* - * Release lock m. - */ -_MTX_INLINE void -_mtx_exit(struct mtx *mtxp, int type, const char *file, int line) -{ - struct mtx *const mpp = mtxp; - - MPASS4(mtx_owned(mpp), STR_mtx_owned, file, line); - WITNESS_EXIT(mpp, type, file, line); - if (((type) & MTX_QUIET) == 0) - CTR5(KTR_LOCK, STR_mtx_exit_fmt, - mpp->mtx_description, mpp, mpp->mtx_recurse, file, line); - if ((type) & MTX_SPIN) { - if ((type) & MTX_NORECURSE) { - int mtx_intr = mpp->mtx_saveintr; - - MPASS4(mpp->mtx_recurse == 0, STR_mtx_recurse, - file, line); - _release_lock_quick(mpp); - if (((type) & MTX_TOPHALF) == 0) { - if ((type) & MTX_FIRST) { - ASS_IDIS; - enable_intr(); - } else - restore_intr(mtx_intr); - } - } else { - if (((type & MTX_TOPHALF) == 0) && - (type & MTX_FIRST)) { - ASS_IDIS; - ASS_SIEN(mpp); - } - _exitlock_spin(mpp); - } - } else { - /* Handle sleep locks */ - if ((type) & MTX_RLIKELY) - _exitlock(mpp, CURTHD, (type) & MTX_HARDOPTS); - else { - _exitlock_norecurse(mpp, CURTHD, - (type) & MTX_HARDOPTS); - } - } -} - -#endif /* KLD_MODULE */ /* Avoid namespace pollution */ #ifndef _KERN_MUTEX_C_