summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_rwlock.c49
-rw-r--r--sys/sys/rwlock.h4
2 files changed, 53 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)
{
diff --git a/sys/sys/rwlock.h b/sys/sys/rwlock.h
index d793e34..0cf1919 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)) \
OpenPOWER on IntegriCloud