diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2022-08-17 16:24:14 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2022-08-17 16:24:14 +0000 |
commit | 1b89d40fbf7788c75a7612b22b1dba1612e45c9a (patch) | |
tree | b07f802e2d686d257a176d01f8a4f3c86b37c25a | |
parent | e674ddec0b4138274539587fe9336b577ff1242a (diff) | |
download | src-1b89d40fbf7788c75a7612b22b1dba1612e45c9a.tar.gz src-1b89d40fbf7788c75a7612b22b1dba1612e45c9a.zip |
Revert "vm: use atomic fetchadd in vm_page_sunbusy"
This reverts commit f6ffed44a8eb5d1ab89a18e60fb056aab2105be7.
fetchadd will fail the waiters flag, which can cause other
code to wait when it should not with nothing clear it
Revert until I sort this out.
Reported by: markj
-rw-r--r-- | sys/vm/vm_page.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index defcebb286ae..e7500e9d3e71 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -973,13 +973,27 @@ vm_page_sunbusy(vm_page_t m) { u_int x; - atomic_thread_fence_rel(); - x = atomic_fetchadd_int(&m->busy_lock, -VPB_ONE_SHARER); - KASSERT(x != VPB_FREED, ("page %p is freed", m)); - KASSERT(x != VPB_UNBUSIED && (x & VPB_BIT_SHARED) != 0, - ("page %p not sbusied", m)); - if (x == (VPB_SHARERS_WORD(1) | VPB_BIT_WAITERS)) + vm_page_assert_sbusied(m); + + x = vm_page_busy_fetch(m); + for (;;) { + KASSERT(x != VPB_FREED, + ("vm_page_sunbusy: Unlocking freed page.")); + 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); + break; + } } /* |