diff options
Diffstat (limited to 'sys/kern/kern_rwlock.c')
-rw-r--r-- | sys/kern/kern_rwlock.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index 617316b..b2469ed 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) { |