vm: use atomic fetchadd in vm_page_sunbusy
This also fixes a bug where not-last unbusy failed to post a release fence. Reviewed by: markj (previous version), kib (previous version) Differential Revision: https://reviews.freebsd.org/D36084
This commit is contained in:
parent
f741319724
commit
f6ffed44a8
@ -973,27 +973,13 @@ vm_page_sunbusy(vm_page_t m)
|
|||||||
{
|
{
|
||||||
u_int x;
|
u_int x;
|
||||||
|
|
||||||
vm_page_assert_sbusied(m);
|
atomic_thread_fence_rel();
|
||||||
|
x = atomic_fetchadd_int(&m->busy_lock, -VPB_ONE_SHARER);
|
||||||
x = vm_page_busy_fetch(m);
|
KASSERT(x != VPB_FREED, ("page %p is freed", m));
|
||||||
for (;;) {
|
KASSERT(x != VPB_UNBUSIED && (x & VPB_BIT_SHARED) != 0,
|
||||||
KASSERT(x != VPB_FREED,
|
("page %p not sbusied", m));
|
||||||
("vm_page_sunbusy: Unlocking freed page."));
|
if (x == (VPB_SHARERS_WORD(1) | VPB_BIT_WAITERS))
|
||||||
if (VPB_SHARERS(x) > 1) {
|
|
||||||
if (atomic_fcmpset_int(&m->busy_lock, &x,
|
|
||||||
x - VPB_ONE_SHARER))
|
|
||||||
break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
KASSERT((x & ~VPB_BIT_WAITERS) == VPB_SHARERS_WORD(1),
|
|
||||||
("vm_page_sunbusy: invalid lock state"));
|
|
||||||
if (!atomic_fcmpset_rel_int(&m->busy_lock, &x, VPB_UNBUSIED))
|
|
||||||
continue;
|
|
||||||
if ((x & VPB_BIT_WAITERS) == 0)
|
|
||||||
break;
|
|
||||||
wakeup(m);
|
wakeup(m);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user