Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102950354
D41787.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
D41787.diff
View Options
diff --git a/sys/kern/kern_rangelock.c b/sys/kern/kern_rangelock.c
--- a/sys/kern/kern_rangelock.c
+++ b/sys/kern/kern_rangelock.c
@@ -27,304 +27,335 @@
*/
#include <sys/param.h>
+#include <sys/kassert.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/rangelock.h>
-#include <sys/systm.h>
+#include <sys/sleepqueue.h>
+#include <sys/smr.h>
#include <vm/uma.h>
+/*
+ * Implementation of range locks based on the paper
+ * https://doi.org/10.1145/3342195.3387533
+ * arXiv:2006.12144v1 [cs.OS] 22 Jun 2020
+ * Scalable Range Locks for Scalable Address Spaces and Beyond
+ * by Alex Kogan, Dave Dice, and Shady Issa
+ */
+
+static struct rl_q_entry *rl_e_unmark(const struct rl_q_entry *e);
+
+/*
+ * rl_q_next links all granted ranges in the lock. We cannot free an
+ * rl_q_entry while in the smr section, and cannot reuse rl_q_next
+ * linkage since other threads might follow it even after CAS removed
+ * the range. Use rl_q_free for local list of ranges to remove after
+ * the smr section is dropped.
+ */
struct rl_q_entry {
- TAILQ_ENTRY(rl_q_entry) rl_q_link;
+ struct rl_q_entry *rl_q_next;
+ struct rl_q_entry *rl_q_free;
off_t rl_q_start, rl_q_end;
int rl_q_flags;
+#ifdef INVARIANTS
+ struct thread *rl_q_owner;
+#endif
};
static uma_zone_t rl_entry_zone;
+static smr_t rl_smr;
static void
rangelock_sys_init(void)
{
-
rl_entry_zone = uma_zcreate("rl_entry", sizeof(struct rl_q_entry),
- NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
+ NULL, NULL, NULL, NULL, UMA_ALIGNOF(struct rl_q_entry),
+ UMA_ZONE_SMR);
+ rl_smr = uma_zone_get_smr(rl_entry_zone);
}
-SYSINIT(vfs, SI_SUB_LOCK, SI_ORDER_ANY, rangelock_sys_init, NULL);
+SYSINIT(rl, SI_SUB_LOCK, SI_ORDER_ANY, rangelock_sys_init, NULL);
static struct rl_q_entry *
-rlqentry_alloc(void)
+rlqentry_alloc(vm_ooffset_t start, vm_ooffset_t end, int flags)
{
+ struct rl_q_entry *e;
+
+ e = uma_zalloc_smr(rl_entry_zone, M_WAITOK);
+ e->rl_q_next = NULL;
+ e->rl_q_free = NULL;
+ e->rl_q_start = start;
+ e->rl_q_end = end;
+ e->rl_q_flags = flags;
+#ifdef INVARIANTS
+ e->rl_q_owner = curthread;
+#endif
+ return (e);
+}
- return (uma_zalloc(rl_entry_zone, M_WAITOK));
+void
+rangelock_init(struct rangelock *lock)
+{
+ lock->sleepers = false;
+ atomic_store_ptr(&lock->head, NULL);
}
void
-rlqentry_free(struct rl_q_entry *rleq)
+rangelock_destroy(struct rangelock *lock)
{
+ struct rl_q_entry *e, *ep;
- uma_zfree(rl_entry_zone, rleq);
+ MPASS(!lock->sleepers);
+ for (e = (struct rl_q_entry *)atomic_load_ptr(&lock->head);
+ e != NULL; e = rl_e_unmark(ep)) {
+ ep = atomic_load_ptr(&e->rl_q_next);
+ uma_zfree_smr(rl_entry_zone, e);
+ }
}
-void
-rangelock_init(struct rangelock *lock)
+static bool
+rl_e_is_marked(const struct rl_q_entry *e)
{
+ return (((uintptr_t)e & 1) != 0);
+}
- TAILQ_INIT(&lock->rl_waiters);
- lock->rl_currdep = NULL;
+static struct rl_q_entry *
+rl_e_unmark(const struct rl_q_entry *e)
+{
+ MPASS(rl_e_is_marked(e));
+ return ((struct rl_q_entry *)((uintptr_t)e & ~1));
}
-void
-rangelock_destroy(struct rangelock *lock)
+static struct rl_q_entry *
+rl_q_load(struct rl_q_entry **p)
{
+ return ((struct rl_q_entry *)atomic_load_acq_ptr((uintptr_t *)p));
+}
- KASSERT(TAILQ_EMPTY(&lock->rl_waiters), ("Dangling waiters"));
+void
+rangelock_unlock(struct rangelock *lock, void *cookie)
+{
+ struct rl_q_entry *e;
+
+ e = cookie;
+ MPASS(lock != NULL && e != NULL);
+ MPASS(!rl_e_is_marked(rl_q_load(&e->rl_q_next)));
+ MPASS(e->rl_q_owner == curthread);
+
+ sleepq_lock(&lock->sleepers);
+#ifdef INVARIANTS
+ int r = atomic_testandset_long((uintptr_t *)&e->rl_q_next, 0);
+ MPASS(r == 0);
+#else
+ atomic_set_ptr((uintptr_t *)&e->rl_q_next, 1);
+#endif
+ lock->sleepers = false;
+ sleepq_broadcast(&lock->sleepers, SLEEPQ_SLEEP, 0, 0);
+ sleepq_release(&lock->sleepers);
}
/*
- * Two entries are compatible if their ranges do not overlap, or both
- * entries are for read.
+ * result: -1 if e1 before e2
+ * 1 if e1 after e2
+ * 0 if e1 and e2 overlap
*/
static int
-ranges_overlap(const struct rl_q_entry *e1,
- const struct rl_q_entry *e2)
+rl_e_compare(const struct rl_q_entry *e1, const struct rl_q_entry *e2)
{
-
- if (e1->rl_q_start < e2->rl_q_end && e1->rl_q_end > e2->rl_q_start)
+ if (e1 == NULL)
return (1);
+ if (e1->rl_q_start >= e2->rl_q_end)
+ return (1);
+ if (e2->rl_q_start >= e1->rl_q_end)
+ return (-1);
return (0);
}
-/*
- * Recalculate the lock->rl_currdep after an unlock.
- */
static void
-rangelock_calc_block(struct rangelock *lock)
+rl_insert_sleep(struct rangelock *lock)
{
- struct rl_q_entry *entry, *nextentry, *entry1;
-
- for (entry = lock->rl_currdep; entry != NULL; entry = nextentry) {
- nextentry = TAILQ_NEXT(entry, rl_q_link);
- if (entry->rl_q_flags & RL_LOCK_READ) {
- /* Reads must not overlap with granted writes. */
- for (entry1 = TAILQ_FIRST(&lock->rl_waiters);
- !(entry1->rl_q_flags & RL_LOCK_READ);
- entry1 = TAILQ_NEXT(entry1, rl_q_link)) {
- if (ranges_overlap(entry, entry1))
- goto out;
- }
- } else {
- /* Write must not overlap with any granted locks. */
- for (entry1 = TAILQ_FIRST(&lock->rl_waiters);
- entry1 != entry;
- entry1 = TAILQ_NEXT(entry1, rl_q_link)) {
- if (ranges_overlap(entry, entry1))
- goto out;
- }
-
- /* Move grantable write locks to the front. */
- TAILQ_REMOVE(&lock->rl_waiters, entry, rl_q_link);
- TAILQ_INSERT_HEAD(&lock->rl_waiters, entry, rl_q_link);
- }
-
- /* Grant this lock. */
- entry->rl_q_flags |= RL_LOCK_GRANTED;
- wakeup(entry);
- }
-out:
- lock->rl_currdep = entry;
+ smr_exit(rl_smr);
+ DROP_GIANT();
+ lock->sleepers = true;
+ sleepq_add(&lock->sleepers, NULL, "rangelk", 0, 0);
+ sleepq_wait(&lock->sleepers, PRI_USER);
+ PICKUP_GIANT();
+ smr_enter(rl_smr);
}
-static void
-rangelock_unlock_locked(struct rangelock *lock, struct rl_q_entry *entry,
- struct mtx *ilk, bool do_calc_block)
+static bool
+rl_q_cas(struct rl_q_entry **prev, struct rl_q_entry *old,
+ struct rl_q_entry *new)
{
-
- MPASS(lock != NULL && entry != NULL && ilk != NULL);
- mtx_assert(ilk, MA_OWNED);
-
- if (!do_calc_block) {
- /*
- * This is the case where rangelock_enqueue() has been called
- * with trylock == true and just inserted this entry in the
- * queue.
- * If rl_currdep is this entry, rl_currdep needs to
- * be set to the next entry in the rl_waiters list.
- * However, since this entry is the last entry in the
- * list, the next entry is NULL.
- */
- if (lock->rl_currdep == entry) {
- KASSERT(TAILQ_NEXT(lock->rl_currdep, rl_q_link) == NULL,
- ("rangelock_enqueue: next entry not NULL"));
- lock->rl_currdep = NULL;
- }
- } else
- KASSERT(entry != lock->rl_currdep, ("stuck currdep"));
-
- TAILQ_REMOVE(&lock->rl_waiters, entry, rl_q_link);
- if (do_calc_block)
- rangelock_calc_block(lock);
- mtx_unlock(ilk);
- if (curthread->td_rlqe == NULL)
- curthread->td_rlqe = entry;
- else
- rlqentry_free(entry);
+ return (atomic_cmpset_rel_ptr((uintptr_t *)prev, (uintptr_t)old,
+ (uintptr_t)new) != 0);
}
-void
-rangelock_unlock(struct rangelock *lock, void *cookie, struct mtx *ilk)
+static bool
+rl_insert(struct rangelock *lock, struct rl_q_entry *e, bool trylock,
+ struct rl_q_entry **free)
{
+ struct rl_q_entry *cur, *next, **prev;
+ int r;
+
+again:
+ prev = &lock->head;
+ if (rl_q_load(prev) == NULL && rl_q_cas(prev, NULL, e))
+ return (true);
+
+ for (cur = rl_q_load(prev);;) {
+ if (rl_e_is_marked(cur))
+ goto again;
+
+ if (cur != NULL) {
+ next = rl_q_load(&cur->rl_q_next);
+ if (rl_e_is_marked(next)) {
+ next = rl_e_unmark(next);
+ if (rl_q_cas(prev, cur, next)) {
+#ifdef INVARIANTS
+ cur->rl_q_owner = NULL;
+#endif
+ cur->rl_q_free = *free;
+ *free = cur;
+ }
+ cur = next;
+ continue;
+ }
+ }
- MPASS(lock != NULL && cookie != NULL && ilk != NULL);
-
- mtx_lock(ilk);
- rangelock_unlock_locked(lock, cookie, ilk, true);
-}
-
-/*
- * Unlock the sub-range of granted lock.
- */
-void *
-rangelock_unlock_range(struct rangelock *lock, void *cookie, off_t start,
- off_t end, struct mtx *ilk)
-{
- struct rl_q_entry *entry;
-
- MPASS(lock != NULL && cookie != NULL && ilk != NULL);
- entry = cookie;
- KASSERT(entry->rl_q_flags & RL_LOCK_GRANTED,
- ("Unlocking non-granted lock"));
- KASSERT(entry->rl_q_start == start, ("wrong start"));
- KASSERT(entry->rl_q_end >= end, ("wrong end"));
-
- mtx_lock(ilk);
- if (entry->rl_q_end == end) {
- rangelock_unlock_locked(lock, cookie, ilk, true);
- return (NULL);
+ r = rl_e_compare(cur, e);
+ if (r == -1) {
+ prev = &cur->rl_q_next;
+ cur = rl_q_load(prev);
+ } else if (r == 0) {
+ sleepq_lock(&lock->sleepers);
+ if (__predict_false(rl_e_is_marked(rl_q_load(
+ &cur->rl_q_next)))) {
+ sleepq_release(&lock->sleepers);
+ continue;
+ }
+ if (trylock) {
+ sleepq_release(&lock->sleepers);
+ return (false);
+ }
+ rl_insert_sleep(lock);
+ /* e is still valid */
+ goto again;
+ } else /* r == 1 */ {
+ e->rl_q_next = cur;
+ if (rl_q_cas(prev, cur, e)) {
+ atomic_thread_fence_acq();
+ return (true);
+ }
+ /* Reset rl_q_next in case we hit fast path. */
+ e->rl_q_next = NULL;
+ cur = rl_q_load(prev);
+ }
}
- entry->rl_q_end = end;
- rangelock_calc_block(lock);
- mtx_unlock(ilk);
- return (cookie);
}
-/*
- * Add the lock request to the queue of the pending requests for
- * rangelock. Sleep until the request can be granted unless trylock == true.
- */
-static void *
-rangelock_enqueue(struct rangelock *lock, off_t start, off_t end, int mode,
- struct mtx *ilk, bool trylock)
+static struct rl_q_entry *
+rangelock_lock_int(struct rangelock *lock, struct rl_q_entry *e,
+ bool trylock)
{
- struct rl_q_entry *entry;
- struct thread *td;
-
- MPASS(lock != NULL && ilk != NULL);
-
- td = curthread;
- if (td->td_rlqe != NULL) {
- entry = td->td_rlqe;
- td->td_rlqe = NULL;
- } else
- entry = rlqentry_alloc();
- MPASS(entry != NULL);
- entry->rl_q_flags = mode;
- entry->rl_q_start = start;
- entry->rl_q_end = end;
-
- mtx_lock(ilk);
- /*
- * XXXKIB TODO. Check that a thread does not try to enqueue a
- * lock that is incompatible with another request from the same
- * thread.
- */
-
- TAILQ_INSERT_TAIL(&lock->rl_waiters, entry, rl_q_link);
- /*
- * If rl_currdep == NULL, there is no entry waiting for a conflicting
- * range to be resolved, so set rl_currdep to this entry. If there is
- * no conflicting entry for this entry, rl_currdep will be set back to
- * NULL by rangelock_calc_block().
- */
- if (lock->rl_currdep == NULL)
- lock->rl_currdep = entry;
- rangelock_calc_block(lock);
- while (!(entry->rl_q_flags & RL_LOCK_GRANTED)) {
- if (trylock) {
- /*
- * For this case, the range is not actually locked
- * yet, but removal from the list requires the same
- * steps, except for not doing a rangelock_calc_block()
- * call, since rangelock_calc_block() was called above.
- */
- rangelock_unlock_locked(lock, entry, ilk, false);
- return (NULL);
- }
- msleep(entry, ilk, 0, "range", 0);
+ struct rl_q_entry *free, *x, *xp;
+ bool res;
+
+ free = NULL;
+ smr_enter(rl_smr);
+ res = rl_insert(lock, e, trylock, &free);
+ smr_exit(rl_smr);
+ MPASS(trylock || res);
+ if (!res) {
+ e->rl_q_free = free;
+ free = e;
+ e = NULL;
+ }
+ for (x = free; x != NULL; x = xp) {
+ MPASS(!rl_e_is_marked(x));
+ xp = x->rl_q_free;
+ MPASS(!rl_e_is_marked(xp));
+ uma_zfree_smr(rl_entry_zone, x);
}
- mtx_unlock(ilk);
- return (entry);
+ return (e);
}
void *
-rangelock_rlock(struct rangelock *lock, off_t start, off_t end, struct mtx *ilk)
+rangelock_rlock(struct rangelock *lock, vm_ooffset_t start, vm_ooffset_t end)
{
+ struct rl_q_entry *e;
- return (rangelock_enqueue(lock, start, end, RL_LOCK_READ, ilk, false));
+ e = rlqentry_alloc(start, end, RL_LOCK_READ);
+ return (rangelock_lock_int(lock, e, false));
}
void *
-rangelock_tryrlock(struct rangelock *lock, off_t start, off_t end,
- struct mtx *ilk)
+rangelock_tryrlock(struct rangelock *lock, vm_ooffset_t start, vm_ooffset_t end)
{
+ struct rl_q_entry *e;
- return (rangelock_enqueue(lock, start, end, RL_LOCK_READ, ilk, true));
+ e = rlqentry_alloc(start, end, RL_LOCK_READ);
+ return (rangelock_lock_int(lock, e, true));
}
void *
-rangelock_wlock(struct rangelock *lock, off_t start, off_t end, struct mtx *ilk)
+rangelock_wlock(struct rangelock *lock, vm_ooffset_t start, vm_ooffset_t end)
{
+ struct rl_q_entry *e;
- return (rangelock_enqueue(lock, start, end, RL_LOCK_WRITE, ilk, false));
+ e = rlqentry_alloc(start, end, RL_LOCK_WRITE);
+ return (rangelock_lock_int(lock, e, true));
}
void *
-rangelock_trywlock(struct rangelock *lock, off_t start, off_t end,
- struct mtx *ilk)
+rangelock_trywlock(struct rangelock *lock, vm_ooffset_t start, vm_ooffset_t end)
{
+ struct rl_q_entry *e;
- return (rangelock_enqueue(lock, start, end, RL_LOCK_WRITE, ilk, true));
+ e = rlqentry_alloc(start, end, RL_LOCK_WRITE);
+ return (rangelock_lock_int(lock, e, true));
}
#ifdef INVARIANT_SUPPORT
void
_rangelock_cookie_assert(void *cookie, int what, const char *file, int line)
{
- struct rl_q_entry *entry;
- int flags;
-
- MPASS(cookie != NULL);
- entry = cookie;
- flags = entry->rl_q_flags;
- switch (what) {
- case RCA_LOCKED:
- if ((flags & RL_LOCK_GRANTED) == 0)
- panic("rangelock not held @ %s:%d\n", file, line);
- break;
- case RCA_RLOCKED:
- if ((flags & (RL_LOCK_GRANTED | RL_LOCK_READ)) !=
- (RL_LOCK_GRANTED | RL_LOCK_READ))
- panic("rangelock not rlocked @ %s:%d\n", file, line);
- break;
- case RCA_WLOCKED:
- if ((flags & (RL_LOCK_GRANTED | RL_LOCK_WRITE)) !=
- (RL_LOCK_GRANTED | RL_LOCK_WRITE))
- panic("rangelock not wlocked @ %s:%d\n", file, line);
- break;
- default:
- panic("Unknown rangelock assertion: %d @ %s:%d", what, file,
- line);
- }
}
#endif /* INVARIANT_SUPPORT */
+
+#include "opt_ddb.h"
+#ifdef DDB
+#include <ddb/ddb.h>
+
+DB_SHOW_COMMAND(rangelock, db_show_rangelock)
+{
+ struct rangelock *lock;
+ struct rl_q_entry *e, *x;
+
+ if (!have_addr) {
+ db_printf("show rangelock addr\n");
+ return;
+ }
+
+ lock = (struct rangelock *)addr;
+ db_printf("rangelock %p sleepers %d\n", lock, lock->sleepers);
+ for (e = lock->head;;) {
+ x = rl_e_is_marked(e) ? rl_e_unmark(e) : e;
+ if (x == NULL)
+ break;
+ db_printf(" entry %p marked %d %d start %#jx end %#jx "
+ "flags %x next %p",
+ e, rl_e_is_marked(e), rl_e_is_marked(x->rl_q_next),
+ x->rl_q_start, x->rl_q_end, x->rl_q_flags, x->rl_q_next);
+#ifdef INVARIANTS
+ db_printf(" owner %p (%d)", x->rl_q_owner,
+ x->rl_q_owner != NULL ? x->rl_q_owner->td_tid : -1);
+#endif
+ db_printf("\n");
+ e = x->rl_q_next;
+ }
+}
+
+#endif /* DDB */
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -478,7 +478,6 @@
td = (struct thread *)mem;
EVENTHANDLER_DIRECT_INVOKE(thread_fini, td);
- rlqentry_free(td->td_rlqe);
turnstile_free(td->td_turnstile);
sleepq_free(td->td_sleepqueue);
umtx_thread_fini(td);
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -184,13 +184,13 @@
"Number of contig reclaims before giving up for default alloc policy");
#define shm_rangelock_unlock(shmfd, cookie) \
- rangelock_unlock(&(shmfd)->shm_rl, (cookie), &(shmfd)->shm_mtx)
+ rangelock_unlock(&(shmfd)->shm_rl, (cookie))
#define shm_rangelock_rlock(shmfd, start, end) \
- rangelock_rlock(&(shmfd)->shm_rl, (start), (end), &(shmfd)->shm_mtx)
+ rangelock_rlock(&(shmfd)->shm_rl, (start), (end))
#define shm_rangelock_tryrlock(shmfd, start, end) \
- rangelock_tryrlock(&(shmfd)->shm_rl, (start), (end), &(shmfd)->shm_mtx)
+ rangelock_tryrlock(&(shmfd)->shm_rl, (start), (end))
#define shm_rangelock_wlock(shmfd, start, end) \
- rangelock_wlock(&(shmfd)->shm_rl, (start), (end), &(shmfd)->shm_mtx)
+ rangelock_wlock(&(shmfd)->shm_rl, (start), (end))
static int
uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio)
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2180,8 +2180,6 @@
VNASSERT(bo->bo_dirty.bv_cnt == 0, vp, ("dirtybufcnt not 0"));
VNASSERT(pctrie_is_empty(&bo->bo_dirty.bv_root), vp,
("dirty blk trie not empty"));
- VNASSERT(TAILQ_EMPTY(&vp->v_rl.rl_waiters), vp,
- ("Dangling rangelock waiters"));
VNASSERT((vp->v_iflag & (VI_DOINGINACT | VI_OWEINACT)) == 0, vp,
("Leaked inactivation"));
VI_UNLOCK(vp);
diff --git a/sys/sys/rangelock.h b/sys/sys/rangelock.h
--- a/sys/sys/rangelock.h
+++ b/sys/sys/rangelock.h
@@ -29,12 +29,14 @@
#ifndef _SYS_RANGELOCK_H
#define _SYS_RANGELOCK_H
-#include <sys/queue.h>
+#include <sys/types.h>
+#ifndef _KERNEL
+#include <stdbool.h>
+#endif
#define RL_LOCK_READ 0x0001
#define RL_LOCK_WRITE 0x0002
#define RL_LOCK_TYPE_MASK 0x0003
-#define RL_LOCK_GRANTED 0x0004
struct rl_q_entry;
@@ -44,42 +46,25 @@
* all existing lock owners are compatible with the request. Two lock
* owners are compatible if their ranges do not overlap, or both
* owners are for read.
- *
- * Access to the structure itself is synchronized with the externally
- * supplied mutex.
- *
- * rl_waiters is the queue containing in order (a) granted write lock
- * requests, (b) granted read lock requests, and (c) in order of arrival,
- * lock requests which cannot be granted yet.
- *
- * rl_currdep is the first lock request that cannot be granted now due
- * to the preceding requests conflicting with it (i.e., it points to
- * position (c) in the list above).
*/
struct rangelock {
- TAILQ_HEAD(, rl_q_entry) rl_waiters;
- struct rl_q_entry *rl_currdep;
+ struct rl_q_entry *head;
+ bool sleepers;
};
#ifdef _KERNEL
-struct mtx;
-
void rangelock_init(struct rangelock *lock);
void rangelock_destroy(struct rangelock *lock);
-void rangelock_unlock(struct rangelock *lock, void *cookie,
- struct mtx *ilk);
-void *rangelock_unlock_range(struct rangelock *lock, void *cookie,
- off_t start, off_t end, struct mtx *ilk);
-void *rangelock_rlock(struct rangelock *lock, off_t start, off_t end,
- struct mtx *ilk);
-void *rangelock_tryrlock(struct rangelock *lock, off_t start, off_t end,
- struct mtx *ilk);
-void *rangelock_wlock(struct rangelock *lock, off_t start, off_t end,
- struct mtx *ilk);
-void *rangelock_trywlock(struct rangelock *lock, off_t start, off_t end,
- struct mtx *ilk);
-void rlqentry_free(struct rl_q_entry *rlqe);
+void rangelock_unlock(struct rangelock *lock, void *cookie);
+void *rangelock_rlock(struct rangelock *lock, vm_ooffset_t start,
+ vm_ooffset_t end);
+void *rangelock_tryrlock(struct rangelock *lock, vm_ooffset_t start,
+ vm_ooffset_t end);
+void *rangelock_wlock(struct rangelock *lock, vm_ooffset_t start,
+ vm_ooffset_t end);
+void *rangelock_trywlock(struct rangelock *lock, vm_ooffset_t start,
+ vm_ooffset_t end);
#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
void _rangelock_cookie_assert(void *cookie, int what, const char *file,
int line);
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -833,18 +833,15 @@
#define vn_seqc_consistent(vp, seq) seqc_consistent(&(vp)->v_seqc, seq)
#define vn_rangelock_unlock(vp, cookie) \
- rangelock_unlock(&(vp)->v_rl, (cookie), VI_MTX(vp))
-#define vn_rangelock_unlock_range(vp, cookie, start, end) \
- rangelock_unlock_range(&(vp)->v_rl, (cookie), (start), (end), \
- VI_MTX(vp))
+ rangelock_unlock(&(vp)->v_rl, (cookie))
#define vn_rangelock_rlock(vp, start, end) \
- rangelock_rlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
+ rangelock_rlock(&(vp)->v_rl, (start), (end))
#define vn_rangelock_tryrlock(vp, start, end) \
- rangelock_tryrlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
+ rangelock_tryrlock(&(vp)->v_rl, (start), (end))
#define vn_rangelock_wlock(vp, start, end) \
- rangelock_wlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
+ rangelock_wlock(&(vp)->v_rl, (start), (end))
#define vn_rangelock_trywlock(vp, start, end) \
- rangelock_trywlock(&(vp)->v_rl, (start), (end), VI_MTX(vp))
+ rangelock_trywlock(&(vp)->v_rl, (start), (end))
#define vn_irflag_read(vp) atomic_load_short(&(vp)->v_irflag)
void vn_irflag_set_locked(struct vnode *vp, short toset);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 20, 2:54 AM (21 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14723951
Default Alt Text
D41787.diff (20 KB)
Attached To
Mode
D41787: Reimplement rangelocks
Attached
Detach File
Event Timeline
Log In to Comment