mtx: add mtx_spin_wait_unlocked

The primitive can be used to wait for the lock to be released. Intended
usage is for locks in structures which are about to be freed.

The benefit is the avoided interrupt enable/disable trip + atomic op to
grab the lock and shorter wait if the lock is held (since there is no
worry someone will contend on the lock, re-reads can be more aggressive).

Briefly discussed with:	 kib
This commit is contained in:
Mateusz Guzik 2018-02-19 00:38:14 +00:00
parent 747de77cd5
commit d257698833
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=329540
2 changed files with 19 additions and 0 deletions

View File

@ -1226,6 +1226,23 @@ _mtx_lock_indefinite_check(struct mtx *m, struct lock_delay_arg *ldap)
cpu_spinwait();
}
void
mtx_spin_wait_unlocked(struct mtx *m)
{
struct lock_delay_arg lda;
lda.spin_cnt = 0;
while (atomic_load_acq_ptr(&m->mtx_lock) != MTX_UNOWNED) {
if (__predict_true(lda.spin_cnt < 10000000)) {
cpu_spinwait();
lda.spin_cnt++;
} else {
_mtx_lock_indefinite_check(m, &lda);
}
}
}
#ifdef DDB
void
db_show_mtx(const struct lock_object *lock)

View File

@ -125,6 +125,8 @@ int __mtx_trylock_spin_flags(volatile uintptr_t *c, int opts,
const char *file, int line);
void __mtx_unlock_spin_flags(volatile uintptr_t *c, int opts,
const char *file, int line);
void mtx_spin_wait_unlocked(struct mtx *m);
#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
void __mtx_assert(const volatile uintptr_t *c, int what, const char *file,
int line);