rwlock: don't check for curthread's read lock count in the fast path
This commit is contained in:
parent
5713e2d563
commit
41e06ccaac
@ -364,12 +364,20 @@ _rw_wunlock_cookie(volatile uintptr_t *c, const char *file, int line)
|
|||||||
* is unlocked and has no writer waiters or spinners. Failing otherwise
|
* is unlocked and has no writer waiters or spinners. Failing otherwise
|
||||||
* prioritizes writers before readers.
|
* prioritizes writers before readers.
|
||||||
*/
|
*/
|
||||||
#define RW_CAN_READ(td, _rw) \
|
static bool __always_inline
|
||||||
(((_rw) & (RW_LOCK_READ | RW_LOCK_WRITE_WAITERS | RW_LOCK_WRITE_SPINNER)) ==\
|
__rw_can_read(struct thread *td, uintptr_t v, bool fp)
|
||||||
RW_LOCK_READ || ((td)->td_rw_rlocks && (_rw) & RW_LOCK_READ))
|
{
|
||||||
|
|
||||||
|
if ((v & (RW_LOCK_READ | RW_LOCK_WRITE_WAITERS | RW_LOCK_WRITE_SPINNER))
|
||||||
|
== RW_LOCK_READ)
|
||||||
|
return (true);
|
||||||
|
if (!fp && td->td_rw_rlocks && (v & RW_LOCK_READ))
|
||||||
|
return (true);
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
static bool __always_inline
|
static bool __always_inline
|
||||||
__rw_rlock_try(struct rwlock *rw, struct thread *td, uintptr_t *vp
|
__rw_rlock_try(struct rwlock *rw, struct thread *td, uintptr_t *vp, bool fp
|
||||||
LOCK_FILE_LINE_ARG_DEF)
|
LOCK_FILE_LINE_ARG_DEF)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -383,7 +391,7 @@ __rw_rlock_try(struct rwlock *rw, struct thread *td, uintptr_t *vp
|
|||||||
* completely unlocked rwlock since such a lock is encoded
|
* completely unlocked rwlock since such a lock is encoded
|
||||||
* as a read lock with no waiters.
|
* as a read lock with no waiters.
|
||||||
*/
|
*/
|
||||||
while (RW_CAN_READ(td, *vp)) {
|
while (__rw_can_read(td, *vp, fp)) {
|
||||||
if (atomic_fcmpset_acq_ptr(&rw->rw_lock, vp,
|
if (atomic_fcmpset_acq_ptr(&rw->rw_lock, vp,
|
||||||
*vp + RW_ONE_READER)) {
|
*vp + RW_ONE_READER)) {
|
||||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||||
@ -452,7 +460,7 @@ __rw_rlock_hard(struct rwlock *rw, struct thread *td, uintptr_t v
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (__rw_rlock_try(rw, td, &v LOCK_FILE_LINE_ARG))
|
if (__rw_rlock_try(rw, td, &v, false LOCK_FILE_LINE_ARG))
|
||||||
break;
|
break;
|
||||||
#ifdef KDTRACE_HOOKS
|
#ifdef KDTRACE_HOOKS
|
||||||
lda.spin_cnt++;
|
lda.spin_cnt++;
|
||||||
@ -492,7 +500,7 @@ __rw_rlock_hard(struct rwlock *rw, struct thread *td, uintptr_t v
|
|||||||
n = RW_READERS(v);
|
n = RW_READERS(v);
|
||||||
lock_delay_spin(n);
|
lock_delay_spin(n);
|
||||||
v = RW_READ_VALUE(rw);
|
v = RW_READ_VALUE(rw);
|
||||||
if ((v & RW_LOCK_READ) == 0 || RW_CAN_READ(td, v))
|
if ((v & RW_LOCK_READ) == 0 || __rw_can_read(td, v, false))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef KDTRACE_HOOKS
|
#ifdef KDTRACE_HOOKS
|
||||||
@ -518,7 +526,7 @@ __rw_rlock_hard(struct rwlock *rw, struct thread *td, uintptr_t v
|
|||||||
* recheck its state and restart the loop if needed.
|
* recheck its state and restart the loop if needed.
|
||||||
*/
|
*/
|
||||||
v = RW_READ_VALUE(rw);
|
v = RW_READ_VALUE(rw);
|
||||||
if (RW_CAN_READ(td, v)) {
|
if (__rw_can_read(td, v, false)) {
|
||||||
turnstile_cancel(ts);
|
turnstile_cancel(ts);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -630,7 +638,7 @@ __rw_rlock_int(struct rwlock *rw LOCK_FILE_LINE_ARG_DEF)
|
|||||||
|
|
||||||
v = RW_READ_VALUE(rw);
|
v = RW_READ_VALUE(rw);
|
||||||
if (__predict_false(LOCKSTAT_OOL_PROFILE_ENABLED(rw__acquire) ||
|
if (__predict_false(LOCKSTAT_OOL_PROFILE_ENABLED(rw__acquire) ||
|
||||||
!__rw_rlock_try(rw, td, &v LOCK_FILE_LINE_ARG)))
|
!__rw_rlock_try(rw, td, &v, true LOCK_FILE_LINE_ARG)))
|
||||||
__rw_rlock_hard(rw, td, v LOCK_FILE_LINE_ARG);
|
__rw_rlock_hard(rw, td, v LOCK_FILE_LINE_ARG);
|
||||||
|
|
||||||
LOCK_LOG_LOCK("RLOCK", &rw->lock_object, 0, 0, file, line);
|
LOCK_LOG_LOCK("RLOCK", &rw->lock_object, 0, 0, file, line);
|
||||||
|
Loading…
Reference in New Issue
Block a user