diff options
author | jhb <jhb@FreeBSD.org> | 2013-06-25 18:44:15 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2013-06-25 18:44:15 +0000 |
commit | 0807c44cdd0226cdd2553f723a00de3d13882321 (patch) | |
tree | 7b07a13eb6ad28065286a3f60650edd2a6a0dc1c /sys/sys/rmlock.h | |
parent | 43efcb27b6a0f52dec7b605055f5aae35f6d41de (diff) | |
download | FreeBSD-src-0807c44cdd0226cdd2553f723a00de3d13882321.zip FreeBSD-src-0807c44cdd0226cdd2553f723a00de3d13882321.tar.gz |
Several improvements to rmlock(9). Many of these are based on patches
provided by Isilon.
- Add an rm_assert() supporting various lock assertions similar to other
locking primitives. Because rmlocks track readers the assertions are
always fully accurate unlike rw_assert() and sx_assert().
- Flesh out the lock class methods for rmlocks to support sleeping via
condvars and rm_sleep() (but only while holding write locks), rmlock
details in 'show lock' in DDB, and the lc_owner method used by
dtrace.
- Add an internal destroyed cookie so that API functions can assert
that an rmlock is not destroyed.
- Make use of rm_assert() to add various assertions to the API (e.g.
to assert locks are held when an unlock routine is called).
- Give RM_SLEEPABLE locks their own lock class and always use the
rmlock's own lock_object with WITNESS.
- Use THREAD_NO_SLEEPING() / THREAD_SLEEPING_OK() to disallow sleeping
while holding a read lock on an rmlock.
Submitted by: andre
Obtained from: EMC/Isilon
Diffstat (limited to 'sys/sys/rmlock.h')
-rw-r--r-- | sys/sys/rmlock.h | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/sys/sys/rmlock.h b/sys/sys/rmlock.h index 5a0fa8a..ed6110a 100644 --- a/sys/sys/rmlock.h +++ b/sys/sys/rmlock.h @@ -65,6 +65,10 @@ void _rm_wunlock(struct rmlock *rm); int _rm_rlock(struct rmlock *rm, struct rm_priotracker *tracker, int trylock); void _rm_runlock(struct rmlock *rm, struct rm_priotracker *tracker); +#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT) +void _rm_assert(const struct rmlock *rm, int what, const char *file, + int line); +#endif /* * Public interface for lock operations. @@ -89,6 +93,9 @@ void _rm_runlock(struct rmlock *rm, struct rm_priotracker *tracker); #define rm_try_rlock(rm,tracker) _rm_rlock((rm),(tracker), 1) #define rm_runlock(rm,tracker) _rm_runlock((rm), (tracker)) #endif +#define rm_sleep(chan, rm, pri, wmesg, timo) \ + _sleep((chan), &(rm)->lock_object, (pri), (wmesg), \ + tick_sbt * (timo), 0, C_HARDCLOCK) struct rm_args { struct rmlock *ra_rm; @@ -123,5 +130,20 @@ struct rm_args_flags { SYSUNINIT(name##_rm_sysuninit, SI_SUB_LOCK, SI_ORDER_MIDDLE, \ rm_destroy, (rm)) +#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT) +#define RA_LOCKED LA_LOCKED +#define RA_RLOCKED LA_SLOCKED +#define RA_WLOCKED LA_XLOCKED +#define RA_UNLOCKED LA_UNLOCKED +#define RA_RECURSED LA_RECURSED +#define RA_NOTRECURSED LA_NOTRECURSED +#endif + +#ifdef INVARIANTS +#define rm_assert(rm, what) _rm_assert((rm), (what), LOCK_FILE, LOCK_LINE) +#else +#define rm_assert(rm, what) +#endif + #endif /* _KERNEL */ #endif /* !_SYS_RMLOCK_H_ */ |