When downgrading exclusively busied page to shared-busy state, wakeup
waiters. Otherwise, owners of the shared-busy state are left blocked and might get into a deadlock. Note that the vm_page_busy_downgrade() function is not used in the tree right now. Reported and tested by: pho (previous version) Reviewed by: alc, markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D8195
This commit is contained in:
parent
199511bcdd
commit
267ed8e2f7
@ -655,15 +655,26 @@ void
|
||||
vm_page_busy_downgrade(vm_page_t m)
|
||||
{
|
||||
u_int x;
|
||||
bool locked;
|
||||
|
||||
vm_page_assert_xbusied(m);
|
||||
locked = mtx_owned(vm_page_lockptr(m));
|
||||
|
||||
for (;;) {
|
||||
x = m->busy_lock;
|
||||
x &= VPB_BIT_WAITERS;
|
||||
if (x != 0 && !locked)
|
||||
vm_page_lock(m);
|
||||
if (atomic_cmpset_rel_int(&m->busy_lock,
|
||||
VPB_SINGLE_EXCLUSIVER | x, VPB_SHARERS_WORD(1) | x))
|
||||
VPB_SINGLE_EXCLUSIVER | x, VPB_SHARERS_WORD(1)))
|
||||
break;
|
||||
if (x != 0 && !locked)
|
||||
vm_page_unlock(m);
|
||||
}
|
||||
if (x != 0) {
|
||||
wakeup(m);
|
||||
if (!locked)
|
||||
vm_page_unlock(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user