diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index 617316b53650..b2469edde1ea 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -203,6 +203,30 @@ _rw_wlock(struct rwlock *rw, const char *file, int line) curthread->td_locks++; } +int +_rw_try_wlock(struct rwlock *rw, const char *file, int line) +{ + int rval; + + KASSERT(rw->rw_lock != RW_DESTROYED, + ("rw_try_wlock() of destroyed rwlock @ %s:%d", file, line)); + + if (rw_wlocked(rw) && (rw->lock_object.lo_flags & RW_RECURSE) != 0) { + rw->rw_recurse++; + rval = 1; + } else + rval = atomic_cmpset_acq_ptr(&rw->rw_lock, RW_UNLOCKED, + (uintptr_t)curthread); + + LOCK_LOG_TRY("WLOCK", &rw->lock_object, 0, rval, file, line); + if (rval) { + WITNESS_LOCK(&rw->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK, + file, line); + curthread->td_locks++; + } + return (rval); +} + void _rw_wunlock(struct rwlock *rw, const char *file, int line) { @@ -386,6 +410,31 @@ _rw_rlock(struct rwlock *rw, const char *file, int line) curthread->td_rw_rlocks++; } +int +_rw_try_rlock(struct rwlock *rw, const char *file, int line) +{ + uintptr_t x; + + for (;;) { + x = rw->rw_lock; + KASSERT(rw->rw_lock != RW_DESTROYED, + ("rw_try_rlock() of destroyed rwlock @ %s:%d", file, line)); + if (!(x & RW_LOCK_READ)) + break; + if (atomic_cmpset_acq_ptr(&rw->rw_lock, x, x + RW_ONE_READER)) { + LOCK_LOG_TRY("RLOCK", &rw->lock_object, 0, 1, file, + line); + WITNESS_LOCK(&rw->lock_object, LOP_TRYLOCK, file, line); + curthread->td_locks++; + curthread->td_rw_rlocks++; + return (1); + } + } + + LOCK_LOG_TRY("RLOCK", &rw->lock_object, 0, 0, file, line); + return (0); +} + void _rw_runlock(struct rwlock *rw, const char *file, int line) { diff --git a/sys/sys/rwlock.h b/sys/sys/rwlock.h index d793e341a207..0cf1919101b9 100644 --- a/sys/sys/rwlock.h +++ b/sys/sys/rwlock.h @@ -132,8 +132,10 @@ void rw_destroy(struct rwlock *rw); void rw_sysinit(void *arg); int rw_wowned(struct rwlock *rw); void _rw_wlock(struct rwlock *rw, const char *file, int line); +int _rw_try_wlock(struct rwlock *rw, const char *file, int line); void _rw_wunlock(struct rwlock *rw, const char *file, int line); void _rw_rlock(struct rwlock *rw, const char *file, int line); +int _rw_try_rlock(struct rwlock *rw, const char *file, int line); void _rw_runlock(struct rwlock *rw, const char *file, int line); void _rw_wlock_hard(struct rwlock *rw, uintptr_t tid, const char *file, int line); @@ -165,7 +167,9 @@ void _rw_assert(struct rwlock *rw, int what, const char *file, int line); #endif #define rw_rlock(rw) _rw_rlock((rw), LOCK_FILE, LOCK_LINE) #define rw_runlock(rw) _rw_runlock((rw), LOCK_FILE, LOCK_LINE) +#define rw_try_rlock(rw) _rw_try_rlock((rw), LOCK_FILE, LOCK_LINE) #define rw_try_upgrade(rw) _rw_try_upgrade((rw), LOCK_FILE, LOCK_LINE) +#define rw_try_wlock(rw) _rw_try_wlock((rw), LOCK_FILE, LOCK_LINE) #define rw_downgrade(rw) _rw_downgrade((rw), LOCK_FILE, LOCK_LINE) #define rw_unlock(rw) do { \ if (rw_wowned(rw)) \